From 0c57a9cbb495d7d152e60068b28d21926b1ba7af Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 9 Feb 2022 21:03:44 +0000 Subject: [PATCH 001/187] Initial checkin for exclude objects regex. --- docs/userguide/coverage.md | 11 +- source/api/ut.pkb | 175 ++++++++++++++++++---- source/api/ut.pks | 72 +++++++-- source/api/ut_runner.pkb | 14 +- source/api/ut_runner.pks | 6 +- source/core/coverage/ut_coverage.pkb | 33 +++- source/core/types/ut_coverage_options.tpb | 13 +- source/core/types/ut_coverage_options.tps | 10 +- 8 files changed, 278 insertions(+), 56 deletions(-) diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 8951b3621..59baf5a04 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -128,16 +128,19 @@ exec ut.run('unit_test_schema', ut_coverage_html_reporter(), a_coverage_schemes #### Filtering objects in coverage reports -There are two options that can be used to narrow down the scope of coverage report: -- `a_include_objects` - list of `[object_owner.].object_name` to be included in the coverage report +There are six options that can be used to narrow down the scope of coverage report: +- `a_include_objects` - list of `[object_owner.].object_name` to be included in the coverage report. - `a_exclude_objects` - list of `[object_owner.].object_name` to be excluded from the coverage report +- `a_include_schema_expr` - string of regex expression of schemas to be included in the coverage report. It will override `a_include_objects` +- `a_include_object_expr` - string of regex expression of objects ( no schema names included ) to be included in the coverage report. It will override `a_include_objects` +- `a_exclude_schema_expr` - string of regex expression of schemas to be excluded from the coverage report. It will override `a_exclude_objects` +- `a_exclude_object_expr` - string of regex expression of objects to be excluded from the coverage report. It will override `a_exclude_objects` -You may specify both _include_ and _exclude_ object lists to gain more control over what needs to be included / excluded from the coverage report. +You may specify both _include_ and _exclude_ options to gain more control over what needs to be included / excluded from the coverage report. The object owner is optional in the object list. If you do not provide an object owner, the _include_/_exclude_ list will be considered for every schema used for coverage gathering (as described above). - Example: Limiting coverage by object name, for tested code located in the same schema as the unit tests. ```sql exec ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_include_objects=>ut_varchar2_list('award_bonus')); diff --git a/source/api/ut.pkb b/source/api/ut.pkb index ee3d85342..5c91e54d4 100644 --- a/source/api/ut.pkb +++ b/source/api/ut.pkb @@ -131,7 +131,11 @@ create or replace package body ut is a_client_character_set varchar2, a_random_test_order integer, a_random_test_order_seed positive, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is pragma autonomous_transaction; begin @@ -150,7 +154,11 @@ create or replace package body ut is false, ut_utils.int_to_boolean(a_random_test_order), a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); rollback; end; @@ -167,10 +175,15 @@ create or replace package body ut is a_client_character_set varchar2, a_random_test_order integer, a_random_test_order_seed positive, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is pragma autonomous_transaction; begin + a_reporter := coalesce(a_reporter,ut_documentation_reporter()); ut_runner.run( a_paths, @@ -186,7 +199,11 @@ create or replace package body ut is false, ut_utils.int_to_boolean(a_random_test_order), a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); rollback; end; @@ -227,7 +244,11 @@ create or replace package body ut is a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined is l_reporter ut_reporter_base := a_reporter; l_results sys_refcursor; @@ -244,7 +265,11 @@ create or replace package body ut is a_client_character_set, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); @@ -266,7 +291,11 @@ create or replace package body ut is a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined is l_reporter ut_reporter_base := a_reporter; l_results sys_refcursor; @@ -283,7 +312,11 @@ create or replace package body ut is a_client_character_set, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); @@ -306,7 +339,11 @@ create or replace package body ut is a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined is l_reporter ut_reporter_base := a_reporter; l_results sys_refcursor; @@ -323,7 +360,11 @@ create or replace package body ut is a_client_character_set, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); @@ -346,7 +387,11 @@ create or replace package body ut is a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined is l_reporter ut_reporter_base := a_reporter; l_results sys_refcursor; @@ -363,7 +408,11 @@ create or replace package body ut is a_client_character_set, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); @@ -386,7 +435,11 @@ create or replace package body ut is a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined is l_reporter ut_reporter_base := a_reporter; l_results sys_refcursor; @@ -403,7 +456,11 @@ create or replace package body ut is a_client_character_set, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); @@ -426,7 +483,11 @@ create or replace package body ut is a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined is l_reporter ut_reporter_base := a_reporter; l_results sys_refcursor; @@ -443,7 +504,11 @@ create or replace package body ut is a_client_character_set, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); @@ -467,7 +532,11 @@ create or replace package body ut is a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is l_reporter ut_reporter_base := a_reporter; begin @@ -487,7 +556,11 @@ create or replace package body ut is a_force_manual_rollback, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); else run_autonomous( @@ -502,7 +575,11 @@ create or replace package body ut is a_client_character_set, ut_utils.boolean_to_int(a_random_test_order), a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); end if; if l_reporter is of (ut_output_reporter_base) then @@ -524,7 +601,11 @@ create or replace package body ut is a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is l_reporter ut_reporter_base := a_reporter; begin @@ -541,7 +622,11 @@ create or replace package body ut is a_force_manual_rollback, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); end; @@ -557,7 +642,11 @@ create or replace package body ut is a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is begin ut.run( @@ -573,7 +662,11 @@ create or replace package body ut is a_force_manual_rollback, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); end; @@ -589,7 +682,11 @@ create or replace package body ut is a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is begin ut.run( @@ -605,7 +702,11 @@ create or replace package body ut is a_force_manual_rollback, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); end; @@ -622,7 +723,11 @@ create or replace package body ut is a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is begin ut.run( @@ -638,7 +743,11 @@ create or replace package body ut is a_force_manual_rollback, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); end; @@ -655,7 +764,11 @@ create or replace package body ut is a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is begin ut.run( @@ -671,7 +784,11 @@ create or replace package body ut is a_force_manual_rollback, a_random_test_order, a_random_test_order_seed, - a_tags + a_tags, + a_include_schema_expr, + a_include_object_expr, + a_exclude_schema_expr, + a_exclude_object_expr ); end; diff --git a/source/api/ut.pks b/source/api/ut.pks index df5a8d8e5..f72c82a0c 100644 --- a/source/api/ut.pks +++ b/source/api/ut.pks @@ -62,7 +62,11 @@ create or replace package ut authid current_user as a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined; function run( @@ -76,7 +80,11 @@ create or replace package ut authid current_user as a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined; function run( @@ -91,7 +99,11 @@ create or replace package ut authid current_user as a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined; function run( @@ -106,7 +118,11 @@ create or replace package ut authid current_user as a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined; function run( @@ -121,7 +137,11 @@ create or replace package ut authid current_user as a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined; function run( @@ -136,7 +156,11 @@ create or replace package ut authid current_user as a_client_character_set varchar2 := null, a_random_test_order integer := 0, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) return ut_varchar2_rows pipelined; procedure run( @@ -151,7 +175,11 @@ create or replace package ut authid current_user as a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ); procedure run( @@ -166,7 +194,11 @@ create or replace package ut authid current_user as a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ); procedure run( @@ -182,7 +214,11 @@ create or replace package ut authid current_user as a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ); procedure run( @@ -198,7 +234,11 @@ create or replace package ut authid current_user as a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ); procedure run( @@ -214,7 +254,11 @@ create or replace package ut authid current_user as a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ); procedure run( @@ -230,7 +274,11 @@ create or replace package ut authid current_user as a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ); /** diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index d2bd74b91..af168fe5d 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -69,7 +69,11 @@ create or replace package body ut_runner is a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ) is l_run ut_run; l_coverage_schema_names ut_varchar2_rows; @@ -120,7 +124,6 @@ create or replace package body ut_runner is ut_utils.trim_list_elements(ut_utils.filter_list(ut_utils.string_to_table(a_tags,','),ut_utils.gc_word_no_space)) ); end if; - l_run := ut_run( a_run_paths => l_paths, a_coverage_options => ut_coverage_options( @@ -128,7 +131,11 @@ create or replace package body ut_runner is schema_names => l_coverage_schema_names, exclude_objects => ut_utils.convert_collection(a_exclude_objects), include_objects => ut_utils.convert_collection(a_include_objects), - file_mappings => set(a_source_file_mappings) + file_mappings => set(a_source_file_mappings), + include_schema_expr => a_include_schema_expr, + include_object_expr => a_include_object_expr, + exclude_schema_expr => a_exclude_schema_expr, + exclude_object_expr => a_exclude_object_expr ), a_test_file_mappings => set(a_test_file_mappings), a_client_character_set => a_client_character_set, @@ -142,7 +149,6 @@ create or replace package body ut_runner is end if; l_run.do_execute(); - finish_run(l_run, a_force_manual_rollback); exception when others then diff --git a/source/api/ut_runner.pks b/source/api/ut_runner.pks index 75aa12f8f..3170dedee 100644 --- a/source/api/ut_runner.pks +++ b/source/api/ut_runner.pks @@ -71,7 +71,11 @@ create or replace package ut_runner authid current_user is a_force_manual_rollback boolean := false, a_random_test_order boolean := false, a_random_test_order_seed positive := null, - a_tags varchar2 := null + a_tags varchar2 := null, + a_include_schema_expr varchar2 := null, + a_include_object_expr varchar2 := null, + a_exclude_schema_expr varchar2 := null, + a_exclude_object_expr varchar2 := null ); /** diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index ddcdeaf2e..b3667bb26 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -30,11 +30,12 @@ create or replace package body ut_coverage is end; function get_cov_sources_sql(a_coverage_options ut_coverage_options, a_skip_objects ut_object_names) return varchar2 is - l_result varchar2(32767); + l_result varchar2(32767); --QUESTION: Given fact that we can pass large regex filters same as objects filter should we consider a clob ? l_full_name varchar2(32767); l_join_mappings varchar2(32767); l_filters varchar2(32767); l_mappings_cardinality integer := 0; + l_regex_exc_filters varchar2(32767); begin l_result := q'[ with @@ -82,8 +83,9 @@ create or replace package body ut_coverage is -- Exclude calls to utPLSQL framework, Unit Test packages and objects from a_exclude_list parameter of coverage reporter where (s.owner, s.name) not in ( select /*+ cardinality(el {skipped_objects_cardinality})*/el.owner, el.name from table(:l_skipped_objects) el ) and line > 0 + {regex_filters} ]'; - + if a_coverage_options.file_mappings is not empty then l_mappings_cardinality := ut_utils.scale_cardinality(cardinality(a_coverage_options.file_mappings)); l_full_name := 'f.file_name'; @@ -92,6 +94,15 @@ create or replace package body ut_coverage is on s.name = f.object_name and s.type = f.object_type and s.owner = f.object_owner'; + elsif a_coverage_options.include_schema_expr is not null or a_coverage_options.include_object_expr is not null then + l_full_name := q'[lower(s.type||' '||s.owner||'.'||s.name)]'; + if a_coverage_options.include_schema_expr is not null then + l_filters := q'[and regexp_like(s.owner,']'||a_coverage_options.include_schema_expr||q'[','i')]'; + end if; + + if a_coverage_options.include_object_expr is not null then + l_filters := l_filters|| q'[ and regexp_like(s.name,']'||a_coverage_options.include_object_expr||q'[','i')]'; + end if; else l_full_name := q'[lower(s.type||' '||s.owner||'.'||s.name)]'; l_filters := case @@ -109,13 +120,27 @@ create or replace package body ut_coverage is end; end if; + + if a_coverage_options.exclude_schema_expr is not null then + l_regex_exc_filters := l_regex_exc_filters||q'[and not regexp_like(s.owner,']'||a_coverage_options.exclude_schema_expr||q'[,'i') + ]'; + end if; + + if a_coverage_options.exclude_object_expr is not null then + l_regex_exc_filters := l_regex_exc_filters||q'[and not regexp_like(s.name,']'||a_coverage_options.exclude_object_expr||q'[,'i') + ]'; + end if; + + + l_result := replace(l_result, '{sources_view}', ut_metadata.get_source_view_name()); l_result := replace(l_result, '{l_full_name}', l_full_name); l_result := replace(l_result, '{join_file_mappings}', l_join_mappings); l_result := replace(l_result, '{filters}', l_filters); l_result := replace(l_result, '{mappings_cardinality}', l_mappings_cardinality); l_result := replace(l_result, '{skipped_objects_cardinality}', ut_utils.scale_cardinality(cardinality(a_skip_objects))); - + l_result := replace(l_result, '{regex_filters}', l_regex_exc_filters); + return l_result; end; @@ -138,6 +163,8 @@ create or replace package body ut_coverage is open l_cursor for l_sql using a_coverage_options.file_mappings, l_skip_objects; elsif a_coverage_options.include_objects is not empty then open l_cursor for l_sql using a_coverage_options.include_objects, a_coverage_options.include_objects, l_skip_objects; + elsif a_coverage_options.include_schema_expr is not null or a_coverage_options.include_object_expr is not null then + open l_cursor for l_sql using l_skip_objects; else open l_cursor for l_sql using a_coverage_options.schema_names, a_coverage_options.schema_names, l_skip_objects; end if; diff --git a/source/core/types/ut_coverage_options.tpb b/source/core/types/ut_coverage_options.tpb index 308c75553..a091802af 100644 --- a/source/core/types/ut_coverage_options.tpb +++ b/source/core/types/ut_coverage_options.tpb @@ -22,7 +22,11 @@ create or replace type body ut_coverage_options as schema_names ut_varchar2_rows := null, exclude_objects ut_varchar2_rows := null, include_objects ut_varchar2_rows := null, - file_mappings ut_file_mappings := null + file_mappings ut_file_mappings := null, + include_schema_expr varchar2 := null, + include_object_expr varchar2 := null, + exclude_schema_expr varchar2 := null, + exclude_object_expr varchar2 := null ) return self as result is function to_ut_object_list(a_names ut_varchar2_rows, a_schema_names ut_varchar2_rows) return ut_object_names is l_result ut_object_names; @@ -54,10 +58,15 @@ create or replace type body ut_coverage_options as if exclude_objects is not empty then self.exclude_objects := to_ut_object_list(exclude_objects, self.schema_names); end if; --- self.exclude_objects := self.exclude_objects multiset union all ut_suite_manager.get_schema_ut_packages(schema_names); self.include_objects := to_ut_object_list(include_objects, self.schema_names); + self.include_schema_expr := include_schema_expr; + self.include_object_expr := include_object_expr; + self.exclude_schema_expr := exclude_schema_expr; + self.exclude_object_expr := exclude_object_expr; + + return; end; end; diff --git a/source/core/types/ut_coverage_options.tps b/source/core/types/ut_coverage_options.tps index 1be518c5e..245539179 100644 --- a/source/core/types/ut_coverage_options.tps +++ b/source/core/types/ut_coverage_options.tps @@ -21,13 +21,21 @@ create or replace type ut_coverage_options force as object ( exclude_objects ut_object_names, include_objects ut_object_names, file_mappings ut_file_mappings, + include_schema_expr varchar2(32767), + include_object_expr varchar2(32767), + exclude_schema_expr varchar2(32767), + exclude_object_expr varchar2(32767), constructor function ut_coverage_options( self in out nocopy ut_coverage_options, coverage_run_id raw, schema_names ut_varchar2_rows := null, exclude_objects ut_varchar2_rows := null, include_objects ut_varchar2_rows := null, - file_mappings ut_file_mappings := null + file_mappings ut_file_mappings := null, + include_schema_expr varchar2 := null, + include_object_expr varchar2 := null, + exclude_schema_expr varchar2 := null, + exclude_object_expr varchar2 := null ) return self as result ) / From 8370aa98ee48c2a2d4dc5f6cacf75d519a4a6e54 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 22 Feb 2022 11:21:22 +0000 Subject: [PATCH 002/187] commit changes --- source/core/coverage/ut_coverage.pkb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index b3667bb26..93439daea 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -122,13 +122,11 @@ create or replace package body ut_coverage is if a_coverage_options.exclude_schema_expr is not null then - l_regex_exc_filters := l_regex_exc_filters||q'[and not regexp_like(s.owner,']'||a_coverage_options.exclude_schema_expr||q'[,'i') - ]'; + l_regex_exc_filters := l_regex_exc_filters||q'[ and not regexp_like(s.owner,']'||a_coverage_options.exclude_schema_expr||q'[,'i')]'; end if; if a_coverage_options.exclude_object_expr is not null then - l_regex_exc_filters := l_regex_exc_filters||q'[and not regexp_like(s.name,']'||a_coverage_options.exclude_object_expr||q'[,'i') - ]'; + l_regex_exc_filters := l_regex_exc_filters||q'[ and not regexp_like(s.name,']'||a_coverage_options.exclude_object_expr||q'[,'i')]'; end if; From 7b9e0859438765be9585de966777cd043b4932a5 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 25 Feb 2022 00:05:47 +0000 Subject: [PATCH 003/187] Making more changes --- source/core/coverage/ut_coverage.pkb | 33 +++++---- test/ut3_tester_helper/coverage_helper.pkb | 22 ++++-- .../test_coverage/test_extended_coverage.pkb | 71 +++++++++++++++++++ .../test_coverage/test_extended_coverage.pks | 16 ++++- 4 files changed, 122 insertions(+), 20 deletions(-) diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index 18d359b72..cdef6dd04 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -55,6 +55,7 @@ create or replace package body ut_coverage is from {sources_view} s {join_file_mappings} where s.type in ('PACKAGE BODY', 'TYPE BODY', 'PROCEDURE', 'FUNCTION', 'TRIGGER') {filters} + {regex_exc_filters} ), coverage_sources as ( select full_name, owner, name, type, line, text, @@ -85,7 +86,6 @@ create or replace package body ut_coverage is where s.owner = el.owner and s.name = el.name ) and line > 0 - {regex_filters} ]'; if a_coverage_options.file_mappings is not empty then @@ -99,11 +99,14 @@ create or replace package body ut_coverage is elsif a_coverage_options.include_schema_expr is not null or a_coverage_options.include_object_expr is not null then l_full_name := q'[lower(s.type||' '||s.owner||'.'||s.name)]'; if a_coverage_options.include_schema_expr is not null then - l_filters := q'[and regexp_like(s.owner,']'||a_coverage_options.include_schema_expr||q'[','i')]'; - end if; - + l_filters := q'[and regexp_like(s.owner,:a_include_schema_expr,'i')]'; + else + l_filters := 'and :a_include_schema_expr is null'; + end if; if a_coverage_options.include_object_expr is not null then - l_filters := l_filters|| q'[ and regexp_like(s.name,']'||a_coverage_options.include_object_expr||q'[','i')]'; + l_filters := l_filters|| q'[ and regexp_like(s.name,:a_include_object_expr,'i')]'; + else + l_filters := l_filters|| 'and :a_include_object_expr is null'; end if; else l_full_name := q'[lower(s.type||' '||s.owner||'.'||s.name)]'; @@ -124,11 +127,15 @@ create or replace package body ut_coverage is if a_coverage_options.exclude_schema_expr is not null then - l_regex_exc_filters := l_regex_exc_filters||q'[ and not regexp_like(s.owner,']'||a_coverage_options.exclude_schema_expr||q'[,'i')]'; + l_regex_exc_filters := q'[ and not regexp_like(s.owner,:a_exclude_schema_expr,'i')]'; + else + l_regex_exc_filters := ' and :a_exclude_schema_expr is null '; end if; if a_coverage_options.exclude_object_expr is not null then - l_regex_exc_filters := l_regex_exc_filters||q'[ and not regexp_like(s.name,']'||a_coverage_options.exclude_object_expr||q'[,'i')]'; + l_regex_exc_filters := l_regex_exc_filters||q'[ and not regexp_like(s.name,:a_exclude_obj_expr:,'i')]'; + else + l_regex_exc_filters := l_regex_exc_filters||'and :a_exclude_obj_expr is null '; end if; @@ -139,7 +146,7 @@ create or replace package body ut_coverage is l_result := replace(l_result, '{filters}', l_filters); l_result := replace(l_result, '{mappings_cardinality}', l_mappings_cardinality); l_result := replace(l_result, '{skipped_objects_cardinality}', ut_utils.scale_cardinality(cardinality(a_skip_objects))); - l_result := replace(l_result, '{regex_filters}', l_regex_exc_filters); + l_result := replace(l_result, '{regex_exc_filters}', l_regex_exc_filters); return l_result; @@ -160,13 +167,15 @@ create or replace package body ut_coverage is ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_key_anyvalues().put('l_sql',l_sql) ); if a_coverage_options.file_mappings is not empty then - open l_cursor for l_sql using a_coverage_options.file_mappings, l_skip_objects; + open l_cursor for l_sql using a_coverage_options.file_mappings,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; elsif a_coverage_options.include_objects is not empty then - open l_cursor for l_sql using a_coverage_options.include_objects, l_skip_objects; + open l_cursor for l_sql using a_coverage_options.include_objects,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; elsif a_coverage_options.include_schema_expr is not null or a_coverage_options.include_object_expr is not null then - open l_cursor for l_sql using l_skip_objects; + open l_cursor for l_sql using a_coverage_options.include_schema_expr,a_coverage_options.include_object_expr, + a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr, + l_skip_objects; else - open l_cursor for l_sql using a_coverage_options.schema_names, l_skip_objects; + open l_cursor for l_sql using a_coverage_options.schema_names,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; end if; return l_cursor; end; diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index 4be062645..bbf288ed4 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -200,14 +200,14 @@ create or replace package body coverage_helper is begin execute immediate q'[drop package ut3_develop.test_regex_dummy_cov]'; exception when others then null; end; end; - procedure create_regex_dummy_cov_schema is + procedure create_regex_dummy_for_schema(p_schema in varchar2) is pragma autonomous_transaction; begin - execute immediate q'[create or replace package ut3_develop.]'||covered_package_name||q'[ is + execute immediate q'[create or replace package ]'||p_schema||q'[.regex_dummy_cov_schema is procedure do_stuff(i_input in number); end;]'; - execute immediate q'[create or replace package body ut3_develop.]'||covered_package_name||q'[ is + execute immediate q'[create or replace package body ]'||p_schema||q'[.regex_dummy_cov_schema is procedure do_stuff(i_input in number) is begin if i_input = 2 then dbms_output.put_line('should not get here'); elsif i_input = 1 then dbms_output.put_line('should get here'); @@ -217,7 +217,7 @@ create or replace package body coverage_helper is end; end;]'; - execute immediate q'[create or replace package ut3_develop.test_dummy_coverage is + execute immediate q'[create or replace package ]'||p_schema||q'[.test_regex_dummy_cov_schema is --%suite(dummy coverage test) --%suitepath(coverage_testing) @@ -228,10 +228,10 @@ create or replace package body coverage_helper is procedure zero_coverage; end;]'; - execute immediate q'[create or replace package body ut3_develop.test_dummy_coverage is + execute immediate q'[create or replace package body ]'||p_schema||q'[.test_regex_dummy_cov_schema is procedure test_do_stuff is begin - ]'||covered_package_name||q'[.do_stuff(1); + regex_dummy_cov_schema.do_stuff(1); ut.expect(1).to_equal(1); end; procedure zero_coverage is @@ -241,11 +241,19 @@ create or replace package body coverage_helper is end;]'; end; + procedure create_regex_dummy_cov_schema is + begin + create_regex_dummy_for_schema('ut3_develop'); + create_regex_dummy_for_schema('ut3_tester_helper'); + end; + procedure drop_regex_dummy_cov_schema is pragma autonomous_transaction; begin - begin execute immediate q'[drop package ut3_helper.regex_dummy_cov_schema]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_develop.regex_dummy_cov_schema]'; exception when others then null; end; begin execute immediate q'[drop package ut3_develop.test_regex_dummy_cov_schema]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_tester_helper.regex_dummy_cov_schema]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_tester_helper.test_regex_dummy_cov_schema]'; exception when others then null; end; end; diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb index a8d104e28..5aea2e184 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb @@ -106,5 +106,76 @@ create or replace package body test_extended_coverage is ut.expect(l_actual).to_be_like(l_expected); end; + procedure coverage_regex_include_schema is + l_expected_ut3 clob; + l_expected_help clob; + l_actual_ut3 clob; + l_actual_help clob; + l_actual_both clob; + + begin + --Arrange + l_expected_ut3 := '%' || + '%%'; + l_expected_help := '%' || + '%%'; + --Act + l_actual_ut3 := + ut3_tester_helper.coverage_helper.run_tests_as_job( + q'[ + ut3_develop.ut.run( + a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov_schema', 'ut3_tester_helper.test_regex_dummy_cov_schema'), + a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), + a_include_schema_expr => '^ut3_develop' + ) + ]' + ); + /* + l_actual_help := + ut3_tester_helper.coverage_helper.run_tests_as_job( + q'[ + ut3_develop.ut.run( + a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov_schema', 'ut3_tester_helper.test_regex_dummy_cov_schema'), + a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), + a_include_schema_expr => '^ut3_tester_helper' + ) + ]' + ); + + l_actual_both := + ut3_tester_helper.coverage_helper.run_tests_as_job( + q'[ + ut3_develop.ut.run( + a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov_schema', 'ut3_tester_helper.test_regex_dummy_cov_schema'), + a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), + a_include_schema_expr => '^ut3_tester_helper||^ut3_tester_helper' + ) + ]' + ); + */ + --Assert + ut.expect(l_actual_ut3).to_be_like(l_expected_ut3); + ut.expect(l_actual_ut3).not_to_be_like(l_expected_help); + --ut.expect(l_actual_help).to_be_like(l_expected_help); + --ut.expect(l_actual_help).not_to_be_like(l_expected_ut3); + --ut.expect(l_actual_both).to_be_like(l_expected_ut3); + --ut.expect(l_actual_both).to_be_like(l_expected_help); + end; + + procedure coverage_regex_include_object is + begin + null; + end; + + procedure coverage_regex_exclude_schema is + begin + null; + end; + + procedure coverage_regex_exclude_object is + begin + null; + end; + end; / diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks index c575c240c..a8c71f442 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks @@ -17,6 +17,20 @@ create or replace package test_extended_coverage is --%tags(#1097,#1094) --%test(Extended coverage does not fail the test run then tested code calls DBMS_STATS) procedure coverage_with_dbms_stats; - + + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov_schema) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov_schema) + --%test(Collect coverage for objects with schema regex include) + procedure coverage_regex_include_schema; + + --%test(Collect coverage for objects with schema regex include) + procedure coverage_regex_include_object; + + --%test(Collect coverage for objects with schema regex include) + procedure coverage_regex_exclude_schema; + + --%test(Collect coverage for objects with schema regex include) + procedure coverage_regex_exclude_object; + end; / From b3dba1905941d3ef778d1ebf8372026e7aad97ea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 25 Feb 2022 00:46:31 +0000 Subject: [PATCH 004/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 37bf4e2d1..8c02ce441 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index f064966b3..1fd31b877 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 7979e1c23..05a2abdde 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 4772a25de..9a746a84c 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 537da5148..1ce42648a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 617e888ac..941f5c364 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index e46c20029..104e82f7c 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index dc4a8ffda..65e044fd8 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 0fabf61bd..b9a0a70a0 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses DBMS_PROFILER package provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index be7e9b125..c7b9a3847 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index a50797b2e..f95607466 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index c4b2b1a0b..476b826fd 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 27b2989cf..70441da7e 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index d6e75700c..78735f144 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index ebc28ec38..ee366861f 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 03fe03f3e..1313dc90b 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 177f13589..516850fec 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3872--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 4401742f8..24ea09d0d 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.12.3872-develop'; + gc_version constant varchar2(50) := 'v3.1.12.3879-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From ca3dec790a9821cc2bdbf1bd2e12c33615339b52 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 25 Feb 2022 17:47:58 +0200 Subject: [PATCH 005/187] Updated project version to 3.1.13 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a0d004aa2..d0237db61 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.1.12-develop +v3.1.13-develop From fd81df2439703943825cbf2d4f98e37f31568fa9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 25 Feb 2022 15:56:06 +0000 Subject: [PATCH 006/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- sonar-project.properties | 2 +- source/core/ut_utils.pks | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 8c02ce441..70bdb2613 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 1fd31b877..cdc5d1330 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 05a2abdde..99b9f26d4 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 9a746a84c..fea1bfcad 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 1ce42648a..99a7df954 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 941f5c364..685449c27 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 104e82f7c..6667189e2 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 65e044fd8..415b477b6 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index b9a0a70a0..4cda2c9d4 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses DBMS_PROFILER package provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index c7b9a3847..645d17c89 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index f95607466..5b5d3079f 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 476b826fd..edaf0310d 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 70441da7e..9bbe8a452 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 78735f144..09cfd0029 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index ee366861f..27b37c276 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 1313dc90b..308788d62 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 516850fec..0ec9e80ee 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.12.3879--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) # Upgrading from version 2 diff --git a/sonar-project.properties b/sonar-project.properties index 7559b58a1..5d6cefe12 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.organization=utplsql sonar.projectKey=utPLSQL # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=utPLSQL -sonar.projectVersion=v3.1.12-develop +sonar.projectVersion=v3.1.13-develop # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # Since SonarQube 4.2, this property is optional if sonar.modules is set. diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 24ea09d0d..69955bab0 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.12.3879-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3880-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 7e680eeaa67b94bcface6034ecca7e2ed7684f7e Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 25 Feb 2022 18:49:42 +0200 Subject: [PATCH 007/187] Added disabledReason to `ut_realtime_reporter` --- source/reporters/ut_realtime_reporter.tpb | 1 + .../reporters/test_realtime_reporter.pkb | 38 ++++++++++++++++--- .../reporters/test_realtime_reporter.pks | 3 ++ 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/source/reporters/ut_realtime_reporter.tpb b/source/reporters/ut_realtime_reporter.tpb index 837643b0b..9c2af57ec 100644 --- a/source/reporters/ut_realtime_reporter.tpb +++ b/source/reporters/ut_realtime_reporter.tpb @@ -43,6 +43,7 @@ create or replace type body ut_realtime_reporter is self.print_node('objectName', a_test.item.object_name); self.print_node('procedureName', a_test.item.procedure_name); self.print_node('disabled', case when a_test.get_disabled_flag() then 'true' else 'false' end); + self.print_node('disabledReason', a_test.disabled_reason); self.print_node('name', a_test.name); self.print_node('description', a_test.description); self.print_node('testNumber', to_char(total_number_of_tests)); diff --git a/test/ut3_user/reporters/test_realtime_reporter.pkb b/test/ut3_user/reporters/test_realtime_reporter.pkb index ad354133b..2dafa71d0 100644 --- a/test/ut3_user/reporters/test_realtime_reporter.pkb +++ b/test/ut3_user/reporters/test_realtime_reporter.pkb @@ -45,6 +45,10 @@ create or replace package body test_realtime_reporter as --%test --%disabled procedure test_5; + + --%test + --%disabled(Cannot run this item at this time runtime > 10 mins.) + procedure test_6_disabled_reason; end;]'; execute immediate q'[create or replace package body check_realtime_reporting2 is procedure test_3_ok is @@ -62,6 +66,11 @@ create or replace package body test_realtime_reporter as begin null; end; + + procedure test_6_disabled_reason is + begin + null; + end; end;]'; execute immediate q'[create or replace package check_realtime_reporting3 is @@ -179,6 +188,8 @@ create or replace package body test_realtime_reporter as select 'post-test' as event_type, 'realtime_reporting.check_realtime_reporting2.test_4_nok' as item_id from dual union all select 'pre-test' as event_type, 'realtime_reporting.check_realtime_reporting2.test_5' as item_id from dual union all select 'post-test' as event_type, 'realtime_reporting.check_realtime_reporting2.test_5' as item_id from dual union all + select 'pre-test' as event_type, 'realtime_reporting.check_realtime_reporting2.test_6_disabled_reason' as item_id from dual union all + select 'post-test' as event_type, 'realtime_reporting.check_realtime_reporting2.test_6_disabled_reason' as item_id from dual union all select 'post-suite' as event_type, 'realtime_reporting.check_realtime_reporting2' as item_id from dual union all select 'pre-suite' as event_type, 'realtime_reporting.check_realtime_reporting1' as item_id from dual union all select 'pre-suite' as event_type, 'realtime_reporting.check_realtime_reporting1.test_context' as item_id from dual union all @@ -226,6 +237,7 @@ create or replace package body test_realtime_reporter as select 'event/items/suite/items/suite/items/test' as node_path from dual union all select 'event/items/suite/items/suite/items/test' as node_path from dual union all select 'event/items/suite/items/suite/items/test' as node_path from dual union all + select 'event/items/suite/items/suite/items/test' as node_path from dual union all select 'event/items/suite/items/suite' as node_path from dual union all select 'event/items/suite/items/suite/items' as node_path from dual union all select 'event/items/suite/items/suite/items/suite' as node_path from dual union all @@ -237,7 +249,7 @@ create or replace package body test_realtime_reporter as procedure total_number_of_tests is l_actual integer; - l_expected integer := 8; + l_expected integer := 9; begin select t.event_doc.extract('/event/totalNumberOfTests/text()').getnumberval() into l_actual @@ -283,9 +295,9 @@ create or replace package body test_realtime_reporter as and t.event_doc.extract('//test/@id').getstringval() is not null; open l_expected for select level as test_number, - 8 as total_number_of_tests + 9 as total_number_of_tests from dual - connect by level <= 8; + connect by level <= 9; ut.expect(l_actual).to_equal(l_expected).unordered; end pre_test_nodes; @@ -311,9 +323,9 @@ create or replace package body test_realtime_reporter as and t.event_doc.extract('//test/counter/warning/text()').getnumberval() is not null; open l_expected for select level as test_number, - 8 as total_number_of_tests + 9 as total_number_of_tests from dual - connect by level <= 8; + connect by level <= 9; ut.expect(l_actual).to_equal(l_expected).unordered; end post_test_nodes; @@ -494,6 +506,22 @@ create or replace package body test_realtime_reporter as ut.expect(l_xml is not null).to_be_true(); end; + procedure disabled_reason is + l_actual varchar2(32767); + l_expected varchar2(80) := dbms_xmlgen.convert('Cannot run this item at this time runtime > 10 mins.'); + begin + select t.event_doc.extract( + '//test/disabledReason/text()' + ).getstringval() + into l_actual + from table(g_events) t + where xmlexists( + '/event[@type="pre-run"]/*//test[@id="realtime_reporting.check_realtime_reporting2.test_6_disabled_reason"]' + passing t.event_doc + ); + ut.expect(l_actual).to_equal(l_expected); + end; + procedure remove_test_suites is pragma autonomous_transaction; begin diff --git a/test/ut3_user/reporters/test_realtime_reporter.pks b/test/ut3_user/reporters/test_realtime_reporter.pks index 453824ca5..087713f79 100644 --- a/test/ut3_user/reporters/test_realtime_reporter.pks +++ b/test/ut3_user/reporters/test_realtime_reporter.pks @@ -57,6 +57,9 @@ create or replace package test_realtime_reporter as --%test(Escape nested CDATA sections in test output) procedure nested_cdata_output; + --%test(Provide reason disabled test) + procedure disabled_reason; + --%afterall procedure remove_test_suites; From 4eec03e223c942471112ee9e68303b962e0cd25d Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 25 Feb 2022 20:19:42 +0000 Subject: [PATCH 008/187] Update to code to address sql injection concerns. Dealing with precedence. Adding some more tests. --- source/core/coverage/ut_coverage.pkb | 14 ++- test/ut3_tester_helper/coverage_helper.pkb | 52 ++++---- test/ut3_tester_helper/coverage_helper.pks | 3 - .../test_coverage/test_extended_coverage.pkb | 115 ++++++++++++------ .../test_coverage/test_extended_coverage.pks | 16 ++- 5 files changed, 123 insertions(+), 77 deletions(-) diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index cdef6dd04..3c5bde7af 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -133,7 +133,7 @@ create or replace package body ut_coverage is end if; if a_coverage_options.exclude_object_expr is not null then - l_regex_exc_filters := l_regex_exc_filters||q'[ and not regexp_like(s.name,:a_exclude_obj_expr:,'i')]'; + l_regex_exc_filters := l_regex_exc_filters||q'[ and not regexp_like(s.name,:a_exclude_obj_expr,'i')]'; else l_regex_exc_filters := l_regex_exc_filters||'and :a_exclude_obj_expr is null '; end if; @@ -147,7 +147,7 @@ create or replace package body ut_coverage is l_result := replace(l_result, '{mappings_cardinality}', l_mappings_cardinality); l_result := replace(l_result, '{skipped_objects_cardinality}', ut_utils.scale_cardinality(cardinality(a_skip_objects))); l_result := replace(l_result, '{regex_exc_filters}', l_regex_exc_filters); - + return l_result; end; @@ -159,7 +159,11 @@ create or replace package body ut_coverage is begin if not is_develop_mode() then --skip all the utplsql framework objects and all the unit test packages that could potentially be reported by coverage. - l_skip_objects := ut_utils.get_utplsql_objects_list() multiset union all coalesce(a_coverage_options.exclude_objects, ut_object_names()); + l_skip_objects := coalesce(ut_utils.get_utplsql_objects_list(),ut_object_names()); + --Regex exclusion override the standard exclusion objects. + if a_coverage_options.exclude_schema_expr is null and a_coverage_options.exclude_object_expr is null then + l_skip_objects := l_skip_objects multiset union all coalesce(a_coverage_options.exclude_objects, ut_object_names()); + end if; end if; l_sql := get_cov_sources_sql(a_coverage_options, l_skip_objects); @@ -168,12 +172,12 @@ create or replace package body ut_coverage is if a_coverage_options.file_mappings is not empty then open l_cursor for l_sql using a_coverage_options.file_mappings,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; - elsif a_coverage_options.include_objects is not empty then - open l_cursor for l_sql using a_coverage_options.include_objects,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; elsif a_coverage_options.include_schema_expr is not null or a_coverage_options.include_object_expr is not null then open l_cursor for l_sql using a_coverage_options.include_schema_expr,a_coverage_options.include_object_expr, a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr, l_skip_objects; + elsif a_coverage_options.include_objects is not empty then + open l_cursor for l_sql using a_coverage_options.include_objects,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; else open l_cursor for l_sql using a_coverage_options.schema_names,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; end if; diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index bbf288ed4..5f255a2e6 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -158,14 +158,14 @@ create or replace package body coverage_helper is end; - procedure create_regex_dummy_cov is + procedure create_regex_dummy_for_schema(p_schema in varchar2) is pragma autonomous_transaction; begin - execute immediate q'[create or replace package ut3_develop.regex_dummy_cov is + execute immediate q'[create or replace package ]'||p_schema||q'[.regex_dummy_cov is procedure do_stuff(i_input in number); end;]'; - execute immediate q'[create or replace package body ut3_develop.regex_dummy_cov is + execute immediate q'[create or replace package body ]'||p_schema||q'[.regex_dummy_cov is procedure do_stuff(i_input in number) is begin if i_input = 2 then dbms_output.put_line('should not get here'); elsif i_input = 1 then dbms_output.put_line('should get here'); @@ -175,39 +175,38 @@ create or replace package body coverage_helper is end; end;]'; - execute immediate q'[create or replace package ut3_develop.test_regex_dummy_cov is + execute immediate q'[create or replace package ]'||p_schema||q'[.test_regex_dummy_cov is --%suite(dummy coverage test) --%suitepath(coverage_testing) --%test procedure test_do_stuff; + --%test + procedure zero_coverage; end;]'; - execute immediate q'[create or replace package body ut3_develop.test_regex_dummy_cov is + execute immediate q'[create or replace package body ]'||p_schema||q'[.test_regex_dummy_cov is procedure test_do_stuff is begin regex_dummy_cov.do_stuff(1); ut.expect(1).to_equal(1); end; + procedure zero_coverage is + begin + null; + end; end;]'; end; - - procedure drop_regex_dummy_cov is - pragma autonomous_transaction; - begin - begin execute immediate q'[drop package ut3_develop.regex_dummy_cov]'; exception when others then null; end; - begin execute immediate q'[drop package ut3_develop.test_regex_dummy_cov]'; exception when others then null; end; - end; - procedure create_regex_dummy_for_schema(p_schema in varchar2) is + procedure create_regex_dummy_obj is pragma autonomous_transaction; begin - execute immediate q'[create or replace package ]'||p_schema||q'[.regex_dummy_cov_schema is + execute immediate q'[create or replace package ut3_develop.regex123_dummy_cov is procedure do_stuff(i_input in number); end;]'; - execute immediate q'[create or replace package body ]'||p_schema||q'[.regex_dummy_cov_schema is + execute immediate q'[create or replace package body ut3_develop.regex123_dummy_cov is procedure do_stuff(i_input in number) is begin if i_input = 2 then dbms_output.put_line('should not get here'); elsif i_input = 1 then dbms_output.put_line('should get here'); @@ -217,7 +216,7 @@ create or replace package body coverage_helper is end; end;]'; - execute immediate q'[create or replace package ]'||p_schema||q'[.test_regex_dummy_cov_schema is + execute immediate q'[create or replace package ut3_develop.test_regex123_dummy_cov is --%suite(dummy coverage test) --%suitepath(coverage_testing) @@ -228,10 +227,10 @@ create or replace package body coverage_helper is procedure zero_coverage; end;]'; - execute immediate q'[create or replace package body ]'||p_schema||q'[.test_regex_dummy_cov_schema is + execute immediate q'[create or replace package body ut3_develop.test_regex123_dummy_cov is procedure test_do_stuff is begin - regex_dummy_cov_schema.do_stuff(1); + regex123_dummy_cov.do_stuff(1); ut.expect(1).to_equal(1); end; procedure zero_coverage is @@ -240,20 +239,23 @@ create or replace package body coverage_helper is end; end;]'; end; - - procedure create_regex_dummy_cov_schema is + + procedure create_regex_dummy_cov is begin create_regex_dummy_for_schema('ut3_develop'); create_regex_dummy_for_schema('ut3_tester_helper'); + create_regex_dummy_obj; end; - procedure drop_regex_dummy_cov_schema is + procedure drop_regex_dummy_cov is pragma autonomous_transaction; begin - begin execute immediate q'[drop package ut3_develop.regex_dummy_cov_schema]'; exception when others then null; end; - begin execute immediate q'[drop package ut3_develop.test_regex_dummy_cov_schema]'; exception when others then null; end; - begin execute immediate q'[drop package ut3_tester_helper.regex_dummy_cov_schema]'; exception when others then null; end; - begin execute immediate q'[drop package ut3_tester_helper.test_regex_dummy_cov_schema]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_develop.regex_dummy_cov]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_develop.test_regex_dummy_cov]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_tester_helper.regex_dummy_cov]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_tester_helper.test_regex_dummy_cov]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_develop.regex123_dummy_cov]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_develop.test_regex123_dummy_cov]'; exception when others then null; end; end; diff --git a/test/ut3_tester_helper/coverage_helper.pks b/test/ut3_tester_helper/coverage_helper.pks index 04bb0029c..c5e862612 100644 --- a/test/ut3_tester_helper/coverage_helper.pks +++ b/test/ut3_tester_helper/coverage_helper.pks @@ -17,9 +17,6 @@ create or replace package coverage_helper is procedure create_regex_dummy_cov; procedure drop_regex_dummy_cov; - procedure create_regex_dummy_cov_schema; - procedure drop_regex_dummy_cov_schema; - procedure create_cov_with_dbms_stats; procedure drop_cov_with_dbms_stats; diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb index 5aea2e184..f14eac984 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb @@ -107,74 +107,111 @@ create or replace package body test_extended_coverage is end; procedure coverage_regex_include_schema is - l_expected_ut3 clob; - l_expected_help clob; - l_actual_ut3 clob; - l_actual_help clob; - l_actual_both clob; - + l_expected clob; + l_not_expected clob; + l_actual clob; begin --Arrange - l_expected_ut3 := '%' || + l_expected := '%' || '%%'; - l_expected_help := '%' || + l_not_expected := '%' || '%%'; --Act - l_actual_ut3 := + l_actual := ut3_tester_helper.coverage_helper.run_tests_as_job( q'[ ut3_develop.ut.run( - a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov_schema', 'ut3_tester_helper.test_regex_dummy_cov_schema'), + a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov', 'ut3_tester_helper.test_regex_dummy_cov'), a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), - a_include_schema_expr => '^ut3_develop' + a_include_schema_expr => '^ut3_develop', + a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) ) ]' - ); - /* - l_actual_help := + ); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like(l_not_expected); + end; + + procedure coverage_regex_include_object is + l_expected clob; + l_not_expected clob; + l_actual clob; + begin + --Arrange + l_expected := '%' || + '%%'; + l_not_expected := '%' || + '%%'; + --Act + l_actual := ut3_tester_helper.coverage_helper.run_tests_as_job( q'[ ut3_develop.ut.run( - a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov_schema', 'ut3_tester_helper.test_regex_dummy_cov_schema'), + a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov', 'ut3_develop.test_regex123_dummy_cov'), a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), - a_include_schema_expr => '^ut3_tester_helper' + a_include_object_expr => 'regex123', + a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.regex_dummy_cov' ) ) ]' - ); + ); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like(l_not_expected); + end; - l_actual_both := + procedure coverage_regex_exclude_schema is + l_expected clob; + l_not_expected clob; + l_actual clob; + begin + --Arrange + l_expected := '%' || + '%%'; + l_not_expected := '%' || + '%%'; + --Act + l_actual := ut3_tester_helper.coverage_helper.run_tests_as_job( q'[ ut3_develop.ut.run( - a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov_schema', 'ut3_tester_helper.test_regex_dummy_cov_schema'), + a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov', 'ut3_tester_helper.test_regex_dummy_cov'), a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), - a_include_schema_expr => '^ut3_tester_helper||^ut3_tester_helper' + a_exclude_schema_expr => '^ut3_tester', + a_exclude_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.regex_dummy_cov' ) ) ]' - ); - */ + ); --Assert - ut.expect(l_actual_ut3).to_be_like(l_expected_ut3); - ut.expect(l_actual_ut3).not_to_be_like(l_expected_help); - --ut.expect(l_actual_help).to_be_like(l_expected_help); - --ut.expect(l_actual_help).not_to_be_like(l_expected_ut3); - --ut.expect(l_actual_both).to_be_like(l_expected_ut3); - --ut.expect(l_actual_both).to_be_like(l_expected_help); - end; - - procedure coverage_regex_include_object is - begin - null; - end; - - procedure coverage_regex_exclude_schema is - begin - null; + ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like(l_not_expected); end; procedure coverage_regex_exclude_object is + l_expected clob; + l_not_expected clob; + l_actual clob; begin - null; + --Arrange + l_expected := '%' || + '%%'; + l_not_expected := '%' || + '%%'; + --Act + l_actual := + ut3_tester_helper.coverage_helper.run_tests_as_job( + q'[ + ut3_develop.ut.run( + a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov', 'ut3_develop.test_regex123_dummy_cov'), + a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), + a_exclude_object_expr => 'regex123', + a_exclude_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.regex_dummy_cov' ) + ) + ]' + ); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like(l_not_expected); end; end; diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks index a8c71f442..99d7c5db4 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks @@ -18,18 +18,24 @@ create or replace package test_extended_coverage is --%test(Extended coverage does not fail the test run then tested code calls DBMS_STATS) procedure coverage_with_dbms_stats; - --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov_schema) - --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov_schema) + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) --%test(Collect coverage for objects with schema regex include) procedure coverage_regex_include_schema; - --%test(Collect coverage for objects with schema regex include) + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) + --%test(Collect coverage for objects with object regex include) procedure coverage_regex_include_object; - --%test(Collect coverage for objects with schema regex include) + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) + --%test(Collect coverage for objects with schema regex exclude) procedure coverage_regex_exclude_schema; - --%test(Collect coverage for objects with schema regex include) + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) + --%test(Collect coverage for objects with object regex exclude) procedure coverage_regex_exclude_object; end; From e7d59b4b3eea36cea8fbbaeb7640b1f82ec8ba7b Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 25 Feb 2022 20:55:36 +0000 Subject: [PATCH 009/187] Splitting skipped framework objects and excluded objects into separate table types. Update docs. --- docs/userguide/coverage.md | 32 +++++++++++++++++++--- source/core/coverage/ut_coverage.pkb | 40 +++++++++++++++++++--------- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 1f6cc4be5..29651b68c 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -131,10 +131,34 @@ exec ut.run('unit_test_schema', ut_coverage_html_reporter(), a_coverage_schemes There are six options that can be used to narrow down the scope of coverage report: - `a_include_objects` - list of `[object_owner.].object_name` to be included in the coverage report. - `a_exclude_objects` - list of `[object_owner.].object_name` to be excluded from the coverage report -- `a_include_schema_expr` - string of regex expression of schemas to be included in the coverage report. It will override `a_include_objects` -- `a_include_object_expr` - string of regex expression of objects ( no schema names included ) to be included in the coverage report. It will override `a_include_objects` -- `a_exclude_schema_expr` - string of regex expression of schemas to be excluded from the coverage report. It will override `a_exclude_objects` -- `a_exclude_object_expr` - string of regex expression of objects to be excluded from the coverage report. It will override `a_exclude_objects` +- `a_include_schema_expr` - string of regex expression of schemas to be included in the coverage report. It will override `a_include_objects` for example : + ```sql + a_include_schema_expr => '^ut3_develop', + a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) + ``` + Will result in showing coverage for all schemas that match regular expression `^ut3_develop` and ignore objectes defined by parameter `a_include_objects` + +- `a_include_object_expr` - string of regex expression of objects ( no schema names included ) to be included in the coverage report. It will override `a_include_objects` for example: + ```sql + a_include_object_expr => 'regex123', + a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) + ``` + Will result in showing coverage for all objects that name match regular expression `regex123` and ignore objectes defined by parameter `a_include_objects` + +- `a_exclude_schema_expr` - string of regex expression of schemas to be excluded from the coverage report. It will override `a_exclude_objects` for example: + ```sql + a_exclude_schema_expr => '^ut3_tester', + a_exclude_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.regex_dummy_cov' ) + ``` + Will result in showing coverage for all objects that schema is not matching regular expression `^ut3_tester` and ignore exclusion defined by parameter `a_exclude_objects` + +- `a_exclude_object_expr` - string of regex expression of objects to be excluded from the coverage report. It will override `a_exclude_objects` for example + ```sql + a_exclude_object_expr => 'regex123', + a_exclude_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.regex_dummy_cov' ) + ``` + Will result in showing coverage for all objects that name is not matching regular expression `regex123` and ignore exclusion defined by parameter `a_exclude_objects` + You may specify both _include_ and _exclude_ options to gain more control over what needs to be included / excluded from the coverage report. diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index 3c5bde7af..06951fc2f 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -30,7 +30,7 @@ create or replace package body ut_coverage is end; function get_cov_sources_sql(a_coverage_options ut_coverage_options, a_skip_objects ut_object_names) return varchar2 is - l_result varchar2(32767); --QUESTION: Given fact that we can pass large regex filters same as objects filter should we consider a clob ? + l_result varchar2(32767); l_full_name varchar2(32767); l_join_mappings varchar2(32767); l_filters varchar2(32767); @@ -55,7 +55,12 @@ create or replace package body ut_coverage is from {sources_view} s {join_file_mappings} where s.type in ('PACKAGE BODY', 'TYPE BODY', 'PROCEDURE', 'FUNCTION', 'TRIGGER') {filters} - {regex_exc_filters} + {regex_exc_filters} + and not exists ( + select /*+ cardinality(el {excuded_objects_cardinality})*/ 1 + from table(:l_excluded_objects) el + where s.owner = el.owner and s.name = el.name + ) ), coverage_sources as ( select full_name, owner, name, type, line, text, @@ -146,6 +151,7 @@ create or replace package body ut_coverage is l_result := replace(l_result, '{filters}', l_filters); l_result := replace(l_result, '{mappings_cardinality}', l_mappings_cardinality); l_result := replace(l_result, '{skipped_objects_cardinality}', ut_utils.scale_cardinality(cardinality(a_skip_objects))); + l_result := replace(l_result, '{excuded_objects_cardinality}', ut_utils.scale_cardinality(cardinality(coalesce(a_coverage_options.exclude_objects, ut_object_names())))); l_result := replace(l_result, '{regex_exc_filters}', l_regex_exc_filters); return l_result; @@ -153,33 +159,41 @@ create or replace package body ut_coverage is end; function get_cov_sources_cursor(a_coverage_options in ut_coverage_options) return sys_refcursor is - l_cursor sys_refcursor; - l_skip_objects ut_object_names; - l_sql varchar2(32767); + l_cursor sys_refcursor; + l_skip_objects ut_object_names; + l_excluded_objects ut_object_names; + l_sql varchar2(32767); begin if not is_develop_mode() then --skip all the utplsql framework objects and all the unit test packages that could potentially be reported by coverage. l_skip_objects := coalesce(ut_utils.get_utplsql_objects_list(),ut_object_names()); - --Regex exclusion override the standard exclusion objects. - if a_coverage_options.exclude_schema_expr is null and a_coverage_options.exclude_object_expr is null then - l_skip_objects := l_skip_objects multiset union all coalesce(a_coverage_options.exclude_objects, ut_object_names()); - end if; end if; + --Regex exclusion override the standard exclusion objects. + if a_coverage_options.exclude_schema_expr is null and a_coverage_options.exclude_object_expr is null then + l_excluded_objects := coalesce(a_coverage_options.exclude_objects, ut_object_names()); + end if; + l_sql := get_cov_sources_sql(a_coverage_options, l_skip_objects); ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_key_anyvalues().put('l_sql',l_sql) ); if a_coverage_options.file_mappings is not empty then - open l_cursor for l_sql using a_coverage_options.file_mappings,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; + open l_cursor for l_sql using a_coverage_options.file_mappings,a_coverage_options.exclude_schema_expr, + a_coverage_options.exclude_object_expr,l_excluded_objects, + l_skip_objects; elsif a_coverage_options.include_schema_expr is not null or a_coverage_options.include_object_expr is not null then open l_cursor for l_sql using a_coverage_options.include_schema_expr,a_coverage_options.include_object_expr, a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr, - l_skip_objects; + l_excluded_objects,l_skip_objects; elsif a_coverage_options.include_objects is not empty then - open l_cursor for l_sql using a_coverage_options.include_objects,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; + open l_cursor for l_sql using a_coverage_options.include_objects,a_coverage_options.exclude_schema_expr, + a_coverage_options.exclude_object_expr,l_excluded_objects, + l_skip_objects; else - open l_cursor for l_sql using a_coverage_options.schema_names,a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr,l_skip_objects; + open l_cursor for l_sql using a_coverage_options.schema_names,a_coverage_options.exclude_schema_expr, + a_coverage_options.exclude_object_expr,l_excluded_objects, + l_skip_objects; end if; return l_cursor; end; From 9f229b8f34750f5e6da31fa0bf6070b49b0f48eb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 25 Feb 2022 22:58:15 +0000 Subject: [PATCH 010/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 70bdb2613..34f00c50c 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index cdc5d1330..43a9c7144 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 99b9f26d4..48ece4cc6 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index fea1bfcad..0da2b42fe 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 99a7df954..2437aa9c1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 685449c27..bfd2a13da 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 6667189e2..d3ae90eca 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 415b477b6..b4052a74a 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 4cda2c9d4..813815239 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses DBMS_PROFILER package provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 645d17c89..a78657be0 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 5b5d3079f..91d8d02b3 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index edaf0310d..91099d1bb 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 9bbe8a452..05fed3990 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 09cfd0029..a4e8f1a5d 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 27b37c276..1961e5f98 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 308788d62..ba552ef2d 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 0ec9e80ee..14ac4988c 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3880--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 69955bab0..9d31d71b3 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3880-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3889-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 6f5b2dc81148c7723a1d174992603c5203af1dbd Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 26 Feb 2022 01:25:02 +0200 Subject: [PATCH 011/187] Update of coverage documentation --- docs/userguide/coverage.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 29651b68c..42f35c08a 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -780,6 +780,10 @@ ut_coverage_options( exclude_objects ut_varchar2_rows := null, include_objects ut_varchar2_rows := null, file_mappings ut_file_mappings := null + include_schema_expr varchar2(4000) := null, + include_object_expr varchar2(4000) := null, + exclude_schema_expr varchar2(4000) := null, + exclude_object_expr varchar2(4000) := null ); ``` @@ -795,6 +799,10 @@ The `a_coverage_options` parameter is used to control the scope and formatting o - `exclude_objects` - optional - list of object names to exclude from report - data-type `UT_VARCHAR2_ROWS` - `include_objects` - optional - list of object names to gather coverage on - data-type `UT_VARCHAR2_ROWS` - `file_mappings` - optional - list of schema names to gather coverage on - data-type `UT_FILE_MAPPINGS` +- `include_schema_expr` - optional - regular expression to match against schema name to include in coverage - data-type `VARCHAR2(4000)` +- `include_object_expr` - optional - regular expression to match against object name to include in coverage - data-type `VARCHAR2(4000)` +- `exclude_schema_expr` - optional - regular expression to match against schema name to exclude in coverage - data-type `VARCHAR2(4000)` +- `exclude_object_expr` - optional - regular expression to match against object name to exclude in coverage - data-type `VARCHAR2(4000)` `coverage_run_id` parameter identifies a common coverage run. The valid value type for that parameter is RAW(32). It is recommended to use `sys_guid()` to generate a common, unique identifier for a specific coverage run. @@ -802,4 +810,10 @@ If the identifier is not unique, previous runs of coverage that used the same `c For details on the meaning of `schema_names`, `exclude_objects`, `include_objects`, `file_mappings` see sections above. Note that data-types of include/exclude/schema lists are different when calling `ut.run` vs. calling `get_report/get_report_cursor`. - + +The order of priority is for evaluation of include/exclude is as follows. +- if `file_mappings` is specified then all include/exclude parameters are ignored +- else if `..._expr` is specified then include_objects/exclude_objects parameters are ignored +- else if `schema_names` is specified then the coverage is gathered on all object of specified schemas +- else coverage is gathered on all schemas specified in paths passed to run procedure +- if no paths were specified, the coverage is gathered on current schema of the session running the tests From b430b437d8f7c98a54e082cc1260b93cec1d9d28 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 26 Feb 2022 01:36:19 +0200 Subject: [PATCH 012/187] Fixed typo in documentation --- docs/userguide/coverage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 42f35c08a..663df7f3d 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -730,7 +730,7 @@ exec ut_runner.coverage_stop(); ```sql --SESSION 1 or SESSION2 2 or SESSION 3 --- run after calls in SESSION 1 & 2 are finshed +-- run after calls in SESSION 1 & 2 are finished -- retrieve coverage report in HTML format coverage_run_id value select * from table( @@ -744,7 +744,7 @@ select * ```sql --SESSION 1 or SESSION2 2 or SESSION 3 --- run after calls in SESSION 1 & 2 are finshed +-- run after calls in SESSION 1 & 2 are finished declare l_results_cursor sys_refcursor; begin From b8a3fb6c02e0e52dca57d608aab8f27647f0a62a Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 26 Feb 2022 02:14:17 +0200 Subject: [PATCH 013/187] Adding COVERAGE_RUN_ID to the utPLSQL context to allow for more accurate coverage reporting when runnign tests against the coverage module of the framework. --- docs/userguide/annotations.md | 3 ++- source/core/session_context/ut_session_info.tpb | 2 ++ test/ut3_user/api/test_ut_run.pkb | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index d3ae90eca..72ae33e10 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -2121,7 +2121,8 @@ It can be accessed from any procecure invoked as part of utPLSQL test execution. > For example if utPLSQL is installed into `HR` schema, the context name will be `HR_INFO` Following attributes are populated: -- Always: +- For entire duration of the test-run: + - `sys_context( 'UT3_INFO', 'COVERAGE_RUN_ID' );` - Value of COVERAGE_RUN_ID used by utPLSQL internally for coverage gathering - `sys_context( 'UT3_INFO', 'RUN_PATHS' );` - list of suitepaths / suitenames used as input parameters for call to `ut.run(...)` or `ut_runner.run(...)` - `sys_context( 'UT3_INFO', 'SUITE_DESCRIPTION' );` - the description of test suite that is currently being executed - `sys_context( 'UT3_INFO', 'SUITE_PACKAGE' );` - the owner and name of test suite package that is currently being executed diff --git a/source/core/session_context/ut_session_info.tpb b/source/core/session_context/ut_session_info.tpb index c7fe7dc5f..7d469651a 100644 --- a/source/core/session_context/ut_session_info.tpb +++ b/source/core/session_context/ut_session_info.tpb @@ -28,12 +28,14 @@ create or replace type body ut_session_info as member procedure before_calling_run(self in out nocopy ut_session_info, a_run in ut_run) is begin ut_session_context.set_context( 'run_paths', ut_utils.to_string( ut_utils.table_to_clob( a_run.run_paths,',' ), null ) ); + ut_session_context.set_context( 'coverage_run_id', rawtohex( a_run.coverage_options.coverage_run_id ) ); dbms_application_info.set_module( 'utPLSQL', null ); end; member procedure after_calling_run(self in out nocopy ut_session_info, a_run in ut_run) is begin ut_session_context.clear_context( 'run_paths' ); + ut_session_context.clear_context( 'coverage_run_id' ); dbms_application_info.set_module( module, action ); dbms_application_info.set_client_info( client_info ); end; diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 8ec19f6d8..b4f5a5238 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -1268,7 +1268,8 @@ Failures:% procedure sys_ctx_on_suite_beforeall is begin ut.expect(g_context_test_results).to_be_like( - '%BEFORE_SUITE:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.before_suite' + '%BEFORE_SUITE:COVERAGE_RUN_ID=________________________________%' + ||'%BEFORE_SUITE:CURRENT_EXECUTABLE_NAME='||gc_owner||'.check_context.before_suite' ||'%BEFORE_SUITE:CURRENT_EXECUTABLE_TYPE=beforeall' ||'%BEFORE_SUITE:RUN_PATHS=check_context' ||'%BEFORE_SUITE:SUITE_DESCRIPTION=Suite description' From 4602023a08403869b4b80124f7e24e08a67d514d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 26 Feb 2022 01:04:42 +0000 Subject: [PATCH 014/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 34f00c50c..ceff64be9 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 43a9c7144..110f3197c 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 48ece4cc6..7b4a67750 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 0da2b42fe..4fc3f72f7 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 2437aa9c1..f7b8f7a26 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index bfd2a13da..93da6013e 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 72ae33e10..af996f73c 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index b4052a74a..b5b7cb286 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 813815239..3e541ffbe 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses DBMS_PROFILER package provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index a78657be0..fd6cc6f98 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 91d8d02b3..1335b1d98 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 91099d1bb..b5b9d09f1 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 05fed3990..9f92b7c6a 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index a4e8f1a5d..aac098805 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 1961e5f98..06eefcede 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index ba552ef2d..73e469da3 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 14ac4988c..f0ef68ab2 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3889--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 9d31d71b3..b9917f2a7 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3889-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3896-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From f3ea9e5c5859a271de0738d1db1c6b3fe6c46b3d Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Sat, 26 Feb 2022 15:18:37 +0100 Subject: [PATCH 015/187] fix typo, "can be provided" instead of "can by provided" --- docs/userguide/annotations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index af996f73c..f28e0cd5b 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -127,7 +127,7 @@ end; | `--%suite()` | Package | Mandatory. Marks package as a test suite. Optional suite description can be provided (see `displayname`). | | `--%suitepath()` | Package | Similar to java package. The annotation allows logical grouping of suites into hierarchies. | | `--%displayname()` | Package/procedure | Human-readable and meaningful description of a context/suite/test. Overrides the `` provided with `suite`/`test`/`context` annotation. This annotation is redundant and might be removed in future releases. | -| `--%test()` | Procedure | Denotes that the annotated procedure is a unit test procedure. Optional test description can by provided (see `displayname`). | +| `--%test()` | Procedure | Denotes that the annotated procedure is a unit test procedure. Optional test description can be provided (see `displayname`). | | `--%throws([,...])`| Procedure | Denotes that the annotated test procedure must throw one of the exceptions provided. Supported forms of exceptions are: numeric literals, numeric constant names, exception constant names, predefined Oracle exception names. | | `--%beforeall` | Procedure | Denotes that the annotated procedure should be executed once before all elements of the suite. | | `--%beforeall([[.].][,...])` | Package | Denotes that the mentioned procedure(s) should be executed once before all elements of the suite. | From 5ff7f44ee583b356e635949b95695933fa86927a Mon Sep 17 00:00:00 2001 From: Philipp Salvisberg Date: Sat, 26 Feb 2022 16:24:09 +0100 Subject: [PATCH 016/187] fix typo in expectations.md, whether instead of wheter --- docs/userguide/expectations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 1335b1d98..3bd3e090b 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1096,7 +1096,7 @@ SUCCESS ## to_be_within of -Determines wheter expected value is within range (tolerance) from another value. +Determines whether expected value is within range (tolerance) from another value. The logical formual used for calcuating the matcher is: ``` @@ -1177,7 +1177,7 @@ Failures: ## to_be_within_pct of -Determines wheter actual value is within percentage range of expected value. +Determines whether actual value is within percentage range of expected value. The matcher only works with `number` data-type. The percentage deviation (distance) must be expressed as a non-negative number. From 4ab0f5875d3da51a8fdf17964f9018b71d04845b Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 26 Feb 2022 18:11:49 +0200 Subject: [PATCH 017/187] Added ability to publish coverage generated by test jobs running utPLSQL with coverage into main testing session coverage. --- source/api/ut_runner.pkb | 2 +- source/core/coverage/ut_coverage.pkb | 13 ++++- source/core/coverage/ut_coverage.pks | 2 + test/ut3_tester_helper/coverage_helper.pkb | 67 +++++++++++++++++++++- 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index af168fe5d..cbf1971e7 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -127,7 +127,7 @@ create or replace package body ut_runner is l_run := ut_run( a_run_paths => l_paths, a_coverage_options => ut_coverage_options( - coverage_run_id => sys_guid(), + coverage_run_id => ut_coverage.get_coverage_run_id(), schema_names => l_coverage_schema_names, exclude_objects => ut_utils.convert_collection(a_exclude_objects), include_objects => ut_utils.convert_collection(a_include_objects), diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index 06951fc2f..eeedfc665 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -18,6 +18,7 @@ create or replace package body ut_coverage is g_develop_mode boolean not null := false; g_is_started boolean not null := false; + g_coverage_run_id raw(32); procedure set_develop_mode(a_develop_mode in boolean) is begin @@ -231,6 +232,7 @@ create or replace package body ut_coverage is l_block_coverage_id integer; begin if not is_develop_mode() and not g_is_started then + g_coverage_run_id := a_coverage_run_id; l_line_coverage_id := ut_coverage_helper_profiler.coverage_start( l_run_comment ); l_block_coverage_id := ut_coverage_helper_block.coverage_start( l_run_comment ); g_is_started := true; @@ -256,7 +258,6 @@ create or replace package body ut_coverage is g_is_started := false; ut_coverage_helper_block.coverage_stop(); ut_coverage_helper_profiler.coverage_stop(); - g_is_started := false; end if; end; @@ -314,7 +315,15 @@ create or replace package body ut_coverage is $end return l_result_profiler_enrich; - end get_coverage_data; + end get_coverage_data; + + function get_coverage_run_id return raw is + begin + if g_coverage_run_id is null then + g_coverage_run_id := sys_guid(); + end if; + return g_coverage_run_id; + end; end; / diff --git a/source/core/coverage/ut_coverage.pks b/source/core/coverage/ut_coverage.pks index 210cb13f6..21f3b1f9e 100644 --- a/source/core/coverage/ut_coverage.pks +++ b/source/core/coverage/ut_coverage.pks @@ -74,5 +74,7 @@ create or replace package ut_coverage authid current_user is function get_coverage_data(a_coverage_options ut_coverage_options) return t_coverage; + function get_coverage_run_id return raw; + end; / diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index 5f255a2e6..ab5a09515 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -381,14 +381,75 @@ create or replace package body coverage_helper is return l_result_clob; end; + procedure copy_coverage_data_to_ut3(a_coverage_run_id raw) is + pragma autonomous_transaction; + l_current_coverage_run_id raw(32) := hextoraw(sys_context('UT3_INFO','COVERAGE_RUN_ID')); + begin + insert into ut3.ut_coverage_runs(coverage_run_id, line_coverage_id, block_coverage_id) + select l_current_coverage_run_id, -line_coverage_id, -block_coverage_id + from ut3_develop.ut_coverage_runs + where coverage_run_id = a_coverage_run_id; + + insert into ut3.plsql_profiler_runs(runid, related_run, run_owner, run_date, run_comment, run_total_time, run_system_info, run_comment1, spare1) + select -runid, related_run, run_owner, run_date, run_comment, run_total_time, run_system_info, run_comment1, spare1 + from ut3_develop.plsql_profiler_runs c + join ut3_develop.ut_coverage_runs r + on r.line_coverage_id = c.runid + where r.coverage_run_id = a_coverage_run_id; + + insert into ut3.plsql_profiler_units(runid, unit_number, unit_type, unit_owner, unit_name, unit_timestamp, total_time, spare1, spare2) + select -runid, unit_number, unit_type, unit_owner, unit_name, unit_timestamp, total_time, spare1, spare2 + from ut3_develop.plsql_profiler_units c + join ut3_develop.ut_coverage_runs r + on r.line_coverage_id = c.runid + where r.coverage_run_id = a_coverage_run_id; + + insert into ut3.plsql_profiler_data(runid, unit_number, line#, total_occur, total_time, min_time, max_time, spare1, spare2, spare3, spare4) + select -runid, unit_number, line#, total_occur, total_time, min_time, max_time, spare1, spare2, spare3, spare4 + from ut3_develop.plsql_profiler_data c + join ut3_develop.ut_coverage_runs r + on r.line_coverage_id = c.runid + where r.coverage_run_id = a_coverage_run_id; + + insert into ut3.dbmspcc_runs(run_id, run_comment, run_owner, run_timestamp) + select -run_id, run_comment, run_owner, run_timestamp + from ut3_develop.dbmspcc_runs c + join ut3_develop.ut_coverage_runs r + on r.block_coverage_id = c.run_id + where r.coverage_run_id = a_coverage_run_id; + + insert into ut3.dbmspcc_units(run_id, object_id, owner, name, type, last_ddl_time) + select -run_id, object_id, owner, name, type, last_ddl_time + from ut3_develop.dbmspcc_units c + join ut3_develop.ut_coverage_runs r + on r.block_coverage_id = c.run_id + where r.coverage_run_id = a_coverage_run_id; + + insert into ut3.dbmspcc_blocks(run_id, object_id, block, line, col, covered, not_feasible) + select -run_id, object_id, block, line, col, covered, not_feasible + from ut3_develop.dbmspcc_blocks c + join ut3_develop.ut_coverage_runs r + on r.block_coverage_id = c.run_id + where r.coverage_run_id = a_coverage_run_id; + + commit; + end; + function run_tests_as_job( a_run_command varchar2 ) return clob is l_plsql_block varchar2(32767); l_result_clob clob; - pragma autonomous_transaction; + l_coverage_id raw(32) := sys_guid(); begin - l_plsql_block := 'begin insert into test_results select * from table( {a_run_command} ); commit; end;'; + l_plsql_block := q'[ + begin + ut3_develop.ut_runner.coverage_start(']'||rawtohex(l_coverage_id)||q'['); + insert into test_results select * from table( {a_run_command} ); + commit; + end;]'; l_plsql_block := replace(l_plsql_block,'{a_run_command}',a_run_command); - return run_code_as_job( l_plsql_block ); + l_result_clob := run_code_as_job( l_plsql_block ); + copy_coverage_data_to_ut3(l_coverage_id); + return l_result_clob; end; procedure create_dup_object_name is From 311d5a7250e94decfa79f3a65280153fe5fe95d3 Mon Sep 17 00:00:00 2001 From: Felipe Zorzo Date: Sat, 26 Feb 2022 16:18:03 -0300 Subject: [PATCH 018/187] Fix links to SonarCloud projects and SonarQube documentation --- docs/index.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/reporters.md | 2 +- readme.md | 2 +- source/reporters/ut_coverage_sonar_reporter.tpb | 6 +++--- source/reporters/ut_coverage_sonar_reporter.tps | 2 +- source/reporters/ut_coveralls_reporter.tps | 2 +- source/reporters/ut_sonar_test_reporter.tpb | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/index.md b/docs/index.md index 537da5148..b079557ed 100644 --- a/docs/index.md +++ b/docs/index.md @@ -31,7 +31,7 @@ The framework follows industry standards and best patterns of modern Unit Testin Have a look at our [demo project](https://github.com/utPLSQL/utPLSQL-demo-project/). -It uses [Travis CI](https://travis-ci.org/utPLSQL/utPLSQL-demo-project) to build on every commit, runs all tests, publishes test results and code coverage to [SonarQube](https://sonarqube.com/dashboard?id=utPLSQL%3AutPLSQL-demo-project%3Adevelop). +It uses [Travis CI](https://travis-ci.org/utPLSQL/utPLSQL-demo-project) to build on every commit, runs all tests, publishes test results and code coverage to [SonarCloud](https://sonarcloud.io/project/overview?id=utPLSQL:utPLSQL-demo-project). # Three steps diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 0fabf61bd..0da111301 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -17,7 +17,7 @@ To obtain information about code coverage for unit tests, run utPLSQL with one o The following code coverage reporters are supplied with utPLSQL: * `ut_coverage_html_reporter` - generates a HTML coverage report providing summary and detailed information on code coverage. The HTML reporter is based on the open-source [simplecov-html](https://github.com/colszowka/simplecov-html) reporter for Ruby. It includes source code of the code that was covered (if possible) * `ut_coveralls_reporter` - generates a [Coveralls compatible JSON](https://coveralls.zendesk.com/hc/en-us/articles/201774865-API-Introduction) coverage report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by cloud services like [Coveralls](https://coveralls.io) -* `ut_coverage_sonar_reporter` - generates a [Sonar Compatible XML](https://docs.sonarqube.org/display/SONAR/Generic+Test+Data) coverage report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by services like [SonarQube/SonarCloud](https://about.sonarcloud.io/) +* `ut_coverage_sonar_reporter` - generates a [Sonar Compatible XML](https://docs.sonarqube.org/latest/analysis/generic-test/) coverage report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by services like [SonarQube](https://www.sonarqube.org/) and [SonarCloud](https://about.sonarcloud.io/) * `ut_coverage_cobertura_reporter` - generates a basic Cobertura coverage (http://cobertura.sourceforge.net/xml/coverage-04.dtd) report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by services like TFS and Jenkins. Check this link for an example of XML generated by Java: https://raw.githubusercontent.com/jenkinsci/cobertura-plugin/master/src/test/resources/hudson/plugins/cobertura/coverage-with-data.xml ## Security model diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index ebc28ec38..176027a99 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -84,7 +84,7 @@ Example of failure report details # Sonar test reporter -If you are using [SonarQube](https://about.sonarqube.com/) to do static code analysis for you PLSQL projects, your code analysis can benefit from code coverage and test results. +If you are using [SonarQube](https://www.sonarqube.org/) or [SonarCloud](https://about.sonarcloud.io/) to do static code analysis for you PLSQL projects, your code analysis can benefit from code coverage and test results. utPLSQL provides two reporters to for SonarQube: - `ut_sonar_test_reporter` - provides an XML output of each test executed per each project test file (package) - `ut_coverage_sonar_reporter` - provides XML output of code coverage per each project source file diff --git a/readme.md b/readme.md index f96b88d7f..141c68ffe 100644 --- a/readme.md +++ b/readme.md @@ -9,7 +9,7 @@ [![twitter](https://img.shields.io/twitter/follow/utPLSQL.svg?style=social&label=Follow)](https://twitter.com/utPLSQL) [![build](https://github.com/utPLSQL/utPLSQL/actions/workflows/build.yml/badge.svg)](https://github.com/utPLSQL/utPLSQL/actions/workflows/build.yml) -[![QualityGate](https://sonarcloud.io/api/project_badges/measure?project=utPLSQL&metric=sqale_rating)](https://sonarcloud.io/dashboard/index?id=utPLSQL) +[![QualityGate](https://sonarcloud.io/api/project_badges/measure?project=utPLSQL&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=utPLSQL) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=utPLSQL&metric=coverage)](https://sonarcloud.io/summary/new_code?id=utPLSQL) ---------- diff --git a/source/reporters/ut_coverage_sonar_reporter.tpb b/source/reporters/ut_coverage_sonar_reporter.tpb index 4bde1a88d..8ee78dc24 100644 --- a/source/reporters/ut_coverage_sonar_reporter.tpb +++ b/source/reporters/ut_coverage_sonar_reporter.tpb @@ -96,9 +96,9 @@ create or replace type body ut_coverage_sonar_reporter is overriding member function get_description return varchar2 as begin - return 'Generates a JSON coverage report providing information on code coverage with line numbers.' || chr(10) || - 'Designed for [SonarQube](https://about.sonarqube.com/) to report coverage.' || chr(10) || - 'JSON format returned conforms with the Sonar specification: https://docs.sonarqube.org/display/SONAR/Generic+Test+Data'; + return 'Generates a XML coverage report providing information on code coverage with line numbers.' || chr(10) || + 'Designed for [SonarQube](https://www.sonarqube.org/) to report coverage.' || chr(10) || + 'XML format returned conforms with the Sonar specification: https://docs.sonarqube.org/latest/analysis/generic-test/'; end; end; diff --git a/source/reporters/ut_coverage_sonar_reporter.tps b/source/reporters/ut_coverage_sonar_reporter.tps index f3076368f..715bdefd2 100644 --- a/source/reporters/ut_coverage_sonar_reporter.tps +++ b/source/reporters/ut_coverage_sonar_reporter.tps @@ -18,7 +18,7 @@ create or replace type ut_coverage_sonar_reporter under ut_coverage_reporter_bas /** * Builds a coverage XML report that follows rules described in - * https://docs.sonarqube.org/display/SONAR/Generic+Test+Data + * https://docs.sonarqube.org/latest/analysis/generic-test/ */ constructor function ut_coverage_sonar_reporter( self in out nocopy ut_coverage_sonar_reporter diff --git a/source/reporters/ut_coveralls_reporter.tps b/source/reporters/ut_coveralls_reporter.tps index f3cad3a4e..74363b751 100644 --- a/source/reporters/ut_coveralls_reporter.tps +++ b/source/reporters/ut_coveralls_reporter.tps @@ -18,7 +18,7 @@ create or replace type ut_coveralls_reporter under ut_coverage_reporter_base( /** * Builds a coverage XML report that follows rules described in - * https://docs.sonarqube.org/display/SONAR/Generic+Test+Data + * https://docs.coveralls.io/api-introduction */ constructor function ut_coveralls_reporter( self in out nocopy ut_coveralls_reporter diff --git a/source/reporters/ut_sonar_test_reporter.tpb b/source/reporters/ut_sonar_test_reporter.tpb index 20624fae9..a3ec72241 100644 --- a/source/reporters/ut_sonar_test_reporter.tpb +++ b/source/reporters/ut_sonar_test_reporter.tpb @@ -106,9 +106,9 @@ create or replace type body ut_sonar_test_reporter is overriding member function get_description return varchar2 as begin - return 'Generates a JSON report providing detailed information on test execution.' || chr(10) || - 'Designed for [SonarQube](https://about.sonarqube.com/) to report test execution.' || chr(10) || - 'JSON format returned conforms with the Sonar specification: https://docs.sonarqube.org/display/SONAR/Generic+Test+Data'; + return 'Generates a XML report providing detailed information on test execution.' || chr(10) || + 'Designed for [SonarQube](https://www.sonarqube.org/) to report test execution.' || chr(10) || + 'XML format returned conforms with the Sonar specification: https://docs.sonarqube.org/latest/analysis/generic-test/'; end; end; From 25af9edbcd5b7a9627c667225105bf70ede6a010 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 26 Feb 2022 22:11:18 +0000 Subject: [PATCH 019/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index ceff64be9..c8e1f017a 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 110f3197c..7b95eee4f 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 7b4a67750..2e0d31c99 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 4fc3f72f7..5cbe4dbda 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 2380c0473..695a3e0fb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 93da6013e..6f382970a 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index f28e0cd5b..192ea7b8d 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index b5b7cb286..4c203e73d 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index f6cdcbc93..2c59a8126 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses DBMS_PROFILER package provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index fd6cc6f98..484681b9b 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 3bd3e090b..1000b7747 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index b5b9d09f1..548359f7f 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 9f92b7c6a..c4c5ac903 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index aac098805..e8d36cd72 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 1e0f134b6..5777b36b0 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 73e469da3..4bbd665cd 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index f0ef68ab2..631dc1d56 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3896--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index b9917f2a7..8ef9cff39 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3896-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3905-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 969f52ee0b374a3a491526f49dad09baa9724629 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 27 Feb 2022 00:26:52 +0200 Subject: [PATCH 020/187] Testing local html validator (as a container) --- .github/scripts/validate_report_files.sh | 2 +- .github/workflows/build.yml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/scripts/validate_report_files.sh b/.github/scripts/validate_report_files.sh index 59376a174..722a9220a 100755 --- a/.github/scripts/validate_report_files.sh +++ b/.github/scripts/validate_report_files.sh @@ -7,7 +7,7 @@ XSD_DIR="${SCRIPT_DIR}/xsd" XML_JAR_DIR="${SCRIPT_DIR}/lib" #XML Validator XML_VALIDATOR="$XML_JAR_DIR/xml_validator.jar" -HTML_VALIDATOR_URL="https://validator.w3.org/nu/" +HTML_VALIDATOR_URL="http://localhost:8888/" HTML_FILENAME="coverage.html" declare -A XML_FILES diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf36d4c55..816f0ab39 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,6 +60,10 @@ jobs: oracle-base: '/opt/oracle' services: + html_checker: + image: ghcr.io/validator/validator:latest + options: >- + -p 8888:8888 oracle: image: ${{matrix.oracle-version}} env: From b4d72e391f2e7f5d920ec08744a30431ef201027 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 26 Feb 2022 23:07:21 +0000 Subject: [PATCH 021/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index c8e1f017a..002c7ee3b 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 7b95eee4f..fa782b2ad 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 2e0d31c99..400ead44a 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 5cbe4dbda..11beecd51 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 695a3e0fb..89c4b41b4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 6f382970a..d7c5b6bb0 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 192ea7b8d..c36b06450 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 4c203e73d..35485e4db 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 2c59a8126..664fb78cb 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses DBMS_PROFILER package provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 484681b9b..dbd70d9a0 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 1000b7747..96fd4e2c4 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 548359f7f..548994f5b 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index c4c5ac903..88b4d0942 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index e8d36cd72..6140f2cc7 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 5777b36b0..a6f37d0a6 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 4bbd665cd..88fa7ad0c 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 631dc1d56..1cc6dd58b 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3905--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 8ef9cff39..a19bd82dd 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3905-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3908-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From a84246be72ffa0196d4ebb408b1afda0966158c9 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 27 Feb 2022 17:47:35 +0000 Subject: [PATCH 022/187] Adding extra tests for code coverage --- source/core/coverage/ut_coverage.pkb | 4 +- test/ut3_tester_helper/coverage_helper.pkb | 40 +++++++++ test/ut3_tester_helper/coverage_helper.pks | 1 + .../test_coverage/test_extended_coverage.pkb | 84 ++++++++++++++++++- .../test_coverage/test_extended_coverage.pks | 28 ++++++- 5 files changed, 149 insertions(+), 8 deletions(-) diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index eeedfc665..b606a6dc1 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -102,7 +102,7 @@ create or replace package body ut_coverage is on s.name = f.object_name and s.type = f.object_type and s.owner = f.object_owner'; - elsif a_coverage_options.include_schema_expr is not null or a_coverage_options.include_object_expr is not null then + elsif coalesce(a_coverage_options.include_schema_expr,a_coverage_options.include_object_expr) is not null then l_full_name := q'[lower(s.type||' '||s.owner||'.'||s.name)]'; if a_coverage_options.include_schema_expr is not null then l_filters := q'[and regexp_like(s.owner,:a_include_schema_expr,'i')]'; @@ -183,7 +183,7 @@ create or replace package body ut_coverage is open l_cursor for l_sql using a_coverage_options.file_mappings,a_coverage_options.exclude_schema_expr, a_coverage_options.exclude_object_expr,l_excluded_objects, l_skip_objects; - elsif a_coverage_options.include_schema_expr is not null or a_coverage_options.include_object_expr is not null then + elsif coalesce(a_coverage_options.include_schema_expr,a_coverage_options.include_object_expr) is not null then open l_cursor for l_sql using a_coverage_options.include_schema_expr,a_coverage_options.include_object_expr, a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr, l_excluded_objects,l_skip_objects; diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index ab5a09515..e59fde122 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -435,6 +435,46 @@ create or replace package body coverage_helper is commit; end; + function gather_coverage_on_coverage( a_cov_options varchar2) return clob is + pragma autonomous_transaction; + l_plsql_block varchar2(32767); + l_result_clob clob; + l_coverage_id raw(32) := sys_guid(); + begin + l_plsql_block := q'[ + declare + l_coverage_options ut3_develop.ut_coverage_options; + l_coverage_run_id raw(32) := ']'||rawtohex(l_coverage_id)||q'['; + l_result ut3_develop.ut_coverage.t_coverage; + begin + ut3_develop.ut_runner.coverage_start(l_coverage_run_id); + ut3_develop.ut_coverage.set_develop_mode(a_develop_mode => true); + l_coverage_options := {a_cov_options}; + l_result := ut3_develop.ut_coverage.get_coverage_data(l_coverage_options); + ut3_develop.ut_coverage.set_develop_mode(a_develop_mode => false); + ut3_develop.ut_runner.coverage_stop(); + insert into test_results select owner||'.'||name from ut3_develop.ut_coverage_sources_tmp; + commit; + end;]'; + l_plsql_block := replace(l_plsql_block,'{a_cov_options}',a_cov_options); + run_job_and_wait_for_finish( l_plsql_block ); + execute immediate q'[ + declare + l_results ut3_develop.ut_varchar2_list; + begin + select * + bulk collect into l_results + from test_results; + delete from test_results; + commit; + :clob_results := ut3_tester_helper.main_helper.table_to_clob(l_results); + end; + ]' + using out l_result_clob; + copy_coverage_data_to_ut3(l_coverage_id); + return l_result_clob; + end; + function run_tests_as_job( a_run_command varchar2 ) return clob is l_plsql_block varchar2(32767); l_result_clob clob; diff --git a/test/ut3_tester_helper/coverage_helper.pks b/test/ut3_tester_helper/coverage_helper.pks index c5e862612..8d2c1c150 100644 --- a/test/ut3_tester_helper/coverage_helper.pks +++ b/test/ut3_tester_helper/coverage_helper.pks @@ -23,6 +23,7 @@ create or replace package coverage_helper is procedure run_standalone_coverage(a_coverage_run_id raw, a_input integer); procedure run_coverage_job(a_coverage_run_id raw, a_input integer); + function gather_coverage_on_coverage( a_cov_options varchar2) return clob; function run_tests_as_job( a_run_command varchar2 ) return clob; function run_code_as_job( a_plsql_block varchar2 ) return clob; procedure create_test_results_table; diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb index f14eac984..d22570df0 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb @@ -141,7 +141,7 @@ create or replace package body test_extended_coverage is --Arrange l_expected := '%' || '%%'; - l_not_expected := '%' || + l_not_expected := '%' || '%%'; --Act l_actual := @@ -195,7 +195,7 @@ create or replace package body test_extended_coverage is --Arrange l_expected := '%' || '%%'; - l_not_expected := '%' || + l_not_expected := '%' || '%%'; --Act l_actual := @@ -214,5 +214,85 @@ create or replace package body test_extended_coverage is ut.expect(l_actual).not_to_be_like(l_not_expected); end; + procedure cove_rgx_inc_schema_norun is + l_expected clob; + l_not_expected clob; + l_actual clob; + begin + --Arrange + l_expected := '%UT3_DEVELOP.REGEX_DUMMY_COV%'; + l_not_expected := '%UT3_TESTER_HELPER.REGEX123_DUMMY_COV%'; + --Act + l_actual := ut3_tester_helper.coverage_helper.gather_coverage_on_coverage( + q'[ut3_develop.ut_coverage_options( + coverage_run_id => l_coverage_run_id, + include_schema_expr => '^ut3_develop' + )]'); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like(l_not_expected); + end; + + procedure cove_rgx_inc_object_norun is + l_expected clob; + l_not_expected clob; + l_actual clob; + begin + --Arrange + l_expected := '%UT3_DEVELOP.REGEX123_DUMMY_COV%'; + l_not_expected := '%UT3_DEVELOP.REGEX_DUMMY_COV%'; + --Act + l_actual := ut3_tester_helper.coverage_helper.gather_coverage_on_coverage( + q'[ut3_develop.ut_coverage_options( + coverage_run_id => l_coverage_run_id, + include_object_expr => 'regex123' + )]'); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like(l_not_expected); + end; + + procedure cove_rgx_exc_schema_norun is + l_expected clob; + l_not_expected clob; + l_actual clob; + begin + --Arrange + l_expected := '%UT3_DEVELOP.REGEX_DUMMY_COV%'; + l_not_expected := '%UT3_TESTER_HELPER.REGEX_DUMMY_COV%'; + --Act + l_actual := ut3_tester_helper.coverage_helper.gather_coverage_on_coverage( + q'[ut3_develop.ut_coverage_options( + coverage_run_id => l_coverage_run_id, + schema_names => ut3_develop.ut_varchar2_rows( 'UT3_DEVELOP','UT3_TESTER_HELPER' ), + exclude_schema_expr => '^ut3_tester', + exclude_objects => ut3_develop.ut_varchar2_rows( 'ut3_develop.regex_dummy_cov' ) + )]'); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like(l_not_expected); + end; + + procedure cove_rgx_exc_object_norun is + l_expected clob; + l_not_expected clob; + l_actual clob; + begin + --Arrange + l_expected := '%UT3_DEVELOP.REGEX_DUMMY_COV%'; + l_not_expected := '%UT3_DEVELOP.REGEX123_DUMMY_COV%'; + --Act + l_actual := ut3_tester_helper.coverage_helper.gather_coverage_on_coverage( + q'[ut3_develop.ut_coverage_options( + coverage_run_id => l_coverage_run_id, + schema_names => ut3_develop.ut_varchar2_rows( 'UT3_DEVELOP' ), + exclude_object_expr => 'regex123', + exclude_objects => ut3_develop.ut_varchar2_rows( 'ut3_develop.regex_dummy_cov' ) + )]'); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like(l_not_expected); + end; + end; / diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks index 99d7c5db4..108c5ae52 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks @@ -20,23 +20,43 @@ create or replace package test_extended_coverage is --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) - --%test(Collect coverage for objects with schema regex include) + --%test(Collect coverage for objects with schema regex include with ut_run) procedure coverage_regex_include_schema; --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) - --%test(Collect coverage for objects with object regex include) + --%test(Collect coverage for objects with object regex include with ut_run) procedure coverage_regex_include_object; --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) - --%test(Collect coverage for objects with schema regex exclude) + --%test(Collect coverage for objects with schema regex exclude with ut_run) procedure coverage_regex_exclude_schema; --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) - --%test(Collect coverage for objects with object regex exclude) + --%test(Collect coverage for objects with object regex exclude with ut_run) procedure coverage_regex_exclude_object; + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) + --%test(Collect coverage for objects with schema regex include without ut_run) + procedure cove_rgx_inc_schema_norun; + + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) + --%test(Collect coverage for objects with object regex include without ut_run) + procedure cove_rgx_inc_object_norun; + + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) + --%test(Collect coverage for objects with schema regex exclude without ut_run) + procedure cove_rgx_exc_schema_norun; + + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) + --%test(Collect coverage for objects with object regex exclude without ut_run) + procedure cove_rgx_exc_object_norun; + end; / From 090207c6dadf985d9c88ec646c0fee327785d5fd Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 27 Feb 2022 19:52:16 +0000 Subject: [PATCH 023/187] Added extra coverage for file mapping. --- .../test_coverage/test_extended_coverage.pkb | 17 +++++++++++++++++ .../test_coverage/test_extended_coverage.pks | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb index d22570df0..3c8781bc4 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb @@ -294,5 +294,22 @@ create or replace package body test_extended_coverage is ut.expect(l_actual).not_to_be_like(l_not_expected); end; + procedure cov_file_mapping_no_utrun is + l_expected clob; + l_not_expected clob; + l_actual clob; + begin + --Arrange + l_expected := '%UT3_DEVELOP.REGEX_DUMMY_COV%'; + --Act + l_actual := ut3_tester_helper.coverage_helper.gather_coverage_on_coverage( + q'[ut3_develop.ut_coverage_options( + coverage_run_id => l_coverage_run_id, + file_mappings => ut3_develop.ut_file_mappings( ut3_develop.ut_file_mapping('C:\tests\helpers\core.pkb','UT3_DEVELOP','REGEX_DUMMY_COV','PACKAGE BODY')) + )]'); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + end; + end; / diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks index 108c5ae52..82b19fbed 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pks @@ -58,5 +58,9 @@ create or replace package test_extended_coverage is --%test(Collect coverage for objects with object regex exclude without ut_run) procedure cove_rgx_exc_object_norun; + --%beforetest(ut3_tester_helper.coverage_helper.create_regex_dummy_cov) + --%aftertest(ut3_tester_helper.coverage_helper.drop_regex_dummy_cov) + --%test(Collect coverage for file mapping without ut_run) + procedure cov_file_mapping_no_utrun; end; / From df31fba9decf27bd5308a1df49655200de5238b1 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 28 Feb 2022 01:45:42 +0200 Subject: [PATCH 024/187] g_coverage_run_id is now reset after coverage collection is stopped. --- source/core/coverage/ut_coverage.pkb | 1 + 1 file changed, 1 insertion(+) diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index b606a6dc1..1bd88a186 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -256,6 +256,7 @@ create or replace package body ut_coverage is begin if not is_develop_mode() then g_is_started := false; + g_coverage_run_id := null; ut_coverage_helper_block.coverage_stop(); ut_coverage_helper_profiler.coverage_stop(); end if; From 0a2f478aa0c68753be358db0c9a4857a25c1361b Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 28 Feb 2022 01:47:10 +0200 Subject: [PATCH 025/187] Improved coverage collection scope and stability on self-tests for utPLSQL --- test/ut3_tester_helper/coverage_helper.pkb | 22 +++++++++++++------ .../test_coverage/test_proftab_coverage.pkb | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index e59fde122..fdfa32364 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -341,7 +341,7 @@ create or replace package body coverage_helper is e_exists exception; pragma exception_init ( e_exists, -955 ); begin - execute immediate 'create table test_results (text varchar2(4000))'; + execute immediate 'create table test_results (id integer, text varchar2(4000))'; exception when e_exists then null; @@ -368,9 +368,10 @@ create or replace package body coverage_helper is declare l_results ut3_develop.ut_varchar2_list; begin - select * + select text bulk collect into l_results - from test_results; + from test_results + order by id; delete from test_results; commit; :clob_results := ut3_tester_helper.main_helper.table_to_clob(l_results); @@ -453,7 +454,7 @@ create or replace package body coverage_helper is l_result := ut3_develop.ut_coverage.get_coverage_data(l_coverage_options); ut3_develop.ut_coverage.set_develop_mode(a_develop_mode => false); ut3_develop.ut_runner.coverage_stop(); - insert into test_results select owner||'.'||name from ut3_develop.ut_coverage_sources_tmp; + insert into test_results select rownum, owner||'.'||name from ut3_develop.ut_coverage_sources_tmp; commit; end;]'; l_plsql_block := replace(l_plsql_block,'{a_cov_options}',a_cov_options); @@ -462,9 +463,10 @@ create or replace package body coverage_helper is declare l_results ut3_develop.ut_varchar2_list; begin - select * + select text bulk collect into l_results - from test_results; + from test_results + order by id; delete from test_results; commit; :clob_results := ut3_tester_helper.main_helper.table_to_clob(l_results); @@ -483,7 +485,13 @@ create or replace package body coverage_helper is l_plsql_block := q'[ begin ut3_develop.ut_runner.coverage_start(']'||rawtohex(l_coverage_id)||q'['); - insert into test_results select * from table( {a_run_command} ); + ut3_develop.ut_coverage.set_develop_mode(a_develop_mode => true); + --gather coverage on the command executed + begin {a_run_command}; end; + ut3_develop.ut_coverage.set_develop_mode(a_develop_mode => false); + ut3_develop.ut_runner.coverage_stop(); + --get the actual results of the command gathering the coverage + insert into test_results select rownum as id, x.* from table( {a_run_command} ) x; commit; end;]'; l_plsql_block := replace(l_plsql_block,'{a_run_command}',a_run_command); diff --git a/test/ut3_user/reporters/test_coverage/test_proftab_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_proftab_coverage.pkb index 7256fc202..7cad0a67e 100644 --- a/test/ut3_user/reporters/test_coverage/test_proftab_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_proftab_coverage.pkb @@ -137,14 +137,14 @@ create or replace package body test_proftab_coverage is --Act insert into test_results - select * + select rownum, x.* from table( ut3_develop.ut.run( a_path => 'ut3_develop:coverage_testing', a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.{p}' ) ) - ); + ) x; commit; end; ]'; From bd05e4cb19ea7a77ad1bc629124e58a714c13226 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 2 Mar 2022 01:23:47 +0200 Subject: [PATCH 026/187] Coverage documentation improvements. Fixed datatype for ut_coverage_options.tps attributes Formatting. --- docs/userguide/coverage.md | 122 ++++++++++++++-------- source/core/coverage/ut_coverage.pkb | 21 ++-- source/core/types/ut_coverage_options.tps | 8 +- 3 files changed, 91 insertions(+), 60 deletions(-) diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index b09eaf124..26b00bd85 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,7 +1,7 @@ ![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) # Coverage -utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses DBMS_PROFILER package provided with Oracle database. +utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: * package bodies * type bodies @@ -15,7 +15,7 @@ Code coverage is gathered for the following source types: To obtain information about code coverage for unit tests, run utPLSQL with one of built-in code coverage reporters. The following code coverage reporters are supplied with utPLSQL: -* `ut_coverage_html_reporter` - generates a HTML coverage report providing summary and detailed information on code coverage. The HTML reporter is based on the open-source [simplecov-html](https://github.com/colszowka/simplecov-html) reporter for Ruby. It includes source code of the code that was covered (if possible) +* `ut_coverage_html_reporter` - generates a HTML coverage report providing summary and detailed information on code coverage. The HTML reporter is based on the open-source [simplecov-html](https://github.com/colszowka/simplecov-html) reporter for Ruby. It includes source code of the code that was covered (if the code is accessible for test user) * `ut_coveralls_reporter` - generates a [Coveralls compatible JSON](https://coveralls.zendesk.com/hc/en-us/articles/201774865-API-Introduction) coverage report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by cloud services like [Coveralls](https://coveralls.io) * `ut_coverage_sonar_reporter` - generates a [Sonar Compatible XML](https://docs.sonarqube.org/latest/analysis/generic-test/) coverage report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by services like [SonarQube](https://www.sonarqube.org/) and [SonarCloud](https://about.sonarcloud.io/) * `ut_coverage_cobertura_reporter` - generates a basic Cobertura coverage (http://cobertura.sourceforge.net/xml/coverage-04.dtd) report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by services like TFS and Jenkins. Check this link for an example of XML generated by Java: https://raw.githubusercontent.com/jenkinsci/cobertura-plugin/master/src/test/resources/hudson/plugins/cobertura/coverage-with-data.xml @@ -30,7 +30,7 @@ In order to be able to gather coverage information, the user executing unit test If you have `execute` privilege on the code that is being tested, but do not have `create any procedure` system privilege, then the code that is being tested will be reported as not covered (coverage = 0%). If you have `execute` privilege only on the unit tests, but do not have `execute` privilege on the code that is being tested, the code will not be reported by coverage - as if it did not exist in the database. -If the code that is being tested is complied as NATIVE, the code coverage will not be reported as well. +If the code that is being tested is compiled as NATIVE, the code coverage will not be reported as well. ## Running unit tests with coverage Using the code coverage functionality is as easy as using any other [reporter](reporters.md) for the utPLSQL test-run. You just run your tests from your preferred SQL tool and save the reporter results to a file. @@ -65,6 +65,7 @@ Due to security model of `dbms_plsql_code_coverage` package, utPLSQL grants acce The access and synonyms will be public when using the headless installation. This approach avoids complexity of forcing every user of utPLSQL framework to create tables on their own. Sample output: + ![Package Coverage Summary](../images/extended_coverage_html_summary.png) ![Line Coverage Details](../images/extended_coverage_html_line.png) @@ -128,42 +129,80 @@ exec ut.run('unit_test_schema', ut_coverage_html_reporter(), a_coverage_schemes #### Filtering objects in coverage reports -There are six options that can be used to narrow down the scope of coverage report: -- `a_include_objects` - list of `[object_owner.].object_name` to be included in the coverage report. -- `a_exclude_objects` - list of `[object_owner.].object_name` to be excluded from the coverage report -- `a_include_schema_expr` - string of regex expression of schemas to be included in the coverage report. It will override `a_include_objects` for example : - ```sql - a_include_schema_expr => '^ut3_develop', - a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) - ``` - Will result in showing coverage for all schemas that match regular expression `^ut3_develop` and ignore objectes defined by parameter `a_include_objects` - -- `a_include_object_expr` - string of regex expression of objects ( no schema names included ) to be included in the coverage report. It will override `a_include_objects` for example: - ```sql - a_include_object_expr => 'regex123', - a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) - ``` - Will result in showing coverage for all objects that name match regular expression `regex123` and ignore objectes defined by parameter `a_include_objects` - -- `a_exclude_schema_expr` - string of regex expression of schemas to be excluded from the coverage report. It will override `a_exclude_objects` for example: - ```sql - a_exclude_schema_expr => '^ut3_tester', - a_exclude_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.regex_dummy_cov' ) - ``` - Will result in showing coverage for all objects that schema is not matching regular expression `^ut3_tester` and ignore exclusion defined by parameter `a_exclude_objects` - -- `a_exclude_object_expr` - string of regex expression of objects to be excluded from the coverage report. It will override `a_exclude_objects` for example - ```sql - a_exclude_object_expr => 'regex123', - a_exclude_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.regex_dummy_cov' ) - ``` - Will result in showing coverage for all objects that name is not matching regular expression `regex123` and ignore exclusion defined by parameter `a_exclude_objects` - +There are multiple parameters that can be used to define the scope of coverage report: +- `a_source_file_mappings ( ut_file_mappings )` - map of filenames to database objects. It is used for file-based coverage - see below. +- `a_include_schema_expr ( varchar(4000) )` - string of regex expression of schemas to be included in the coverage report. +- `a_include_object_expr ( varchar(4000) )` - string of regex expression of objects ( without schema name ) to be included in the coverage report. +- `a_exclude_schema_expr ( varchar(4000) )` - string of regex expression of schemas to be excluded from the coverage report. +- `a_exclude_object_expr ( varchar(4000) )` - string of regex expression of objects to be excluded from the coverage report. +- `a_coverage_schemes ( ut_varchar2_list )` - List of database schema names to gather coverage on. +- `a_include_objects ( ut_varchar2_list )` - list of `[object_owner.]object_name` to be included in the coverage report. +- `a_exclude_objects ( ut_varchar2_list )` - list of `[object_owner.]object_name` to be excluded from the coverage report. You may specify both _include_ and _exclude_ options to gain more control over what needs to be included / excluded from the coverage report. -The object owner is optional in the object list. -If you do not provide an object owner, the _include_/_exclude_ list will be considered for every schema used for coverage gathering (as described above). +**Important notes** +The order of priority is for evaluation of include/exclude filter parameters is as follows. +- if `a_source_file_mappings` is defined then all include/exclude parameters are ignored (see section below for usage of `a_source_file_mappings` parameter ) +- else if `a_include_schema_expr` or `a_include_object_expr` parameter is specified then parameters `a_coverage_schemes` and `a_include_objects` are ignored +- else if `a_include_objects` is specified then the coverage is gathered only on specified database objects. + - if `a_coverage_schemes` is specified then those schemas are used for objects in `a_include_objects` without schema name + - if `a_coverage_schemes` is not specified then schema from paths (`a_paths`) parameter are used for objects in `a_include_objects` without schema name +- else if, only the `a_coverage_schemes` is specified then the coverage is gathered only on specified database schemas +- else if no coverage specific parameters are provided coverage is gathered on all schemas specified in paths passed to run procedure +- else if no paths were specified, the coverage is gathered on current schema of the session running the tests + + +Example: Limiting coverage by schema regex. +```sql +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_include_schema_expr => '^ut3_develop' + ); +end; +``` +Will result in showing coverage for all schemas that match regular expression `^ut3_develop` + +```sql +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_include_schema_expr => '^ut3_develop', a_include_objects => ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) + ); +end; +``` +Will result in showing coverage for all schemas that match regular expression `^ut3_develop`. +Will ignore the `a_include_objects` parameter + +```sql +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_include_object_expr => 'regex123', a_include_objects => ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) + ); +end; +``` +Will result in showing coverage for all objects that name match regular expression `regex123`. +Will ignore the `a_include_objects` parameter. + +```sql +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_exclude_schema_expr => '^ut3_tester', a_exclude_objects => ut_varchar2_list( 'regex_dummy_cov' ) + ); +end; +``` +Will result in showing coverage for objects in all schema except schemas that are matching regular expression `^ut3_tester` +Will ignore exclusion defined by parameter `a_exclude_objects` + +```sql +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_exclude_object_expr => 'regex123', a_exclude_objects => ut_varchar2_list( 'regex_dummy_cov' ) + ); +end; +``` +Will result in showing coverage for all objects that name is not matching regular expression `regex123`. +Will ignore exclusion defined by parameter `a_exclude_objects`. + Example: Limiting coverage by object name, for tested code located in the same schema as the unit tests. ```sql @@ -214,7 +253,8 @@ Executes test `test_award_bonus` in schema `unit_test_schema`. Coverage will be **Note** > When running coverage on schema objects, all source code of package bodies, functions, procedures, type bodies and triggers that were not executed will be reported as having 0% code coverage and all source code lines will show as uncovered. -> This is different than the behavior when gathering coverage on project files. +> This is different from the behavior when gathering coverage on project files. + ### Project based Coverage @@ -687,7 +727,7 @@ begin end; ``` -## Reporting coverage outside of utPLSQL +## Reporting coverage outside utPLSQL and in parallel sessions utPSLQL allows fo standalone reporting code coverage across multiple database sessions. This functionality enables coverage reporting for external testing tools. @@ -811,9 +851,3 @@ If the identifier is not unique, previous runs of coverage that used the same `c For details on the meaning of `schema_names`, `exclude_objects`, `include_objects`, `file_mappings` see sections above. Note that data-types of include/exclude/schema lists are different when calling `ut.run` vs. calling `get_report/get_report_cursor`. -The order of priority is for evaluation of include/exclude is as follows. -- if `file_mappings` is specified then all include/exclude parameters are ignored -- else if `..._expr` is specified then include_objects/exclude_objects parameters are ignored -- else if `schema_names` is specified then the coverage is gathered on all object of specified schemas -- else coverage is gathered on all schemas specified in paths passed to run procedure -- if no paths were specified, the coverage is gathered on current schema of the session running the tests diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index 1bd88a186..f5eccc893 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -180,21 +180,18 @@ create or replace package body ut_coverage is ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_key_anyvalues().put('l_sql',l_sql) ); if a_coverage_options.file_mappings is not empty then - open l_cursor for l_sql using a_coverage_options.file_mappings,a_coverage_options.exclude_schema_expr, - a_coverage_options.exclude_object_expr,l_excluded_objects, - l_skip_objects; + open l_cursor for l_sql using a_coverage_options.file_mappings, a_coverage_options.exclude_schema_expr, + a_coverage_options.exclude_object_expr, l_excluded_objects, l_skip_objects; elsif coalesce(a_coverage_options.include_schema_expr,a_coverage_options.include_object_expr) is not null then - open l_cursor for l_sql using a_coverage_options.include_schema_expr,a_coverage_options.include_object_expr, - a_coverage_options.exclude_schema_expr,a_coverage_options.exclude_object_expr, - l_excluded_objects,l_skip_objects; + open l_cursor for l_sql using a_coverage_options.include_schema_expr, a_coverage_options.include_object_expr, + a_coverage_options.exclude_schema_expr, a_coverage_options.exclude_object_expr, + l_excluded_objects, l_skip_objects; elsif a_coverage_options.include_objects is not empty then - open l_cursor for l_sql using a_coverage_options.include_objects,a_coverage_options.exclude_schema_expr, - a_coverage_options.exclude_object_expr,l_excluded_objects, - l_skip_objects; + open l_cursor for l_sql using a_coverage_options.include_objects, a_coverage_options.exclude_schema_expr, + a_coverage_options.exclude_object_expr, l_excluded_objects, l_skip_objects; else - open l_cursor for l_sql using a_coverage_options.schema_names,a_coverage_options.exclude_schema_expr, - a_coverage_options.exclude_object_expr,l_excluded_objects, - l_skip_objects; + open l_cursor for l_sql using a_coverage_options.schema_names, a_coverage_options.exclude_schema_expr, + a_coverage_options.exclude_object_expr, l_excluded_objects, l_skip_objects; end if; return l_cursor; end; diff --git a/source/core/types/ut_coverage_options.tps b/source/core/types/ut_coverage_options.tps index 245539179..a8e3d5129 100644 --- a/source/core/types/ut_coverage_options.tps +++ b/source/core/types/ut_coverage_options.tps @@ -21,10 +21,10 @@ create or replace type ut_coverage_options force as object ( exclude_objects ut_object_names, include_objects ut_object_names, file_mappings ut_file_mappings, - include_schema_expr varchar2(32767), - include_object_expr varchar2(32767), - exclude_schema_expr varchar2(32767), - exclude_object_expr varchar2(32767), + include_schema_expr varchar2(4000), + include_object_expr varchar2(4000), + exclude_schema_expr varchar2(4000), + exclude_object_expr varchar2(4000), constructor function ut_coverage_options( self in out nocopy ut_coverage_options, coverage_run_id raw, From 3b9b6260a75d47332611bce939f317b295a36ba7 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 2 Mar 2022 01:26:48 +0200 Subject: [PATCH 027/187] Coverage documentation improvements. --- docs/userguide/coverage.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 26b00bd85..20210ab47 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -152,6 +152,7 @@ The order of priority is for evaluation of include/exclude filter parameters is - else if no coverage specific parameters are provided coverage is gathered on all schemas specified in paths passed to run procedure - else if no paths were specified, the coverage is gathered on current schema of the session running the tests +The exclude parameters are not mutually-exclusive and can be mixed together. All of exclude parameters are always applied. Example: Limiting coverage by schema regex. ```sql From 3bdb9d05dffb2456d004849c870e660f8113a337 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 2 Mar 2022 12:57:42 +0200 Subject: [PATCH 028/187] Fixing flaky test --- test/ut3_user/expectations/binary/test_to_be_within.pkb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ut3_user/expectations/binary/test_to_be_within.pkb b/test/ut3_user/expectations/binary/test_to_be_within.pkb index d490a8280..032b684a5 100644 --- a/test/ut3_user/expectations/binary/test_to_be_within.pkb +++ b/test/ut3_user/expectations/binary/test_to_be_within.pkb @@ -199,7 +199,7 @@ create or replace package body test_to_be_within is begin --Arrange --Act - ut3_develop.ut.expect(sysdate).to_be_within(INTERVAL '1' MONTH).of_(sysdate+ 45); + ut3_develop.ut.expect(sysdate).to_be_within(INTERVAL '1' MONTH).of_(sysdate+ 46); --Assert l_expected_message := q'[Actual: % (date) was expected to be within 1 month of % (date)]'; l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1); From 1d86276dd76d64b87f81cebc3287397912ce1eaa Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 3 Mar 2022 00:24:21 +0200 Subject: [PATCH 029/187] Fix for unit-test results reporting into Sonar --- .github/variables/.env | 2 +- CONTRIBUTING.md | 2 +- docs/userguide/expectations.md | 8 ++--- docs/userguide/running-unit-tests.md | 2 +- test/install_ut3_tester_helper.sql | 2 +- test/run_tests.sh | 6 +++- .../annotations/test_annotation_manager.pkb | 16 ++++----- .../annotations/test_annotation_manager.pks | 8 ++--- test/ut3_tester_helper/main_helper.pkb | 12 +++---- test/ut3_tester_helper/main_helper.pks | 6 ++-- test/ut3_tester_helper/run_helper.pkb | 34 +++++++++---------- test/ut3_tester_helper/run_helper.pks | 4 +-- test/ut3_user/api/test_ut_run.pkb | 10 +++--- test/ut3_user/api/test_ut_run.pks | 20 +++++------ test/ut3_user/api/test_ut_runner.pkb | 24 ++++++------- test/ut3_user/expectations.pkb | 6 ++-- test/ut3_user/reporters.pkb | 2 +- .../reporters/test_documentation_reporter.pkb | 4 +-- .../reporters/test_teamcity_reporter.pkb | 34 +++++++++---------- 19 files changed, 103 insertions(+), 99 deletions(-) diff --git a/.github/variables/.env b/.github/variables/.env index 9f35a080c..e0a579d52 100644 --- a/.github/variables/.env +++ b/.github/variables/.env @@ -3,7 +3,7 @@ UT3_DEVELOP_SCHEMA=UT3_DEVELOP UT3_DEVELOP_SCHEMA_PASSWORD=ut3 UT3_RELEASE_VERSION_SCHEMA=UT3 UT3_RELEASE_VERSION_SCHEMA_PASSWORD=ut3 -UT3_USER='UT3$USER#' +UT3_USER='UT3_USER' UT3_USER_PASSWORD=ut3 UT3_TESTER=UT3_TESTER UT3_TESTER_PASSWORD=ut3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a65b7b685..41a86ecdd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,7 +46,7 @@ We use four different database accounts (users) for development process. * `ut3` - holds latest released version of utPLSQL. This schema holds the testing framework used for self-testing of utPLSQL development. * `ut3_develop` - holds the version of utPLSQL of your current branch. This is the schema you will be working on. * `ut3_tester` - holds unit test packages for development of utPLSQL. -* `ut3$user#` - used for testing accessibility to schema names with special characters. +* `ut3_user` - used for testing accessibility to schema names with special characters. * `ut3_tester_helper` - elevated privileges user, used for creating and dropping objects in other schemas during test run. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 96fd4e2c4..387149138 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -249,13 +249,13 @@ Failures: 1) the_test "Checking table ALL_USERS" Actual: 28 (number) was expected to equal: 0 (number) - at "UT3$USER#.SHARED_EXPECTATION_TEST.TABLE_IS_EMPTY", line 6 ut.expect( l_count, 'Checking table '||p_table_name ).to_equal(0); - at "UT3$USER#.SHARED_EXPECTATION_TEST.THE_TEST", line 11 + at "UT3_USER.SHARED_EXPECTATION_TEST.TABLE_IS_EMPTY", line 6 ut.expect( l_count, 'Checking table '||p_table_name ).to_equal(0); + at "UT3_USER.SHARED_EXPECTATION_TEST.THE_TEST", line 11 "Checking table ALL_TABLES" Actual: 55 (number) was expected to equal: 0 (number) - at "UT3$USER#.SHARED_EXPECTATION_TEST.TABLE_IS_EMPTY", line 6 ut.expect( l_count, 'Checking table '||p_table_name ).to_equal(0); - at "UT3$USER#.SHARED_EXPECTATION_TEST.THE_TEST", line 12 + at "UT3_USER.SHARED_EXPECTATION_TEST.TABLE_IS_EMPTY", line 6 ut.expect( l_count, 'Checking table '||p_table_name ).to_equal(0); + at "UT3_USER.SHARED_EXPECTATION_TEST.THE_TEST", line 12 Finished in .066344 seconds 1 tests, 1 failed, 0 errored, 0 disabled, 0 warning(s) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 88fa7ad0c..ec9cb0d83 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -195,7 +195,7 @@ declare begin l_reporter.set_reporter_id( 'd8a79e85915640a6a4e1698fdf90ba74' ); l_reporter.output_buffer.init(); - ut_runner.run (ut_varchar2_list ('ut3_tester','ut3$user#'), ut_reporters( l_reporter ) ); + ut_runner.run (ut_varchar2_list ('ut3_tester','ut3_user'), ut_reporters( l_reporter ) ); end; / ``` diff --git a/test/install_ut3_tester_helper.sql b/test/install_ut3_tester_helper.sql index d9aacdf36..b78221627 100644 --- a/test/install_ut3_tester_helper.sql +++ b/test/install_ut3_tester_helper.sql @@ -35,7 +35,7 @@ alter session set plsql_optimize_level=0; @@ut3_tester_helper/annotation_cache_helper.pks @@ut3_tester_helper/annotation_cache_helper.pkb create or replace synonym ut3_tester.annotation_cache_helper for ut3_tester_helper.annotation_cache_helper; -create or replace synonym ut3$user#.coverage_helper for ut3_tester_helper.coverage_helper; +create or replace synonym ut3_user.coverage_helper for ut3_tester_helper.coverage_helper; set linesize 200 set define on diff --git a/test/run_tests.sh b/test/run_tests.sh index 0edc4d96d..ae4a739d9 100755 --- a/test/run_tests.sh +++ b/test/run_tests.sh @@ -6,8 +6,12 @@ git rev-parse && cd "$(git rev-parse --show-cdup)" time utPLSQL-cli/bin/utplsql run ${UT3_TESTER_HELPER}/${UT3_TESTER_HELPER_PASSWORD}@${CONNECTION_STR} \ -source_path=source -owner=ut3_develop \ --p='ut3_tester,ut3$user#' \ +-p='ut3_tester,ut3_user' \ -test_path=test -c \ + -regex_expression="test/(\w+)(/(\w+))*/(\w+)\.(.{3})$" \ + -owner_subexpression=1 \ + -type_subexpression=5 \ + -name_subexpression=4 \ -f=ut_coverage_sonar_reporter -o=coverage.xml \ -f=ut_coverage_cobertura_reporter -o=cobertura.xml \ -f=ut_coverage_html_reporter -o=coverage.html \ diff --git a/test/ut3_tester/core/annotations/test_annotation_manager.pkb b/test/ut3_tester/core/annotations/test_annotation_manager.pkb index a5503f841..8eb3c2f6d 100644 --- a/test/ut3_tester/core/annotations/test_annotation_manager.pkb +++ b/test/ut3_tester/core/annotations/test_annotation_manager.pkb @@ -71,19 +71,19 @@ create or replace package body test_annotation_manager is exec_autonomous(q'[alter package dummy_test_package compile]'); end; - procedure create_parse_proc_as_ut3$user# is + procedure create_parse_proc_as_ut3_user is begin - ut3_tester_helper.main_helper.create_parse_proc_as_ut3$user#(); + ut3_tester_helper.main_helper.create_parse_proc_as_ut3_user(); end; - procedure parse_dummy_test_as_ut3$user# is + procedure parse_dummy_test_as_ut3_user is begin - ut3_tester_helper.main_helper.parse_dummy_test_as_ut3$user#(); + ut3_tester_helper.main_helper.parse_dummy_test_as_ut3_user(); end; - procedure drop_parse_proc_as_ut3$user# is + procedure drop_parse_proc_as_ut3_user is begin - ut3_tester_helper.main_helper.drop_parse_proc_as_ut3$user#(); + ut3_tester_helper.main_helper.drop_parse_proc_as_ut3_user(); exception when others then null; @@ -400,10 +400,10 @@ create or replace package body test_annotation_manager is l_start_date date; begin l_start_date := sysdate; - parse_dummy_test_as_ut3$user#(); + parse_dummy_test_as_ut3_user(); drop_dummy_test_package(); --Act - parse_dummy_test_as_ut3$user#(); + parse_dummy_test_as_ut3_user(); --Assert select count(1) into l_cache_count diff --git a/test/ut3_tester/core/annotations/test_annotation_manager.pks b/test/ut3_tester/core/annotations/test_annotation_manager.pks index 5d7464fd2..7207917f3 100644 --- a/test/ut3_tester/core/annotations/test_annotation_manager.pks +++ b/test/ut3_tester/core/annotations/test_annotation_manager.pks @@ -14,9 +14,9 @@ create or replace package test_annotation_manager is procedure create_dummy_test_package; - procedure create_parse_proc_as_ut3$user#; + procedure create_parse_proc_as_ut3_user; - procedure drop_parse_proc_as_ut3$user#; + procedure drop_parse_proc_as_ut3_user; procedure drop_dummy_test_package; @@ -85,8 +85,8 @@ create or replace package test_annotation_manager is procedure update_modified_test_package; --%test(Keeps annotations in cache when object was removed but user can't see whole schema) - --%beforetest(create_dummy_test_package,create_parse_proc_as_ut3$user#) - --%aftertest(drop_parse_proc_as_ut3$user#) + --%beforetest(create_dummy_test_package,create_parse_proc_as_ut3_user) + --%aftertest(drop_parse_proc_as_ut3_user) procedure keep_dropped_data_in_cache; --%test(Does not return data for dropped object) diff --git a/test/ut3_tester_helper/main_helper.pkb b/test/ut3_tester_helper/main_helper.pkb index 76245ea12..f1dadec66 100644 --- a/test/ut3_tester_helper/main_helper.pkb +++ b/test/ut3_tester_helper/main_helper.pkb @@ -104,26 +104,26 @@ create or replace package body main_helper is commit; end; - procedure create_parse_proc_as_ut3$user# is + procedure create_parse_proc_as_ut3_user is pragma autonomous_transaction; begin execute immediate q'[ - create or replace procedure ut3$user#.parse_annotations is + create or replace procedure ut3_user.parse_annotations is begin ut3_develop.ut_runner.rebuild_annotation_cache('UT3_TESTER','PACKAGE'); end;]'; end; - procedure drop_parse_proc_as_ut3$user# is + procedure drop_parse_proc_as_ut3_user is pragma autonomous_transaction; begin - execute immediate 'drop procedure ut3$user#.parse_annotations'; + execute immediate 'drop procedure ut3_user.parse_annotations'; end; - procedure parse_dummy_test_as_ut3$user# is + procedure parse_dummy_test_as_ut3_user is pragma autonomous_transaction; begin - execute immediate 'begin ut3$user#.parse_annotations; end;'; + execute immediate 'begin ut3_user.parse_annotations; end;'; end; procedure append_to_list(a_list in out nocopy ut3_develop.ut_varchar2_list, a_item varchar2) is diff --git a/test/ut3_tester_helper/main_helper.pks b/test/ut3_tester_helper/main_helper.pks index 6dd453446..7decad88d 100644 --- a/test/ut3_tester_helper/main_helper.pks +++ b/test/ut3_tester_helper/main_helper.pks @@ -29,11 +29,11 @@ create or replace package main_helper is procedure cleanup_annotation_cache; - procedure create_parse_proc_as_ut3$user#; + procedure create_parse_proc_as_ut3_user; - procedure drop_parse_proc_as_ut3$user#; + procedure drop_parse_proc_as_ut3_user; - procedure parse_dummy_test_as_ut3$user#; + procedure parse_dummy_test_as_ut3_user; procedure append_to_list(a_list in out nocopy ut3_develop.ut_varchar2_list, a_item varchar2); diff --git a/test/ut3_tester_helper/run_helper.pkb b/test/ut3_tester_helper/run_helper.pkb index c2a50170e..95f93f751 100644 --- a/test/ut3_tester_helper/run_helper.pkb +++ b/test/ut3_tester_helper/run_helper.pkb @@ -3,7 +3,7 @@ create or replace package body run_helper is procedure setup_cache_objects is pragma autonomous_transaction; begin - execute immediate q'[create or replace package ut3$user#.dummy_test_package as + execute immediate q'[create or replace package ut3_user.dummy_test_package as --%suite(dummy_test_suite) --%suitepath(some.path) --%rollback(manual) @@ -12,7 +12,7 @@ create or replace package body run_helper is --%beforetest(some_procedure) procedure some_dummy_test_procedure; end;]'; - execute immediate q'[create or replace procedure ut3$user#.dummy_test_procedure as + execute immediate q'[create or replace procedure ut3_user.dummy_test_procedure as --%some_annotation(some_text) --%rollback(manual) begin @@ -27,7 +27,7 @@ create or replace package body run_helper is execute immediate q'[grant execute on ut3_tester_helper.dummy_test_procedure to public]'; - execute immediate q'[create or replace package ut3$user#.bad_test_package as + execute immediate q'[create or replace package ut3_user.bad_test_package as --%rollback(manual) --%test(dummy_test) procedure some_dummy_test_procedure; @@ -37,7 +37,7 @@ create or replace package body run_helper is procedure setup_cache_objectstag is pragma autonomous_transaction; begin - execute immediate q'[create or replace package ut3$user#.dummy_test_package as + execute immediate q'[create or replace package ut3_user.dummy_test_package as --%suite(dummy_test_suite) --%suitepath(some.path) --%tags(dummy) @@ -48,7 +48,7 @@ create or replace package body run_helper is --%beforetest(some_procedure) procedure some_dummy_test_procedure; end;]'; - execute immediate q'[create or replace procedure ut3$user#.dummy_test_procedure as + execute immediate q'[create or replace procedure ut3_user.dummy_test_procedure as --%some_annotation(some_text) --%rollback(manual) begin @@ -67,7 +67,7 @@ create or replace package body run_helper is procedure setup_cache_twotags is pragma autonomous_transaction; begin - execute immediate q'[create or replace package ut3$user#.dummy_test_package as + execute immediate q'[create or replace package ut3_user.dummy_test_package as --%suite(dummy_test_suite) --%tags(suitetag1,suitetag2) --%rollback(manual) @@ -77,7 +77,7 @@ create or replace package body run_helper is --%beforetest(some_procedure) procedure some_dummy_test_procedure; end;]'; - execute immediate q'[create or replace procedure ut3$user#.dummy_test_procedure as + execute immediate q'[create or replace procedure ut3_user.dummy_test_procedure as --%some_annotation(some_text) --%rollback(manual) begin @@ -141,8 +141,8 @@ create or replace package body run_helper is pragma autonomous_transaction; begin setup_cache_objects(); - ut3_develop.ut_annotation_manager.rebuild_annotation_cache('UT3$USER#','PACKAGE'); - ut3_develop.ut_annotation_manager.rebuild_annotation_cache('UT3$USER#','PROCEDURE'); + ut3_develop.ut_annotation_manager.rebuild_annotation_cache('UT3_USER','PACKAGE'); + ut3_develop.ut_annotation_manager.rebuild_annotation_cache('UT3_USER','PROCEDURE'); ut3_develop.ut_annotation_manager.rebuild_annotation_cache('UT3_TESTER_HELPER','PROCEDURE'); end; @@ -150,10 +150,10 @@ create or replace package body run_helper is pragma autonomous_transaction; begin delete from ut3_develop.ut_annotation_cache_info - where object_type = 'PROCEDURE' and object_owner in ('UT3$USER#','UT3_TESTER_HELPER') + where object_type = 'PROCEDURE' and object_owner in ('UT3_USER','UT3_TESTER_HELPER') or object_type = 'PACKAGE' and object_owner = user and object_name = 'DUMMY_TEST_PACKAGE'; - execute immediate q'[drop package ut3$user#.dummy_test_package]'; - execute immediate q'[drop procedure ut3$user#.dummy_test_procedure]'; + execute immediate q'[drop package ut3_user.dummy_test_package]'; + execute immediate q'[drop procedure ut3_user.dummy_test_procedure]'; execute immediate q'[drop procedure ut3_tester_helper.dummy_test_procedure]'; end; @@ -185,7 +185,7 @@ create or replace package body run_helper is begin create_db_link; execute immediate q'[ - create or replace package ut3$user#.test_db_link is + create or replace package ut3_user.test_db_link is --%suite --%test @@ -193,7 +193,7 @@ create or replace package body run_helper is end;]'; execute immediate q'[ - create or replace package body ut3$user#.test_db_link is + create or replace package body ut3_user.test_db_link is procedure runs_with_db_link is a_value integer; begin @@ -208,7 +208,7 @@ create or replace package body run_helper is procedure db_link_cleanup is begin drop_db_link; - begin execute immediate 'drop package ut3$user#.test_db_link'; exception when others then null; end; + begin execute immediate 'drop package ut3_user.test_db_link'; exception when others then null; end; end; procedure create_suite_with_link is @@ -258,7 +258,7 @@ create or replace package body run_helper is execute immediate 'drop package test_distributed_savepoint'; end; - procedure create_ut3$user#_tests is + procedure create_ut3_user_tests is pragma autonomous_transaction; begin execute immediate q'[create or replace package test_package_1 is @@ -348,7 +348,7 @@ create or replace package body run_helper is execute immediate q'[grant execute on test_package_3 to public]'; end; - procedure drop_ut3$user#_tests is + procedure drop_ut3_user_tests is pragma autonomous_transaction; begin execute immediate q'[drop package test_package_1]'; diff --git a/test/ut3_tester_helper/run_helper.pks b/test/ut3_tester_helper/run_helper.pks index 0657c1a51..ad0f615e5 100644 --- a/test/ut3_tester_helper/run_helper.pks +++ b/test/ut3_tester_helper/run_helper.pks @@ -17,8 +17,8 @@ create or replace package run_helper is procedure create_suite_with_link; procedure drop_suite_with_link; - procedure create_ut3$user#_tests; - procedure drop_ut3$user#_tests; + procedure create_ut3_user_tests; + procedure drop_ut3_user_tests; procedure create_test_suite; procedure drop_test_suite; diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index b4f5a5238..7b47193c9 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -13,14 +13,14 @@ create or replace package body test_ut_run is ut3_tester_helper.main_helper.clear_expectations(); end; - procedure create_ut3$user#_tests is + procedure create_ut3_user_tests is begin - ut3_tester_helper.run_helper.create_ut3$user#_tests(); + ut3_tester_helper.run_helper.create_ut3_user_tests(); end; - procedure drop_ut3$user#_tests is + procedure drop_ut3_user_tests is begin - ut3_tester_helper.run_helper.drop_ut3$user#_tests(); + ut3_tester_helper.run_helper.drop_ut3_user_tests(); end; procedure ut_version is @@ -257,7 +257,7 @@ create or replace package body test_ut_run is ut.expect(l_results).to_be_like( '%1) does_stuff%' || 'ORA-01403: no data found%' || - 'ORA-06512: at "UT3$USER#.PARENT_SUITE%' + 'ORA-06512: at "UT3_USER.PARENT_SUITE%' ); end; diff --git a/test/ut3_user/api/test_ut_run.pks b/test/ut3_user/api/test_ut_run.pks index 753af79da..b3be8700d 100644 --- a/test/ut3_user/api/test_ut_run.pks +++ b/test/ut3_user/api/test_ut_run.pks @@ -4,8 +4,8 @@ create or replace package test_ut_run is procedure clear_expectations; - procedure create_ut3$user#_tests; - procedure drop_ut3$user#_tests; + procedure create_ut3_user_tests; + procedure drop_ut3_user_tests; --%test(ut.version() returns version of the framework) procedure ut_version; @@ -17,8 +17,8 @@ create or replace package test_ut_run is --%context(ut_run_procedure) --%displayname(ut.run() procedure options) - --%beforeall(create_ut3$user#_tests) - --%afterall(drop_ut3$user#_tests) + --%beforeall(create_ut3_user_tests) + --%afterall(drop_ut3_user_tests) --%test(Runs all tests in current schema with default reporter when no parameters given) procedure run_proc_no_params; @@ -88,8 +88,8 @@ create or replace package test_ut_run is --%context(ut_run_function) --%displayname(ut.run() function options) - --%beforeall(create_ut3$user#_tests) - --%afterall(drop_ut3$user#_tests) + --%beforeall(create_ut3_user_tests) + --%afterall(drop_ut3_user_tests) --%test(Runs all tests in current schema with default reporter when no parameters given) procedure run_func_no_params; @@ -167,8 +167,8 @@ create or replace package test_ut_run is --%context(random_order) --%displayname(Random test execution order) - --%beforeall(create_ut3$user#_tests) - --%afterall(drop_ut3$user#_tests) + --%beforeall(create_ut3_user_tests) + --%afterall(drop_ut3_user_tests) --%test(Runs tests in random order) procedure run_with_random_order; @@ -184,8 +184,8 @@ create or replace package test_ut_run is --%context(run with tags) --%displayname(Call ut.run with #tags) - --%beforeall(create_ut3$user#_tests) - --%afterall(drop_ut3$user#_tests) + --%beforeall(create_ut3_user_tests) + --%afterall(drop_ut3_user_tests) --%test(Execute test by tag ut_run) procedure test_run_by_one_tag; diff --git a/test/ut3_user/api/test_ut_runner.pkb b/test/ut3_user/api/test_ut_runner.pkb index a24fc2d51..6774698f2 100644 --- a/test/ut3_user/api/test_ut_runner.pkb +++ b/test/ut3_user/api/test_ut_runner.pkb @@ -265,27 +265,27 @@ end;'; --Arrange open l_expected for select - 'UT3$USER#' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'DUMMY_TEST_PACKAGE' item_name, + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'DUMMY_TEST_PACKAGE' item_name, 'dummy_test_suite' item_description, 'UT_SUITE' item_type, 2 item_line_no, 'some.path.dummy_test_package' path, 0 disabled_flag, null disabled_reason,null tags from dual union all select - 'UT3$USER#' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'SOME_DUMMY_TEST_PROCEDURE' item_name, + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'SOME_DUMMY_TEST_PROCEDURE' item_name, 'dummy_test' item_description, 'UT_TEST' item_type, 6 item_line_no, 'some.path.dummy_test_package.some_dummy_test_procedure' path, 0 disabled_flag, null disabled_reason,null tags from dual union all select - 'UT3$USER#' object_owner, 'PATH' object_name, 'PATH' item_name, + 'UT3_USER' object_owner, 'PATH' object_name, 'PATH' item_name, null item_description, 'UT_LOGICAL_SUITE' item_type, null item_line_no, 'some.path' path, 0 disabled_flag, null disabled_reason, null tags from dual union all select - 'UT3$USER#' object_owner, 'SOME' object_name, 'SOME' item_name, + 'UT3_USER' object_owner, 'SOME' object_name, 'SOME' item_name, null item_description, 'UT_LOGICAL_SUITE' item_type, null item_line_no, 'some' path, 0 disabled_flag, null disabled_reason, null tags from dual; --Act - open l_actual for select * from table(ut3_develop.ut_runner.get_suites_info('UT3$USER#','DUMMY_TEST_PACKAGE')); + open l_actual for select * from table(ut3_develop.ut_runner.get_suites_info('UT3_USER','DUMMY_TEST_PACKAGE')); --Assert ut.expect(l_actual).to_equal(l_expected); end; @@ -297,27 +297,27 @@ end;'; --Arrange open l_expected for select - 'UT3$USER#' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'DUMMY_TEST_PACKAGE' item_name, + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'DUMMY_TEST_PACKAGE' item_name, 'dummy_test_suite' item_description, 'UT_SUITE' item_type, 2 item_line_no, 'some.path.dummy_test_package' path, 0 disabled_flag, null disabled_reason,'dummy' tags from dual union all select - 'UT3$USER#' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'SOME_DUMMY_TEST_PROCEDURE' item_name, + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'SOME_DUMMY_TEST_PROCEDURE' item_name, 'dummy_test' item_description, 'UT_TEST' item_type, 7 item_line_no, 'some.path.dummy_test_package.some_dummy_test_procedure' path, 0 disabled_flag, null disabled_reason,'testtag' tags from dual union all select - 'UT3$USER#' object_owner, 'PATH' object_name, 'PATH' item_name, + 'UT3_USER' object_owner, 'PATH' object_name, 'PATH' item_name, null item_description, 'UT_LOGICAL_SUITE' item_type, null item_line_no, 'some.path' path, 0 disabled_flag, null disabled_reason, null tags from dual union all select - 'UT3$USER#' object_owner, 'SOME' object_name, 'SOME' item_name, + 'UT3_USER' object_owner, 'SOME' object_name, 'SOME' item_name, null item_description, 'UT_LOGICAL_SUITE' item_type, null item_line_no, 'some' path, 0 disabled_flag, null disabled_reason, null tags from dual; --Act - open l_actual for select * from table(ut3_develop.ut_runner.get_suites_info('UT3$USER#','DUMMY_TEST_PACKAGE')); + open l_actual for select * from table(ut3_develop.ut_runner.get_suites_info('UT3_USER','DUMMY_TEST_PACKAGE')); --Assert ut.expect(l_actual).to_equal(l_expected); end; @@ -329,12 +329,12 @@ end;'; --Arrange open l_expected for select - 'UT3$USER#' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'DUMMY_TEST_PACKAGE' item_name, + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'DUMMY_TEST_PACKAGE' item_name, 'dummy_test_suite' item_description, 'UT_SUITE' item_type, 2 item_line_no, 'dummy_test_package' path, 0 disabled_flag, null disabled_reason,'suitetag1,suitetag2' tags from dual union all select - 'UT3$USER#' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'SOME_DUMMY_TEST_PROCEDURE' item_name, + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'SOME_DUMMY_TEST_PROCEDURE' item_name, 'dummy_test' item_description, 'UT_TEST' item_type, 6 item_line_no, 'dummy_test_package.some_dummy_test_procedure' path, 0 disabled_flag, null disabled_reason,'testtag1,testtag2' tags from dual; diff --git a/test/ut3_user/expectations.pkb b/test/ut3_user/expectations.pkb index 30af48a44..be8627712 100644 --- a/test/ut3_user/expectations.pkb +++ b/test/ut3_user/expectations.pkb @@ -16,14 +16,14 @@ create or replace package body expectations as l_expected := q'[FAILURE Actual: 1 (number) was expected to equal: 0 (number) - at "UT3$USER#.SOME_PKG%", line 4 ut3_develop.ut.expect(1).to_equal(0); + at "UT3_USER.SOME_PKG%", line 4 ut3_develop.ut.expect(1).to_equal(0); at "anonymous block", line 1 - at "UT3$USER#.EXPECTATIONS%", line 10 + at "UT3_USER.EXPECTATIONS%", line 10 SUCCESS Actual: 0 (number) was expected to equal: 0 (number) FAILURE Actual: 1 (number) was expected to equal: 0 (number) - at "UT3$USER#.EXPECTATIONS%", line 11 ut3_develop.ut.expect(1).to_equal(0); + at "UT3_USER.EXPECTATIONS%", line 11 ut3_develop.ut.expect(1).to_equal(0); SUCCESS Actual: 0 (number) was expected to equal: 0 (number) ]'; diff --git a/test/ut3_user/reporters.pkb b/test/ut3_user/reporters.pkb index 76d345a3d..b6d43b144 100644 --- a/test/ut3_user/reporters.pkb +++ b/test/ut3_user/reporters.pkb @@ -188,7 +188,7 @@ end;]'; --Assert ut.expect(l_actual).to_be_like('%' (varchar2)%]' - ||q'[at "UT3$USER#.CHECK_FAIL_ESCAPE%", line % ut3_develop.ut.expect('test').to_equal('');]' + ||q'[at "UT3_USER.CHECK_FAIL_ESCAPE%", line % ut3_develop.ut.expect('test').to_equal('');]' ||'%]]>%' ); end; diff --git a/test/ut3_user/reporters/test_documentation_reporter.pkb b/test/ut3_user/reporters/test_documentation_reporter.pkb index a627d26b4..6ace70c49 100644 --- a/test/ut3_user/reporters/test_documentation_reporter.pkb +++ b/test/ut3_user/reporters/test_documentation_reporter.pkb @@ -33,12 +33,12 @@ Failures: 1) failing_test "Fails as values are different" Actual: 'number [1] ' (varchar2) was expected to equal: 'number [2] ' (varchar2)% - at "UT3$USER#.TEST_REPORTERS%", line 36 ut3_develop.ut.expect('number [1] ','Fails as values are different').to_equal('number [2] '); + at "UT3_USER.TEST_REPORTERS%", line 36 ut3_develop.ut.expect('number [1] ','Fails as values are different').to_equal('number [2] '); % % 2) erroring_test ORA-06502: PL/SQL: numeric or value error: character to number conversion error - ORA-06512: at "UT3$USER#.TEST_REPORTERS", line 44% + ORA-06512: at "UT3_USER.TEST_REPORTERS", line 44% ORA-06512: at line 6 Finished in % seconds 5 tests, 1 failed, 1 errored, 2 disabled, 0 warning(s)%]'; diff --git a/test/ut3_user/reporters/test_teamcity_reporter.pkb b/test/ut3_user/reporters/test_teamcity_reporter.pkb index 6d471b2b0..ff550e488 100644 --- a/test/ut3_user/reporters/test_teamcity_reporter.pkb +++ b/test/ut3_user/reporters/test_teamcity_reporter.pkb @@ -45,29 +45,29 @@ create or replace package body test_teamcity_reporter as %##teamcity[testSuiteStarted timestamp='%' name='org.utplsql.tests.helpers'] %##teamcity[testSuiteStarted timestamp='%' name='A suite for testing different outcomes from reporters'] %##teamcity[testSuiteStarted timestamp='%' name='A description of some context'] -%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3$user#.test_reporters.passing_test'] +%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.test_reporters.passing_test'] -%##teamcity[testFinished timestamp='%' duration='%' name='ut3$user#.test_reporters.passing_test'] +%##teamcity[testFinished timestamp='%' duration='%' name='ut3_user.test_reporters.passing_test'] %##teamcity[testSuiteFinished timestamp='%' name='A description of some context'] -%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3$user#.test_reporters.failing_test'] +%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.test_reporters.failing_test'] -%##teamcity[testFailed timestamp='%' details='Actual: |'number |[1|] |' (varchar2) was expected to equal: |'number |[2|] |' (varchar2)' message='Fails as values are different' name='ut3$user#.test_reporters.failing_test'] -%##teamcity[testFinished timestamp='%' duration='%' name='ut3$user#.test_reporters.failing_test'] -%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3$user#.test_reporters.erroring_test'] +%##teamcity[testFailed timestamp='%' details='Actual: |'number |[1|] |' (varchar2) was expected to equal: |'number |[2|] |' (varchar2)' message='Fails as values are different' name='ut3_user.test_reporters.failing_test'] +%##teamcity[testFinished timestamp='%' duration='%' name='ut3_user.test_reporters.failing_test'] +%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.test_reporters.erroring_test'] -%##teamcity[testStdErr timestamp='%' name='ut3$user#.test_reporters.erroring_test' out='Test exception:|nORA-06502: PL/SQL: numeric or value error: character to number conversion error|nORA-06512: at "UT3$USER#.TEST_REPORTERS", line %|nORA-06512: at %|n'] -%##teamcity[testFailed timestamp='%' details='Test exception:|nORA-06502: PL/SQL: numeric or value error: character to number conversion error|nORA-06512: at "UT3$USER#.TEST_REPORTERS", line %|nORA-06512: at %|n' message='Error occured' name='ut3$user#.test_reporters.erroring_test'] -%##teamcity[testFinished timestamp='%' duration='%' name='ut3$user#.test_reporters.erroring_test'] -%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3$user#.test_reporters.disabled_test'] -%##teamcity[testIgnored timestamp='%' name='ut3$user#.test_reporters.disabled_test'] +%##teamcity[testStdErr timestamp='%' name='ut3_user.test_reporters.erroring_test' out='Test exception:|nORA-06502: PL/SQL: numeric or value error: character to number conversion error|nORA-06512: at "UT3_USER.TEST_REPORTERS", line %|nORA-06512: at %|n'] +%##teamcity[testFailed timestamp='%' details='Test exception:|nORA-06502: PL/SQL: numeric or value error: character to number conversion error|nORA-06512: at "UT3_USER.TEST_REPORTERS", line %|nORA-06512: at %|n' message='Error occured' name='ut3_user.test_reporters.erroring_test'] +%##teamcity[testFinished timestamp='%' duration='%' name='ut3_user.test_reporters.erroring_test'] +%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.test_reporters.disabled_test'] +%##teamcity[testIgnored timestamp='%' name='ut3_user.test_reporters.disabled_test'] %##teamcity[testSuiteFinished timestamp='%' name='A suite for testing different outcomes from reporters'] %##teamcity[testSuiteFinished timestamp='%' name='org.utplsql.tests.helpers'] %##teamcity[testSuiteFinished timestamp='%' name='org.utplsql.tests'] @@ -88,9 +88,9 @@ create or replace package body test_teamcity_reporter as l_expected varchar2(32767); begin l_expected := q'{%##teamcity[testSuiteStarted timestamp='%' name='A suite with |'quote|''] -%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3$user#.check_escape_special_chars.test_do_stuff'] -%##teamcity[testFailed timestamp='%' details='Actual: (varchar2)|n |' |[ |r|n |] |'|n was expected to be null' name='ut3$user#.check_escape_special_chars.test_do_stuff'] -%##teamcity[testFinished timestamp='%' duration='%' name='ut3$user#.check_escape_special_chars.test_do_stuff'] +%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.check_escape_special_chars.test_do_stuff'] +%##teamcity[testFailed timestamp='%' details='Actual: (varchar2)|n |' |[ |r|n |] |'|n was expected to be null' name='ut3_user.check_escape_special_chars.test_do_stuff'] +%##teamcity[testFinished timestamp='%' duration='%' name='ut3_user.check_escape_special_chars.test_do_stuff'] %##teamcity[testSuiteFinished timestamp='%' name='A suite with |'quote|'']}'; --act select * @@ -107,9 +107,9 @@ create or replace package body test_teamcity_reporter as l_expected varchar2(32767); begin l_expected := q'{%##teamcity[testSuiteStarted timestamp='%' name='check_trims_long_output'] -%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3$user#.check_trims_long_output.long_output'] -%##teamcity[testFailed timestamp='%' details='Actual: (varchar2)|n |'aVarcharaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|[...|]' name='ut3$user#.check_trims_long_output.long_output'] -%##teamcity[testFinished timestamp='%' duration='%' name='ut3$user#.check_trims_long_output.long_output'] +%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.check_trims_long_output.long_output'] +%##teamcity[testFailed timestamp='%' details='Actual: (varchar2)|n |'aVarcharaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|[...|]' name='ut3_user.check_trims_long_output.long_output'] +%##teamcity[testFinished timestamp='%' duration='%' name='ut3_user.check_trims_long_output.long_output'] %##teamcity[testSuiteFinished timestamp='%' name='check_trims_long_output']}'; --act select * From 7cca6b468bc31194f2ecd0d9b2812982037c0578 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 3 Mar 2022 00:58:59 +0200 Subject: [PATCH 030/187] Update of coverage.md --- docs/userguide/coverage.md | 73 +++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 20210ab47..cdc573758 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -32,18 +32,19 @@ If you have `execute` privilege on the code that is being tested, but do not hav If you have `execute` privilege only on the unit tests, but do not have `execute` privilege on the code that is being tested, the code will not be reported by coverage - as if it did not exist in the database. If the code that is being tested is compiled as NATIVE, the code coverage will not be reported as well. -## Running unit tests with coverage -Using the code coverage functionality is as easy as using any other [reporter](reporters.md) for the utPLSQL test-run. You just run your tests from your preferred SQL tool and save the reporter results to a file. -All you need to do is pass the constructor of the reporter to the `ut.run` procedure call. +## Manually running unit tests with coverage +Using the code coverage functionality is as easy as using any other [reporter](reporters.md) for the utPLSQL test-run. Run your tests from your preferred SQL tool and save the reporter results to a file. +All you need to do, is pass the constructor of the reporter to the `ut.run` procedure call. Example: ```sql +set serveroutput on begin ut.run(ut_coverage_html_reporter()); end; / ``` -The above command executes all unit tests in the **current schema**, gathers information about code coverage and outputs the HTML report as text into DBMS_OUTPUT. +The above command executes all unit tests in the **current schema**, gathers information about code coverage for all sources in that schema and outputs the HTML report as text into DBMS_OUTPUT. The `ut_coverage_html_reporter` will produce an interactive HTML report. You can see a sample of code coverage for the utPLSQL project [here](https://utplsql.github.io/utPLSQL-coverage-html/) The report provides summary information with a list of source code that should be covered. @@ -79,14 +80,14 @@ There are two distinct ways to gather code coverage: - Coverage on project files Those two options are mutually exclusive and cannot be mixed. -By default, when using one of coverage reporters, coverage is gathered on schema(s). +By default, when using one of coverage reporters, coverage is gathered on schema(s). +The database schema(s) containing the tests that were executed during the run will be reported on by coverage reporter. The parameters used to execute tests determine if utPLSQL will be using one approach or the other. +If parameter `a_source_file_mappings` or `a_source_files` is provided, then coverage is gathered on project files provided, otherwise coverage is gathered on schemas. -The database schema(s) containing the tests that were executed during the run will be reported on by coverage reporter. **Note** - > Regardless of the options provided, all unit test packages are excluded from the coverage report. Coverage reports provide information only about the **tested** code. The default behavior of coverage reporting can be altered using invocation parameters. @@ -131,10 +132,10 @@ exec ut.run('unit_test_schema', ut_coverage_html_reporter(), a_coverage_schemes There are multiple parameters that can be used to define the scope of coverage report: - `a_source_file_mappings ( ut_file_mappings )` - map of filenames to database objects. It is used for file-based coverage - see below. -- `a_include_schema_expr ( varchar(4000) )` - string of regex expression of schemas to be included in the coverage report. -- `a_include_object_expr ( varchar(4000) )` - string of regex expression of objects ( without schema name ) to be included in the coverage report. -- `a_exclude_schema_expr ( varchar(4000) )` - string of regex expression of schemas to be excluded from the coverage report. -- `a_exclude_object_expr ( varchar(4000) )` - string of regex expression of objects to be excluded from the coverage report. +- `a_include_schema_expr ( varchar(4000) )` - string of regex expression of schemas to be included in the coverage report. Case-insensitive. +- `a_include_object_expr ( varchar(4000) )` - string of regex expression of objects ( without schema name ) to be included in the coverage report. Case-insensitive. +- `a_exclude_schema_expr ( varchar(4000) )` - string of regex expression of schemas to be excluded from the coverage report. Case-insensitive. +- `a_exclude_object_expr ( varchar(4000) )` - string of regex expression of objects ( without schema name ) to be excluded from the coverage report. Case-insensitive. - `a_coverage_schemes ( ut_varchar2_list )` - List of database schema names to gather coverage on. - `a_include_objects ( ut_varchar2_list )` - list of `[object_owner.]object_name` to be included in the coverage report. - `a_exclude_objects ( ut_varchar2_list )` - list of `[object_owner.]object_name` to be excluded from the coverage report. @@ -164,6 +165,7 @@ end; ``` Will result in showing coverage for all schemas that match regular expression `^ut3_develop` +Example: Limiting coverage by schema regex with parameter `a_include_objects` ignored. ```sql begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), @@ -172,37 +174,68 @@ begin end; ``` Will result in showing coverage for all schemas that match regular expression `^ut3_develop`. -Will ignore the `a_include_objects` parameter +Example: Limiting coverage by object regex. ```sql begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), - a_include_object_expr => 'regex123', a_include_objects => ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) + a_include_object_expr => 'regex123' ); end; ``` Will result in showing coverage for all objects that name match regular expression `regex123`. -Will ignore the `a_include_objects` parameter. +Example: Limiting coverage by object regex with parameter `a_include_objects` ignored. +```sql +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_include_object_expr => 'utl', a_include_objects => ut_varchar2_list( 'user_2.utils_package' ) + ); +end; +``` +Will result in showing coverage for all objects that name match regular expression `utl`. + +Example: Limiting coverage by excluding schema with regex. +```sql +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_exclude_schema_expr => 'er_1$' + ); +end; +``` +Will result in showing coverage for objects in all schema except schemas that are matching regular expression `er_1$` + +Example: Limiting coverage by excluding schema with regex and excluding specific object. +```sql +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_exclude_schema_expr => 'er_1$', a_exclude_objects => ut_varchar2_list( 'user_2.utils_package' ) + ); +end; +``` +Will result in showing coverage for objects in all schemas except schemas that are matching regular expression `er_1$` +Will also exclude object `user_2.utils_package` from coverage report + +Example: Limiting coverage by excluding objects with regex. ```sql begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), - a_exclude_schema_expr => '^ut3_tester', a_exclude_objects => ut_varchar2_list( 'regex_dummy_cov' ) + a_exclude_object_expr => 'utl' ); end; ``` -Will result in showing coverage for objects in all schema except schemas that are matching regular expression `^ut3_tester` -Will ignore exclusion defined by parameter `a_exclude_objects` +Will result in showing coverage for all objects that name is not matching regular expression `utl`. +Example: Limiting coverage by excluding objects with regex with parameter `a_exclude_objects` ignored. ```sql begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), - a_exclude_object_expr => 'regex123', a_exclude_objects => ut_varchar2_list( 'regex_dummy_cov' ) + a_exclude_object_expr => 'utl', a_exclude_objects => ut_varchar2_list( 'user_2.utils_package' ) ); end; ``` -Will result in showing coverage for all objects that name is not matching regular expression `regex123`. -Will ignore exclusion defined by parameter `a_exclude_objects`. +Will result in showing coverage for all objects that name is not matching regular expression `utl`. +Will also exclude object `user_2.utils_package` from coverage report Example: Limiting coverage by object name, for tested code located in the same schema as the unit tests. From a0462a7584113c494d37fd2c6ceb1bbfec404b35 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 3 Mar 2022 01:12:55 +0200 Subject: [PATCH 031/187] Fixing tests after schema rename. Make sure SONAR runs, even if build fails. --- .github/workflows/build.yml | 2 +- test/ut3_user/api/test_ut_run.pkb | 2 +- test/ut3_user/api/test_ut_runner.pkb | 28 +++++++++---------- .../expectations/test_expectations_cursor.pkb | 4 +-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 816f0ab39..a0aae6b64 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -193,7 +193,7 @@ jobs: - name: SonarCloud Scan id: sonar - if: ${{ matrix.db_version_name == '21XE' }} + if: ${{ always() && matrix.db_version_name == '21XE' }} uses: SonarSource/sonarcloud-github-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 7b47193c9..492efcba2 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -625,7 +625,7 @@ Failures:% begin execute immediate q'[select count(1) from all_objects o where o.owner = :object_owner and o.object_type = 'PACKAGE' and o.status = 'INVALID' and o.object_name= :object_name]' into l_is_invalid - using 'UT3$USER#','INVALID_PCKAG_THAT_REVALIDATES'; + using 'UT3_USER','INVALID_PCKAG_THAT_REVALIDATES'; select * bulk collect into l_results from table(ut3_develop.ut.run('invalid_pckag_that_revalidates')); diff --git a/test/ut3_user/api/test_ut_runner.pkb b/test/ut3_user/api/test_ut_runner.pkb index 6774698f2..80b1cd60b 100644 --- a/test/ut3_user/api/test_ut_runner.pkb +++ b/test/ut3_user/api/test_ut_runner.pkb @@ -339,7 +339,7 @@ end;'; 'dummy_test_package.some_dummy_test_procedure' path, 0 disabled_flag, null disabled_reason,'testtag1,testtag2' tags from dual; --Act - open l_actual for select * from table(ut3_develop.ut_runner.get_suites_info('UT3$USER#','DUMMY_TEST_PACKAGE')); + open l_actual for select * from table(ut3_develop.ut_runner.get_suites_info('UT3_USER','DUMMY_TEST_PACKAGE')); --Assert ut.expect(l_actual).to_equal(l_expected); end; @@ -571,20 +571,20 @@ end;'; begin ut.expect( ut3_develop.ut_runner.is_test( - a_owner => 'UT3$USER#', + a_owner => 'UT3_USER', a_package_name => 'DUMMY_TEST_PACKAGE', a_procedure_name => 'SOME_DUMMY_TEST_PROCEDURE' ) ).to_be_true(); - ut.expect( ut3_develop.ut_runner.is_test( 'ut3$user#','dummy_test_package','some_dummy_test_procedure' ) ).to_be_true(); + ut.expect( ut3_develop.ut_runner.is_test( 'ut3_user','dummy_test_package','some_dummy_test_procedure' ) ).to_be_true(); end; procedure is_test_false is begin - ut.expect( ut3_develop.ut_runner.is_test( 'UT3$USER#','DUMMY_TEST_PACKAGE', 'BAD' ) ).to_be_false(); - ut.expect( ut3_develop.ut_runner.is_test( 'UT3$USER#','BAD_TEST_PACKAGE', 'some_dummy_test_procedure' ) ).to_be_false(); - ut.expect( ut3_develop.ut_runner.is_test( 'UT3$USER#','DUMMY_TEST_PACKAGE', null ) ).to_be_false(); - ut.expect( ut3_develop.ut_runner.is_test( 'UT3$USER#',null,'some_dummy_test_procedure' ) ).to_be_false(); + ut.expect( ut3_develop.ut_runner.is_test( 'UT3_USER','DUMMY_TEST_PACKAGE', 'BAD' ) ).to_be_false(); + ut.expect( ut3_develop.ut_runner.is_test( 'UT3_USER','BAD_TEST_PACKAGE', 'some_dummy_test_procedure' ) ).to_be_false(); + ut.expect( ut3_develop.ut_runner.is_test( 'UT3_USER','DUMMY_TEST_PACKAGE', null ) ).to_be_false(); + ut.expect( ut3_develop.ut_runner.is_test( 'UT3_USER',null,'some_dummy_test_procedure' ) ).to_be_false(); ut.expect( ut3_develop.ut_runner.is_test( null,'DUMMY_TEST_PACKAGE','some_dummy_test_procedure' ) ).to_be_false(); end; @@ -592,26 +592,26 @@ end;'; begin ut.expect( ut3_develop.ut_runner.is_suite( - a_owner => 'UT3$USER#', + a_owner => 'UT3_USER', a_package_name => 'DUMMY_TEST_PACKAGE' ) ).to_be_true(); - ut.expect( ut3_develop.ut_runner.is_suite( 'ut3$user#','dummy_test_package' ) ).to_be_true(); + ut.expect( ut3_develop.ut_runner.is_suite( 'ut3_user','dummy_test_package' ) ).to_be_true(); end; procedure is_suite_false is begin - ut.expect( ut3_develop.ut_runner.is_suite( 'UT3$USER#','BAD' ) ).to_be_false(); - ut.expect( ut3_develop.ut_runner.is_suite( 'UT3$USER#', null ) ).to_be_false(); + ut.expect( ut3_develop.ut_runner.is_suite( 'UT3_USER','BAD' ) ).to_be_false(); + ut.expect( ut3_develop.ut_runner.is_suite( 'UT3_USER', null ) ).to_be_false(); ut.expect( ut3_develop.ut_runner.is_suite( null,'DUMMY_TEST_PACKAGE' ) ).to_be_false(); - ut.expect( ut3_develop.ut_runner.is_suite( 'UT3$USER#','bad_test_package' ) ).to_be_false(); + ut.expect( ut3_develop.ut_runner.is_suite( 'UT3_USER','bad_test_package' ) ).to_be_false(); end; procedure has_suites_true is begin - ut.expect( ut3_develop.ut_runner.has_suites( a_owner => 'UT3$USER#' ) ).to_be_true(); - ut.expect( ut3_develop.ut_runner.has_suites( 'ut3$user#' ) ).to_be_true(); + ut.expect( ut3_develop.ut_runner.has_suites( a_owner => 'UT3_USER' ) ).to_be_true(); + ut.expect( ut3_develop.ut_runner.has_suites( 'ut3_user' ) ).to_be_true(); end; procedure has_suites_false is diff --git a/test/ut3_user/expectations/test_expectations_cursor.pkb b/test/ut3_user/expectations/test_expectations_cursor.pkb index 409c81ace..952084fd3 100644 --- a/test/ut3_user/expectations/test_expectations_cursor.pkb +++ b/test/ut3_user/expectations/test_expectations_cursor.pkb @@ -2507,7 +2507,7 @@ Diff:% 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 % ut3_develop.ut.expect(l_actual).to_equal(l_expected);% +at "UT3_USER.TEST_EXPECTATIONS_CURSOR%", line % ut3_develop.ut.expect(l_actual).to_equal(l_expected);% Check the query and data for errors.'; open l_actual for @@ -2532,7 +2532,7 @@ Check the query and data for errors.'; 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 % ut3_develop.ut.expect(l_actual).to_equal(l_expected);% +at "UT3_USER.TEST_EXPECTATIONS_CURSOR%", line % ut3_develop.ut.expect(l_actual).to_equal(l_expected);% Check the query and data for errors.'; open l_expected for From 25336385a0d7192d704fcfe67860f5efd5af5d24 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 3 Mar 2022 01:17:09 +0200 Subject: [PATCH 032/187] Update coverage.md --- docs/userguide/coverage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index cdc573758..664c972d1 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -130,7 +130,7 @@ exec ut.run('unit_test_schema', ut_coverage_html_reporter(), a_coverage_schemes #### Filtering objects in coverage reports -There are multiple parameters that can be used to define the scope of coverage report: +Multiple parameters can be used to define the scope of coverage report. - `a_source_file_mappings ( ut_file_mappings )` - map of filenames to database objects. It is used for file-based coverage - see below. - `a_include_schema_expr ( varchar(4000) )` - string of regex expression of schemas to be included in the coverage report. Case-insensitive. - `a_include_object_expr ( varchar(4000) )` - string of regex expression of objects ( without schema name ) to be included in the coverage report. Case-insensitive. From 79fcf85bf07b4694f34c2d6821b8694233427226 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 2 Mar 2022 23:54:33 +0000 Subject: [PATCH 033/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 002c7ee3b..718422bd7 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index fa782b2ad..dce7a66bd 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 400ead44a..73bb5df36 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 11beecd51..c11655c2f 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 89c4b41b4..cec5f8eb4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index d7c5b6bb0..420c72cfe 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index c36b06450..c7f1f152f 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 35485e4db..cf2e1cc1c 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 664c972d1..6415b538d 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index dbd70d9a0..f4cc81754 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 96fd4e2c4..71311c2c9 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 548994f5b..6e29a82da 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 88b4d0942..6a7562b8c 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 6140f2cc7..7a164257c 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index a6f37d0a6..3b8510f89 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 88fa7ad0c..538d2be49 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 1cc6dd58b..825c122cf 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3908--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index a19bd82dd..c233b22f7 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3908-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3931-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From ed936458138849bd4c38009cc45ea75f05fe0b1d Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 4 Mar 2022 00:48:22 +0200 Subject: [PATCH 034/187] Fixing stability of data setup rename of test_package_3 to testing_package_3 to avoid odd behavior on 11g --- .../annotations/test_annot_disabled_reason.pkb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/ut3_tester/core/annotations/test_annot_disabled_reason.pkb b/test/ut3_tester/core/annotations/test_annot_disabled_reason.pkb index e3df44425..7f1e068a8 100644 --- a/test/ut3_tester/core/annotations/test_annot_disabled_reason.pkb +++ b/test/ut3_tester/core/annotations/test_annot_disabled_reason.pkb @@ -115,7 +115,7 @@ end test_package_2;]'; end test_package_2;]'; - execute immediate q'[create or replace package test_package_3 is + execute immediate q'[create or replace package testing_package_3 is --%suite --%displayname(Disable tests on test level) @@ -144,9 +144,9 @@ end test_package_2;]'; --%endcontext -end test_package_3;]'; +end testing_package_3;]'; - execute immediate q'[create or replace package body test_package_3 is + execute immediate q'[create or replace package body testing_package_3 is procedure test1 is begin @@ -168,7 +168,7 @@ end test_package_3;]'; ut.expect(2).to_equal(2); end; -end test_package_3;]'; +end testing_package_3;]'; execute immediate q'[create or replace package test_package_4 is @@ -334,10 +334,10 @@ end test_package_6;]'; begin execute immediate 'drop package test_package_1'; execute immediate 'drop package test_package_2'; - execute immediate 'drop package test_package_3'; - execute immediate 'drop package test_package_4'; - execute immediate 'drop package test_package_5'; - execute immediate 'drop package test_package_6'; + execute immediate 'drop package testing_package_3'; + execute immediate 'drop package test_package_4'; + execute immediate 'drop package test_package_5'; + execute immediate 'drop package test_package_6'; end; procedure test_disable_on_suite_level is @@ -394,7 +394,7 @@ end test_package_6;]'; begin --Act - select * bulk collect into l_test_results from table(ut3_develop.ut.run((sys_context('USERENV', 'CURRENT_USER')||'.test_package_3'))); + select * bulk collect into l_test_results from table(ut3_develop.ut.run((sys_context('USERENV', 'CURRENT_USER')||'.testing_package_3'))); l_actual_message := ut3_develop.ut_utils.table_to_clob(l_test_results); From 85fd36d222680ebe1420d0fe40ed34520595a0b2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 3 Mar 2022 22:56:23 +0000 Subject: [PATCH 035/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 718422bd7..846862073 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index dce7a66bd..c03c53846 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 73bb5df36..7a49d944f 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index c11655c2f..af0c3f5f1 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index cec5f8eb4..e87cd94d9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 420c72cfe..ae00602cf 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index c7f1f152f..53d291fa3 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index cf2e1cc1c..4d7517f7d 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 6415b538d..82c4c34b2 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index f4cc81754..5fbec44a0 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index e13de9936..7129cd87c 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 6e29a82da..9668b49ef 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 6a7562b8c..42ff5ddd1 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 7a164257c..a68c427a4 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 3b8510f89..804cd64f6 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 46499273b..92d77cdba 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 825c122cf..b7399c1f6 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3931--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index c233b22f7..27979bf38 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3931-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3935-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 61ce1bb2380e7335132f206dba7ad7008c0f61ed Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 14 Mar 2022 01:13:46 +0200 Subject: [PATCH 036/187] Removed test users env variables Those variables are not needed and bring no real benefit asu the usernames actually cannot be configured and even if they were, there would be no real benefit to it. --- .github/scripts/create_test_users.sh | 50 ++++++++++++++-------------- .github/variables/.env | 8 +---- development/cleanup.sh | 6 ++-- development/template.env.sh | 7 ---- test/install_tests.sh | 6 ++-- test/run_tests.sh | 2 +- 6 files changed, 33 insertions(+), 46 deletions(-) diff --git a/.github/scripts/create_test_users.sh b/.github/scripts/create_test_users.sh index 43f64784d..fe43b7467 100755 --- a/.github/scripts/create_test_users.sh +++ b/.github/scripts/create_test_users.sh @@ -13,14 +13,14 @@ PROMPT Adding back create-trigger privilege to $UT3_DEVELOP_SCHEMA for testing grant administer database trigger to $UT3_DEVELOP_SCHEMA; -------------------------------------------------------------------------------- -PROMPT Creating $UT3_TESTER - Power-user for testing internal framework code +PROMPT Creating UT3_TESTER - Power-user for testing internal framework code -create user $UT3_TESTER identified by "$UT3_TESTER_PASSWORD" default tablespace $UT3_TABLESPACE quota unlimited on $UT3_TABLESPACE; -grant create session, create procedure, create type, create table to $UT3_TESTER; +create user UT3_TESTER identified by "ut3" default tablespace $UT3_TABLESPACE quota unlimited on $UT3_TABLESPACE; +grant create session, create procedure, create type, create table to UT3_TESTER; -grant execute on dbms_lock to $UT3_TESTER; +grant execute on dbms_lock to UT3_TESTER; -PROMPT Granting $UT3_DEVELOP_SCHEMA code to $UT3_TESTER +PROMPT Granting $UT3_DEVELOP_SCHEMA code to UT3_TESTER begin for i in ( @@ -30,31 +30,31 @@ begin and generated = 'N' and object_name not like 'SYS%') loop - execute immediate 'grant execute on $UT3_DEVELOP_SCHEMA."'||i.object_name||'" to $UT3_TESTER'; + execute immediate 'grant execute on $UT3_DEVELOP_SCHEMA."'||i.object_name||'" to UT3_TESTER'; end loop; end; / -PROMPT Granting $UT3_DEVELOP_SCHEMA tables to $UT3_TESTER +PROMPT Granting $UT3_DEVELOP_SCHEMA tables to UT3_TESTER begin for i in ( select table_name from all_tables t where owner = '$UT3_DEVELOP_SCHEMA' and nested = 'NO' and iot_name is null) loop - execute immediate 'grant select on $UT3_DEVELOP_SCHEMA.'||i.table_name||' to $UT3_TESTER'; + execute immediate 'grant select on $UT3_DEVELOP_SCHEMA.'||i.table_name||' to UT3_TESTER'; end loop; end; / -------------------------------------------------------------------------------- -PROMPT Creating $UT3_USER - minimal privileges user for API testing +PROMPT Creating UT3_USER - minimal privileges user for API testing -create user $UT3_USER identified by "$UT3_USER_PASSWORD" default tablespace $UT3_TABLESPACE quota unlimited on $UT3_TABLESPACE; -grant create session, create procedure, create type, create table to $UT3_USER; +create user UT3_USER identified by "ut3" default tablespace $UT3_TABLESPACE quota unlimited on $UT3_TABLESPACE; +grant create session, create procedure, create type, create table to UT3_USER; -PROMPT Grants for starting a debugging session from $UT3_USER -grant debug connect session to $UT3_USER; -grant debug any procedure to $UT3_USER; +PROMPT Grants for starting a debugging session from UT3_USER +grant debug connect session to UT3_USER; +grant debug any procedure to UT3_USER; begin \$if dbms_db_version.version <= 11 \$then null; -- no addition action necessary @@ -64,7 +64,7 @@ begin host =>'*', ace => sys.xs\$ace_type( privilege_list => sys.xs\$name_list('JDWP') , - principal_name => '$UT3_USER', + principal_name => 'UT3_USER', principal_type => sys.xs_acl.ptype_db ) ); @@ -73,29 +73,29 @@ end; / -------------------------------------------------------------------------------- -PROMPT Creating $UT3_TESTER_HELPER - provides functions to allow min grant test user setup tests. +PROMPT Creating UT3_TESTER_HELPER - provides functions to allow min grant test user setup tests. -create user $UT3_TESTER_HELPER identified by "$UT3_TESTER_HELPER_PASSWORD" default tablespace $UT3_TABLESPACE quota unlimited on $UT3_TABLESPACE; -grant create session, create procedure, create type, create table to $UT3_TESTER_HELPER; +create user UT3_TESTER_HELPER identified by "ut3" default tablespace $UT3_TABLESPACE quota unlimited on $UT3_TABLESPACE; +grant create session, create procedure, create type, create table to UT3_TESTER_HELPER; PROMPT Grants for testing distributed transactions -grant create public database link to $UT3_TESTER_HELPER; -grant drop public database link to $UT3_TESTER_HELPER; +grant create public database link to UT3_TESTER_HELPER; +grant drop public database link to UT3_TESTER_HELPER; PROMPT Grants for testing coverage outside of main $UT3_DEVELOP_SCHEMA schema. grant create any procedure, drop any procedure, execute any procedure, create any type, drop any type, execute any type, under any type, select any table, update any table, insert any table, delete any table, create any table, drop any table, alter any table, select any dictionary, create any synonym, drop any synonym, grant any object privilege, grant any privilege, create public synonym, drop public synonym, create any trigger - to $UT3_TESTER_HELPER; + to UT3_TESTER_HELPER; -grant create job to $UT3_TESTER_HELPER; +grant create job to UT3_TESTER_HELPER; PROMPT Additional grants for disabling DDL trigger and testing parser without trigger enabled/present -grant alter any trigger to $UT3_TESTER_HELPER; -grant administer database trigger to $UT3_TESTER_HELPER; -grant execute on dbms_lock to $UT3_TESTER_HELPER; +grant alter any trigger to UT3_TESTER_HELPER; +grant administer database trigger to UT3_TESTER_HELPER; +grant execute on dbms_lock to UT3_TESTER_HELPER; create user ut3_cache_test_owner identified by ut3; grant create session, create procedure to ut3_cache_test_owner; diff --git a/.github/variables/.env b/.github/variables/.env index e0a579d52..7bb5003e8 100644 --- a/.github/variables/.env +++ b/.github/variables/.env @@ -3,12 +3,6 @@ UT3_DEVELOP_SCHEMA=UT3_DEVELOP UT3_DEVELOP_SCHEMA_PASSWORD=ut3 UT3_RELEASE_VERSION_SCHEMA=UT3 UT3_RELEASE_VERSION_SCHEMA_PASSWORD=ut3 -UT3_USER='UT3_USER' -UT3_USER_PASSWORD=ut3 -UT3_TESTER=UT3_TESTER -UT3_TESTER_PASSWORD=ut3 -UT3_TESTER_HELPER=UT3_TESTER_HELPER -UT3_TESTER_HELPER_PASSWORD=ut3 UT3_TABLESPACE=users # Database Env @@ -30,4 +24,4 @@ GIT_COMMITTER_NAME="github-actions[bot]" GIT_COMMITTER_EMAIL="github-actions[bot]@users.noreply.github.com" #Docker environment for running utPLSQL install commands -DOCKER_ENV="-e SQLCLI=sqlplus -e UT3_DEVELOP_SCHEMA -e UT3_DEVELOP_SCHEMA_PASSWORD -e UT3_RELEASE_VERSION_SCHEMA -e UT3_RELEASE_VERSION_SCHEMA_PASSWORD -e UT3_USER -e UT3_USER_PASSWORD -e UT3_TESTER -e UT3_TESTER_PASSWORD -e UT3_TESTER_HELPER -e UT3_TESTER_HELPER_PASSWORD -e UT3_TABLESPACE -e ORACLE_PWD -e CONNECTION_STR -e UTPLSQL_DIR" \ No newline at end of file +DOCKER_ENV="-e SQLCLI=sqlplus -e UT3_DEVELOP_SCHEMA -e UT3_DEVELOP_SCHEMA_PASSWORD -e UT3_RELEASE_VERSION_SCHEMA -e UT3_RELEASE_VERSION_SCHEMA_PASSWORD -e UT3_TABLESPACE -e ORACLE_PWD -e CONNECTION_STR -e UTPLSQL_DIR" \ No newline at end of file diff --git a/development/cleanup.sh b/development/cleanup.sh index c13ddb4aa..33358302a 100755 --- a/development/cleanup.sh +++ b/development/cleanup.sh @@ -20,9 +20,9 @@ end; drop user ${UT3_DEVELOP_SCHEMA} cascade; drop user ${UT3_RELEASE_VERSION_SCHEMA} cascade; -drop user ${UT3_TESTER} cascade; -drop user ${UT3_TESTER_HELPER} cascade; -drop user ${UT3_USER} cascade; +drop user ut3_tester cascade; +drop user ut3_tester_helper cascade; +drop user ut3_user cascade; drop user ut3_cache_test_owner cascade; drop user ut3_no_extra_priv_user cascade; drop user ut3_select_catalog_user cascade; diff --git a/development/template.env.sh b/development/template.env.sh index 521d9343d..e69aa81aa 100755 --- a/development/template.env.sh +++ b/development/template.env.sh @@ -12,11 +12,4 @@ export UT3_DEVELOP_SCHEMA=UT3_DEVELOP export UT3_DEVELOP_SCHEMA_PASSWORD=ut3 export UT3_RELEASE_VERSION_SCHEMA=UT3 export UT3_RELEASE_VERSION_SCHEMA_PASSWORD=ut3 -export UT3_TESTER=UT3_TESTER -export UT3_TESTER_PASSWORD=ut3 -export UT3_TESTER_HELPER=UT3_TESTER_HELPER -export UT3_TESTER_HELPER_PASSWORD=ut3 export UT3_TABLESPACE=users -export UT3_USER="UT3\$USER#" -export UT3_USER_PASSWORD=ut3 -export DOCKER_ENV="-e SQLCLI=sqlplus -e UT3_DEVELOP_SCHEMA -e UT3_DEVELOP_SCHEMA_PASSWORD -e UT3_RELEASE_VERSION_SCHEMA -e UT3_RELEASE_VERSION_SCHEMA_PASSWORD -e UT3_USER -e UT3_USER_PASSWORD -e UT3_TESTER -e UT3_TESTER_PASSWORD -e UT3_TESTER_HELPER -e UT3_TESTER_HELPER_PASSWORD -e UT3_TABLESPACE -e ORACLE_PWD -e CONNECTION_STR -e UTPLSQL_DIR" diff --git a/test/install_tests.sh b/test/install_tests.sh index 4ccc312e8..1b97ec33d 100755 --- a/test/install_tests.sh +++ b/test/install_tests.sh @@ -5,9 +5,9 @@ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) cd ${SCRIPT_DIR} -"$SQLCLI" ${UT3_TESTER_HELPER}/${UT3_TESTER_HELPER_PASSWORD}@//${CONNECTION_STR} @install_ut3_tester_helper.sql +"$SQLCLI" UT3_TESTER_HELPER/ut3@//${CONNECTION_STR} @install_ut3_tester_helper.sql -"$SQLCLI" ${UT3_USER}/${UT3_USER_PASSWORD}@//${CONNECTION_STR} @install_ut3_user_tests.sql +"$SQLCLI" UT3_USER/ut3@//${CONNECTION_STR} @install_ut3_user_tests.sql -"$SQLCLI" ${UT3_TESTER}/${UT3_TESTER_PASSWORD}@//${CONNECTION_STR} @install_ut3_tester_tests.sql +"$SQLCLI" UT3_TESTER/ut3@//${CONNECTION_STR} @install_ut3_tester_tests.sql diff --git a/test/run_tests.sh b/test/run_tests.sh index ae4a739d9..118bab920 100755 --- a/test/run_tests.sh +++ b/test/run_tests.sh @@ -4,7 +4,7 @@ set -ev #goto git root directory git rev-parse && cd "$(git rev-parse --show-cdup)" -time utPLSQL-cli/bin/utplsql run ${UT3_TESTER_HELPER}/${UT3_TESTER_HELPER_PASSWORD}@${CONNECTION_STR} \ +time utPLSQL-cli/bin/utplsql run UT3_TESTER_HELPER/ut3@${CONNECTION_STR} \ -source_path=source -owner=ut3_develop \ -p='ut3_tester,ut3_user' \ -test_path=test -c \ From 8e54e91a844d87ea8029212269ab830910fccf65 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 14 Mar 2022 08:48:00 +0000 Subject: [PATCH 037/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 846862073..b93720226 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index c03c53846..a96043438 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 7a49d944f..1402d09ad 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index af0c3f5f1..9c2e9ee4a 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index e87cd94d9..740bc199a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index ae00602cf..72aca4936 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 53d291fa3..3017acdc5 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 4d7517f7d..8a7045e9c 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 82c4c34b2..018b206bd 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 5fbec44a0..7a1445c2d 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 7129cd87c..34f0970d5 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 9668b49ef..28cc3de62 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 42ff5ddd1..f1e96e50d 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index a68c427a4..2d947f391 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 804cd64f6..3ba397177 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 92d77cdba..f392dd1e5 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index b7399c1f6..5137e6490 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3935--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 27979bf38..aeff16dd8 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3935-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3940-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 86d4d0a76475a8a2eb78c1a1ae72e930c3afbf33 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 18 Mar 2022 16:33:57 +0000 Subject: [PATCH 038/187] Initial check-in. There is still no error handling. --- source/core/types/ut_path_item.tpb | 42 ++++++ source/core/types/ut_path_item.tps | 26 ++++ source/core/types/ut_path_items.tps | 19 +++ source/core/ut_suite_cache_manager.pkb | 182 ++++++++++++++++++++++++- source/core/ut_suite_cache_manager.pks | 6 + source/core/ut_suite_manager.pkb | 134 +++++++++--------- source/install.sql | 4 +- source/uninstall_objects.sql | 4 + 8 files changed, 354 insertions(+), 63 deletions(-) create mode 100644 source/core/types/ut_path_item.tpb create mode 100644 source/core/types/ut_path_item.tps create mode 100644 source/core/types/ut_path_items.tps diff --git a/source/core/types/ut_path_item.tpb b/source/core/types/ut_path_item.tpb new file mode 100644 index 000000000..3878b544c --- /dev/null +++ b/source/core/types/ut_path_item.tpb @@ -0,0 +1,42 @@ +create or replace type body ut_path_item as + /* + utPLSQL - Version 3 + Copyright 2016 - 2021 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2) return self as result is + begin + self.schema_name := schema_name; + self.object_name := object_name; + self.procedure_name := procedure_name; + return; + end; + + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2,suite_path varchar2) return self as result is + begin + self.schema_name := schema_name; + self.suite_path := suite_path; + return; + end; + + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result is + begin + self.schema_name := schema_name; + self.object_name := object_name; + self.procedure_name := procedure_name; + self.suite_path := suite_path; + return; + end; +end; +/ \ No newline at end of file diff --git a/source/core/types/ut_path_item.tps b/source/core/types/ut_path_item.tps new file mode 100644 index 000000000..9a5ef51d0 --- /dev/null +++ b/source/core/types/ut_path_item.tps @@ -0,0 +1,26 @@ +create or replace type ut_path_item as object ( + /* + utPLSQL - Version 3 + Copyright 2016 - 2021 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + schema_name varchar2(4000), + object_name varchar2(250), + procedure_name varchar2(250), + suite_path varchar2(4000), + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2) return self as result, + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2,suite_path varchar2) return self as result, + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result +) +/ \ No newline at end of file diff --git a/source/core/types/ut_path_items.tps b/source/core/types/ut_path_items.tps new file mode 100644 index 000000000..0c87cf28c --- /dev/null +++ b/source/core/types/ut_path_items.tps @@ -0,0 +1,19 @@ +create or replace type ut_path_items as + /* + utPLSQL - Version 3 + Copyright 2016 - 2021 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + table of ut_path_item +/ diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index ad1634c10..cc5cd0f19 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -20,7 +20,7 @@ create or replace package body ut_suite_cache_manager is * Private code */ - gc_get_cache_suite_sql constant varchar2(32767) := + gc_get_cache_suite_sql constant varchar2(32767) := q'[with suite_items as ( select /*+ cardinality(c 500) */ value(c) as obj @@ -83,6 +83,87 @@ create or replace package body ut_suite_cache_manager is from items c order by c.obj.object_owner,{:random_seed:}]'; + + gc_get_bulk_cache_suite_sql constant varchar2(32767) := + q'[with + suite_paths_tabs as ( + select schema_name,object_name,procedure_name,suite_path + from table(:l_schema_paths) + ), + suite_items as ( + select /*+ cardinality(c 500) */ value(c) as obj + from ut_suite_cache c, + suite_paths_tabs sp + where c.object_owner = upper(sp.schema_name) + and sp.suite_path is not null + and ( + sp.suite_path||'.' like c.path||'.%' /*all parents and self*/ + or + ( + c.path||'.' like sp.suite_path||'.%' /*all children and self*/ + and c.object_name like nvl(upper(sp.object_name),c.object_name) + and c.name like nvl(upper(sp.procedure_name),c.name) + ) + ) + union all + select /*+ cardinality(c 500) */ value(c) as obj + from ut_suite_cache c, + suite_paths_tabs sp + where c.object_owner = upper(sp.schema_name) + and sp.suite_path is null + and c.object_name like nvl(upper(replace(sp.object_name,'*','%')),c.object_name) + and c.name like nvl(upper(replace(sp.procedure_name,'*','%')),c.name) + ), + {:tags:} + suitepaths as ( + select distinct substr(c.obj.path,1,instr(c.obj.path,'.',-1)-1) as suitepath, + c.obj.path as path, + c.obj.object_owner as object_owner + from {:suite_item_name:} c + where c.obj.self_type = 'UT_SUITE' + ), + gen as ( + select rownum as pos + from xmltable('1 to 20') + ), + suitepath_part AS ( + select distinct + substr(b.suitepath, 1, instr(b.suitepath || '.', '.', 1, g.pos) -1) as path, + object_owner + from suitepaths b + join gen g + on g.pos <= regexp_count(b.suitepath, '\w+') + ), + logical_suite_data as ( + select 'UT_LOGICAL_SUITE' as self_type, p.path, p.object_owner, + upper( substr(p.path, instr( p.path, '.', -1 ) + 1 ) ) as object_name, + cast(null as ut_executables) as x, + cast(null as ut_varchar2_rows) as y, + cast(null as ut_executable_test) as z + from suitepath_part p + where p.path + not in (select s.path from suitepaths s) + ), + logical_suites as ( + select ut_suite_cache_row( + null, + s.self_type, s.path, s.object_owner, s.object_name, + s.object_name, null, null, null, null, 0,null, + ut_varchar2_rows(), + s.x, s.x, s.x, s.x, s.x, s.x, + s.y, null, s.z + ) as obj + from logical_suite_data s + ), + items as ( + select obj from {:suite_item_name:} + union all + select obj from logical_suites + ) + select /*+ no_parallel */ c.obj + from items c + order by c.obj.object_owner,{:random_seed:}]'; + function get_missing_cache_objects(a_object_owner varchar2) return ut_varchar2_rows is l_result ut_varchar2_rows; l_data ut_annotation_objs_cache_info; @@ -190,6 +271,29 @@ create or replace package body ut_suite_cache_manager is ) desc nulls last' end; end; + + --Possible move logic to type + function group_paths_by_schema(a_paths ut_varchar2_list) return ut_path_items is + c_package_path_regex constant varchar2(100) := '^([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_\*]+))?(\.([A-Za-z0-9$#_\*]+))?$'; + l_results ut_path_items := ut_path_items(); + l_path_item ut_path_item; + begin + for i in 1 .. a_paths.count loop + l_results.extend; + if a_paths(i) like '%:%' then + l_path_item := ut_path_item(upper(regexp_substr(a_paths(i),'^[^.:]+')), + ltrim(regexp_substr(a_paths(i),'[.:].*$'),':')); + l_results(l_results.last) := l_path_item; + else + l_path_item := ut_path_item(regexp_substr(a_paths(i), c_package_path_regex, subexpression => 1), + regexp_substr(a_paths(i), c_package_path_regex, subexpression => 3), + regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5)); + l_results(l_results.last) := l_path_item; + end if; + end loop; + + return l_results; + end; @@ -254,6 +358,82 @@ create or replace package body ut_suite_cache_manager is using upper(l_object_owner), l_path, l_path, upper(a_object_name), upper(a_procedure_name), l_include_tags, l_include_tags, l_exclude_tags, a_random_seed; return l_results; end; + + function expand_paths(a_schema_paths ut_path_items) return ut_path_items is + l_schema_paths ut_path_items:= ut_path_items(); + begin + with paths_to_expand as ( + select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(sp.object_name,c.object_name) as object_name,sp.procedure_name as procedure_name + from ut_suite_cache c, + table(a_schema_paths) sp + where c.object_owner = upper(sp.schema_name) + and c.object_name like nvl(replace(upper(sp.object_name),'*','%'),c.object_name) + and c.name like nvl(replace(upper(sp.procedure_name),'*','%'), c.name) + and sp.suite_path is null + group by sp.schema_name,nvl(sp.object_name,c.object_name),sp.procedure_name + union all + select /*+ no_parallel */ c.path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name + from + ut_suite_cache c, + table(a_schema_paths) sp + where c.object_owner = upper(sp.schema_name) + and sp.suite_path is not null + and instr(sp.suite_path,'*') > 0 + and c.path like replace(sp.suite_path,'*','%') + union all + select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name + from table(a_schema_paths) sp + where sp.suite_path is not null + and instr(sp.suite_path,'*') = 0 + ) + select ut_path_item(schema_name,object_name,procedure_name,suite_path) + bulk collect into l_schema_paths + from paths_to_expand; + return l_schema_paths; + end; + + function get_cached_suite_rows( + a_paths ut_varchar2_list, + a_random_seed positive := null, + a_tags ut_varchar2_rows := null + ) return ut_suite_cache_rows is + l_results ut_suite_cache_rows := ut_suite_cache_rows(); + l_schema_paths ut_path_items; + l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); + l_include_tags ut_varchar2_rows; + l_exclude_tags ut_varchar2_rows; + l_suite_item_name varchar2(20); + l_paths ut_varchar2_rows; + l_schema varchar2(4000); + l_sql varchar2(32767); + begin + select /*+ no_parallel */ column_value + bulk collect into l_include_tags + from table(l_tags) + where column_value not like '-%'; + + select /*+ no_parallel */ ltrim(column_value,'-') + bulk collect into l_exclude_tags + from table(l_tags) + where column_value like '-%'; + + l_schema_paths := expand_paths(group_paths_by_schema(a_paths)); + --We still need to turn this into qualified SQL name....maybe as part of results ? + l_suite_item_name := case when l_tags.count > 0 then 'suite_items_tags' else 'suite_items' end; + + l_sql := gc_get_bulk_cache_suite_sql; + l_sql := replace(l_sql,'{:suite_item_name:}',l_suite_item_name); + l_sql := replace(l_sql,'{:tags:}',get_tags_sql(l_tags.count)); + l_sql := replace(l_sql,'{:random_seed:}',get_random_seed_sql(a_random_seed)); + ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_key_anyvalues().put('l_sql',l_sql) ); + + execute immediate l_sql + bulk collect into l_results + using l_schema_paths, l_include_tags, l_include_tags, l_exclude_tags, a_random_seed; + return l_results; + end; + + function get_schema_parse_time(a_schema_name varchar2) return timestamp result_cache is l_cache_parse_time timestamp; diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 0a38851fe..10444a4d2 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -53,6 +53,12 @@ create or replace package ut_suite_cache_manager authid definer is a_random_seed positive := null, a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows; + + function get_cached_suite_rows( + a_paths ut_varchar2_list, + a_random_seed positive := null, + a_tags ut_varchar2_rows := null + ) return ut_suite_cache_rows; /* * Retrieves suite item info rows from cache. diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 4bcb83afa..2f081d2c2 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -18,14 +18,6 @@ create or replace package body ut_suite_manager is gc_suitpath_error_message constant varchar2(100) := 'Suitepath exceeds 1000 CHAR on: '; - type t_path_item is record ( - object_name varchar2(250), - procedure_name varchar2(250), - suite_path varchar2(4000) - ); - type t_path_items is table of t_path_item; - type t_schema_paths is table of t_path_items index by varchar2(250 char); - cursor c_cached_suites_cursor is select * from table(ut_suite_cache_rows()); type tt_cached_suites is table of c_cached_suites_cursor%rowtype; type t_cached_suites_cursor is ref cursor return c_cached_suites_cursor%rowtype; @@ -41,7 +33,8 @@ create or replace package body ut_suite_manager is else for i in 1 .. a_paths.count loop l_path := a_paths(i); - if l_path is null or not (regexp_like(l_path, '^[A-Za-z0-9$#_]+(\.[A-Za-z0-9$#_]+){0,2}$') or regexp_like(l_path, '^([A-Za-z0-9$#_]+)?:[A-Za-z0-9$#_]+(\.[A-Za-z0-9$#_]+)*$')) then + if l_path is null or not ( + regexp_like(l_path, '^[A-Za-z0-9$#_\*]+(\.[A-Za-z0-9$#_\*]+){0,2}$') or regexp_like(l_path, '^([A-Za-z0-9$#_]+)?:[A-Za-z0-9$#_\*]+(\.[A-Za-z0-9$#_\*]+)*$')) then raise_application_error(ut_utils.gc_invalid_path_format, 'Invalid path format: ' || nvl(l_path, 'NULL')); end if; end loop; @@ -84,12 +77,17 @@ create or replace package body ut_suite_manager is -- get schema name / object.[procedure] name -- When path is one of: schema or schema.package[.object] or package[.object] -- transform it back to schema[.package[.object]] + -- Object name or procedure is allowed to have filter char + -- However this is not allowed on schema begin - l_object := regexp_substr(a_paths(i), '^[A-Za-z0-9$#_]+'); + l_object := regexp_substr(a_paths(i), '^[A-Za-z0-9$#_\*]+'); l_schema := sys.dbms_assert.schema_name(upper(l_object)); exception when sys.dbms_assert.invalid_schema_name then - if ut_metadata.package_exists_in_cur_schema(upper(l_object)) then + if l_object like '%*%' then + a_paths(i) := c_current_schema || '.' || a_paths(i); + l_schema := c_current_schema; + elsif ut_metadata.package_exists_in_cur_schema(upper(l_object)) then a_paths(i) := c_current_schema || '.' || a_paths(i); l_schema := c_current_schema; else @@ -110,34 +108,6 @@ create or replace package body ut_suite_manager is l_schema_names := resolve_schema_names(a_paths); end; - function group_paths_by_schema(a_paths ut_varchar2_list) return t_schema_paths is - c_package_path_regex constant varchar2(100) := '^([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_]+))?(\.([A-Za-z0-9$#_]+))?$'; - l_schema varchar2(4000); - l_empty_result t_path_item; - l_result t_path_item; - l_results t_schema_paths; - begin - for i in 1 .. a_paths.count loop - l_result := l_empty_result; - if a_paths(i) like '%:%' then - l_schema := upper(regexp_substr(a_paths(i),'^[^.:]+')); - l_result.suite_path := ltrim(regexp_substr(a_paths(i),'[.:].*$'),':'); - else - l_schema := regexp_substr(a_paths(i), c_package_path_regex, subexpression => 1); - l_result.object_name := regexp_substr(a_paths(i), c_package_path_regex, subexpression => 3); - l_result.procedure_name := regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5); - end if; - if l_results.exists(l_schema) then - l_results(l_schema).extend; - l_results(l_schema)(l_results(l_schema).last) := l_result; - else - l_results(l_schema) := t_path_items(l_result); - end if; - end loop; - return l_results; - end; - - function sort_by_seq_no( a_list ut_executables ) return ut_executables is @@ -370,6 +340,45 @@ create or replace package body ut_suite_manager is return l_result; end; + function get_cached_suite_data( + a_paths ut_varchar2_list, + a_random_seed positive, + a_tags ut_varchar2_rows := null + ) return t_cached_suites_cursor is + l_unfiltered_rows ut_suite_cache_rows; + l_result t_cached_suites_cursor; + begin + l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_rows( + a_paths, + a_random_seed, + a_tags + ); + + if ut_metadata.user_has_execute_any_proc() then + open l_result for + select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c; + else + open l_result for + select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c + where sys_context( 'userenv', 'current_user' ) = upper(c.object_owner) + union all + select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c + where sys_context( 'userenv', 'current_user' ) != upper(c.object_owner) + and ( exists + ( select 1 + from all_objects a + where a.object_name = c.object_name + and a.owner = c.object_owner + and a.object_type = 'PACKAGE' + ) + or c.self_type = 'UT_LOGICAL_SUITE'); + + end if; + return l_result; + + return l_result; + end; + function can_skip_all_objects_scan( a_owner_name varchar2 ) return boolean is @@ -442,31 +451,21 @@ create or replace package body ut_suite_manager is ut_event_manager.trigger_event('refresh_cache - end'); end; - procedure add_suites_for_path( - a_owner_name varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, + procedure add_suites_for_paths( + a_paths ut_varchar2_list, a_suites in out nocopy ut_suite_items, a_random_seed positive, a_tags ut_varchar2_rows := null ) is begin - refresh_cache(a_owner_name); - reconstruct_from_cache( a_suites, get_cached_suite_data( - a_owner_name, - a_path, - a_object_name, - a_procedure_name, - can_skip_all_objects_scan(a_owner_name), + a_paths, a_random_seed, a_tags ) ); - end; ----------------------------------------------- @@ -530,20 +529,32 @@ create or replace package body ut_suite_manager is a_tags ut_varchar2_rows := ut_varchar2_rows() ) is l_paths ut_varchar2_list := a_paths; - l_path_items t_path_items; - l_path_item t_path_item; + l_schema_names ut_varchar2_rows; l_schema varchar2(4000); l_suites_count pls_integer := 0; l_index varchar2(4000 char); - l_schema_paths t_schema_paths; begin ut_event_manager.trigger_event('configure_execution_by_path - start'); - a_suites := ut_suite_items(); + a_suites := ut_suite_items(); --resolve schema names from paths and group paths by schema name - resolve_schema_names(l_paths); - - l_schema_paths := group_paths_by_schema(l_paths); + l_schema_names := resolve_schema_names(l_paths); + --refresh cache + l_schema := l_schema_names.first; + while l_schema is not null loop + refresh_cache(upper(l_schema_names(l_schema))); + l_schema := l_schema_names.next(l_schema); + end loop; + + --We will get a single list of paths rather than loop by loop. + add_suites_for_paths( + l_paths, + a_suites, + a_random_seed, + a_tags + ); + + /* l_schema := l_schema_paths.first; while l_schema is not null loop l_path_items := l_schema_paths(l_schema); @@ -571,8 +582,9 @@ create or replace package body ut_suite_manager is l_suites_count := a_suites.count; end loop; l_schema := l_schema_paths.next(l_schema); - end loop; - + end loop;*/ + + --propagate rollback type to suite items after organizing suites into hierarchy for i in 1 .. a_suites.count loop a_suites(i).set_rollback_type( a_suites(i).get_rollback_type() ); diff --git a/source/install.sql b/source/install.sql index cda057bdf..6f3c16801 100644 --- a/source/install.sql +++ b/source/install.sql @@ -89,7 +89,8 @@ create or replace context &&ut3_owner._info using &&ut3_owner..ut_session_contex @@install_component.sql 'core/types/ut_run.tps' @@install_component.sql 'core/types/ut_reporter_base.tps' @@install_component.sql 'core/types/ut_reporters.tps' - +@@install_component.sql 'core/types/ut_path_item.tps' +@@install_component.sql 'core/types/ut_path_items.tps' @@install_component.sql 'expectations/json_objects_specs.sql' @@install_component.sql 'expectations/matchers/ut_matcher_options_items.tps' @@ -207,6 +208,7 @@ prompt Installing DBMSPLSQL Tables objects into &&ut3_owner schema @@install_component.sql 'core/types/ut_executable_test.tpb' @@install_component.sql 'core/types/ut_console_reporter_base.tps' @@install_component.sql 'core/types/ut_console_reporter_base.tpb' +@@install_component.sql 'core/types/ut_path_item.tpb' --expectations and matchers @@install_component.sql 'expectations/data_values/ut_compound_data_tmp.sql' diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index 4d77d9993..ab4069497 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -88,6 +88,10 @@ drop type ut_suite_items_info force; drop type ut_suite_item_info force; +drop type ut_path_items force; + +drop type ut_path_item force; + drop package ut_suite_manager; drop package ut_suite_builder; From f1f6d71db4728e89413b5ab52a0e973cd3ff5f58 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 19 Mar 2022 14:12:28 +0000 Subject: [PATCH 039/187] Tidy up code to make sure we got distinct set of expanded tests. Addressing issue of WITH error ORA-32036: unsupported case for inlining of query name in WITH clause --- source/core/ut_suite_cache_manager.pkb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index cc5cd0f19..562435e0f 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -85,15 +85,11 @@ create or replace package body ut_suite_cache_manager is gc_get_bulk_cache_suite_sql constant varchar2(32767) := - q'[with - suite_paths_tabs as ( - select schema_name,object_name,procedure_name,suite_path - from table(:l_schema_paths) - ), + q'[with suite_items as ( select /*+ cardinality(c 500) */ value(c) as obj from ut_suite_cache c, - suite_paths_tabs sp + table(:l_schema_paths) sp where c.object_owner = upper(sp.schema_name) and sp.suite_path is not null and ( @@ -108,7 +104,7 @@ create or replace package body ut_suite_cache_manager is union all select /*+ cardinality(c 500) */ value(c) as obj from ut_suite_cache c, - suite_paths_tabs sp + table(:l_schema_paths) sp where c.object_owner = upper(sp.schema_name) and sp.suite_path is null and c.object_name like nvl(upper(replace(sp.object_name,'*','%')),c.object_name) @@ -388,7 +384,11 @@ create or replace package body ut_suite_cache_manager is ) select ut_path_item(schema_name,object_name,procedure_name,suite_path) bulk collect into l_schema_paths - from paths_to_expand; + from + (select schema_name,object_name,procedure_name,suite_path, + row_number() over ( partition by schema_name,object_name,procedure_name,suite_path order by 1) r_num + from paths_to_expand) + where r_num = 1 ; return l_schema_paths; end; @@ -429,7 +429,7 @@ create or replace package body ut_suite_cache_manager is execute immediate l_sql bulk collect into l_results - using l_schema_paths, l_include_tags, l_include_tags, l_exclude_tags, a_random_seed; + using l_schema_paths, l_schema_paths, l_include_tags, l_include_tags, l_exclude_tags, a_random_seed; return l_results; end; From 01ec694a0289562f7434699493fa6dbed5af7022 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 19 Mar 2022 17:14:08 +0000 Subject: [PATCH 040/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index b93720226..ad0cad34c 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index a96043438..9641132fd 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 1402d09ad..c1eefa2dd 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 9c2e9ee4a..5812e2cab 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 740bc199a..140c3e3dd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 72aca4936..9e4528342 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 3017acdc5..a2612c3b8 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 8a7045e9c..9c90a1865 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 018b206bd..2c262abbf 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 7a1445c2d..27dfc6c1f 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 34f0970d5..8e1872497 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 28cc3de62..3aa97dcb8 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index f1e96e50d..08308bc8a 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 2d947f391..11e08be1d 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 3ba397177..373830f95 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index f392dd1e5..d3fcfd520 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 5137e6490..bf5cf8c7b 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3940--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index aeff16dd8..027a06c21 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3940-develop'; + gc_version constant varchar2(50) := 'v3.1.13.3943-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 1454221535f2dc53e2e776a1bbf97bc09da8a079 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 23 Mar 2022 19:45:20 +0000 Subject: [PATCH 041/187] Adding extra fields. --- source/core/types/ut_path_item.tpb | 9 ++- source/core/types/ut_path_item.tps | 15 +++-- source/core/ut_suite_cache_manager.pkb | 67 +++++++++++-------- source/core/ut_suite_cache_manager.pks | 4 +- source/core/ut_suite_manager.pkb | 93 ++++++++++++++++++-------- source/core/ut_suite_manager.pks | 4 ++ 6 files changed, 126 insertions(+), 66 deletions(-) diff --git a/source/core/types/ut_path_item.tpb b/source/core/types/ut_path_item.tpb index 3878b544c..2973b3412 100644 --- a/source/core/types/ut_path_item.tpb +++ b/source/core/types/ut_path_item.tpb @@ -15,27 +15,30 @@ create or replace type body ut_path_item as See the License for the specific language governing permissions and limitations under the License. */ - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2) return self as result is + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2, originated_path varchar2) return self as result is begin self.schema_name := schema_name; self.object_name := object_name; self.procedure_name := procedure_name; + self.originated_path := originated_path; return; end; - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2,suite_path varchar2) return self as result is + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2,suite_path varchar2, originated_path varchar2) return self as result is begin self.schema_name := schema_name; self.suite_path := suite_path; + self.originated_path := originated_path; return; end; - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result is + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2, originated_path varchar2) return self as result is begin self.schema_name := schema_name; self.object_name := object_name; self.procedure_name := procedure_name; self.suite_path := suite_path; + self.originated_path := originated_path; return; end; end; diff --git a/source/core/types/ut_path_item.tps b/source/core/types/ut_path_item.tps index 9a5ef51d0..c4b751abc 100644 --- a/source/core/types/ut_path_item.tps +++ b/source/core/types/ut_path_item.tps @@ -15,12 +15,13 @@ create or replace type ut_path_item as object ( See the License for the specific language governing permissions and limitations under the License. */ - schema_name varchar2(4000), - object_name varchar2(250), - procedure_name varchar2(250), - suite_path varchar2(4000), - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2) return self as result, - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2,suite_path varchar2) return self as result, - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result + schema_name varchar2(4000), + object_name varchar2(250), + procedure_name varchar2(250), + suite_path varchar2(4000), + originated_path varchar2(4000), + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2, originated_path varchar2) return self as result, + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, suite_path varchar2, originated_path varchar2) return self as result, + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2, originated_path varchar2) return self as result ) / \ No newline at end of file diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 562435e0f..aea6fc24b 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -277,13 +277,15 @@ create or replace package body ut_suite_cache_manager is for i in 1 .. a_paths.count loop l_results.extend; if a_paths(i) like '%:%' then - l_path_item := ut_path_item(upper(regexp_substr(a_paths(i),'^[^.:]+')), - ltrim(regexp_substr(a_paths(i),'[.:].*$'),':')); + l_path_item := ut_path_item(schema_name => upper(regexp_substr(a_paths(i),'^[^.:]+')), + suite_path => ltrim(regexp_substr(a_paths(i),'[.:].*$'),':'), + originated_path => a_paths(i)); l_results(l_results.last) := l_path_item; else - l_path_item := ut_path_item(regexp_substr(a_paths(i), c_package_path_regex, subexpression => 1), - regexp_substr(a_paths(i), c_package_path_regex, subexpression => 3), - regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5)); + l_path_item := ut_path_item(schema_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 1), + object_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 3), + procedure_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5), + originated_path => a_paths(i)); l_results(l_results.last) := l_path_item; end if; end loop; @@ -359,41 +361,50 @@ create or replace package body ut_suite_cache_manager is l_schema_paths ut_path_items:= ut_path_items(); begin with paths_to_expand as ( - select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(sp.object_name,c.object_name) as object_name,sp.procedure_name as procedure_name - from ut_suite_cache c, - table(a_schema_paths) sp - where c.object_owner = upper(sp.schema_name) - and c.object_name like nvl(replace(upper(sp.object_name),'*','%'),c.object_name) - and c.name like nvl(replace(upper(sp.procedure_name),'*','%'), c.name) - and sp.suite_path is null - group by sp.schema_name,nvl(sp.object_name,c.object_name),sp.procedure_name + select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(sp.object_name,c.object_name) as object_name, + sp.procedure_name as procedure_name,sp.originated_path + from table(a_schema_paths) sp left outer join ut_suite_cache c + on ( c.object_owner = upper(sp.schema_name) + and c.object_name like replace(upper(sp.object_name),'*','%') + and c.name like nvl(replace(upper(sp.procedure_name),'*','%'), c.name)) + where sp.suite_path is null + and sp.object_name is not null + group by sp.schema_name,nvl(sp.object_name,c.object_name),sp.procedure_name,sp.originated_path union all - select /*+ no_parallel */ c.path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name - from - ut_suite_cache c, - table(a_schema_paths) sp - where c.object_owner = upper(sp.schema_name) - and sp.suite_path is not null - and instr(sp.suite_path,'*') > 0 - and c.path like replace(sp.suite_path,'*','%') + select /*+ no_parallel */ c.path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name,sp.originated_path + from + table(a_schema_paths) sp left outer join ut_suite_cache c on + ( c.object_owner = upper(sp.schema_name) + and sp.suite_path is not null + and instr(sp.suite_path,'*') > 0) + where c.path like replace(sp.suite_path,'*','%') union all - select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name - from table(a_schema_paths) sp + select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name,sp.originated_path + from table(a_schema_paths) sp where sp.suite_path is not null - and instr(sp.suite_path,'*') = 0 + and instr(sp.suite_path,'*') = 0 + union all + select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name,sp.originated_path + from table(a_schema_paths) sp + where sp.suite_path is null and sp.object_name is null ) - select ut_path_item(schema_name,object_name,procedure_name,suite_path) + select ut_path_item(schema_name,object_name,procedure_name,suite_path,originated_path) bulk collect into l_schema_paths from - (select schema_name,object_name,procedure_name,suite_path, + (select schema_name,object_name,procedure_name,suite_path,originated_path, row_number() over ( partition by schema_name,object_name,procedure_name,suite_path order by 1) r_num from paths_to_expand) where r_num = 1 ; return l_schema_paths; end; + function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items is + begin + return expand_paths(group_paths_by_schema(a_paths)); + end; + function get_cached_suite_rows( - a_paths ut_varchar2_list, + a_schema_paths ut_path_items, a_random_seed positive := null, a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows is @@ -417,7 +428,7 @@ create or replace package body ut_suite_cache_manager is from table(l_tags) where column_value like '-%'; - l_schema_paths := expand_paths(group_paths_by_schema(a_paths)); + l_schema_paths := a_schema_paths; --We still need to turn this into qualified SQL name....maybe as part of results ? l_suite_item_name := case when l_tags.count > 0 then 'suite_items_tags' else 'suite_items' end; diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 10444a4d2..3e2ac6451 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -54,8 +54,10 @@ create or replace package ut_suite_cache_manager authid definer is a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows; + function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items; + function get_cached_suite_rows( - a_paths ut_varchar2_list, + a_schema_paths ut_path_items, a_random_seed positive := null, a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows; diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 2f081d2c2..2f019438c 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -18,10 +18,7 @@ create or replace package body ut_suite_manager is gc_suitpath_error_message constant varchar2(100) := 'Suitepath exceeds 1000 CHAR on: '; - cursor c_cached_suites_cursor is select * from table(ut_suite_cache_rows()); - type tt_cached_suites is table of c_cached_suites_cursor%rowtype; type t_cached_suites_cursor is ref cursor return c_cached_suites_cursor%rowtype; - type t_item_levels is table of ut_suite_items index by binary_integer; ------------------ @@ -339,30 +336,20 @@ create or replace package body ut_suite_manager is return l_result; end; - - function get_cached_suite_data( - a_paths ut_varchar2_list, - a_random_seed positive, - a_tags ut_varchar2_rows := null - ) return t_cached_suites_cursor is - l_unfiltered_rows ut_suite_cache_rows; + + function get_filtered_cursor(a_unfiltered_rows in ut_suite_cache_rows) + return t_cached_suites_cursor is l_result t_cached_suites_cursor; begin - l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_rows( - a_paths, - a_random_seed, - a_tags - ); - if ut_metadata.user_has_execute_any_proc() then open l_result for - select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c; + select /*+ no_parallel */ c.* from table(a_unfiltered_rows) c; else open l_result for - select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c + select /*+ no_parallel */ c.* from table(a_unfiltered_rows) c where sys_context( 'userenv', 'current_user' ) = upper(c.object_owner) union all - select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c + select /*+ no_parallel */ c.* from table(a_unfiltered_rows) c where sys_context( 'userenv', 'current_user' ) != upper(c.object_owner) and ( exists ( select 1 @@ -371,13 +358,61 @@ create or replace package body ut_suite_manager is and a.owner = c.object_owner and a.object_type = 'PACKAGE' ) - or c.self_type = 'UT_LOGICAL_SUITE'); - - end if; - return l_result; - + or c.self_type = 'UT_LOGICAL_SUITE'); + end if; return l_result; end; + + procedure reconcile_paths_and_suites( + a_schema_paths ut_path_items, + a_filtered_rows t_cached_suites_cursor + ) is + l_rows_tmp tt_cached_suites:= tt_cached_suites(); + l_rows tt_cached_suites := tt_cached_suites(); + l_limit number := 5000; + begin + loop + fetch a_filtered_rows bulk collect into l_rows_tmp limit l_limit; + l_rows := l_rows multiset union l_rows_tmp; + exit when a_filtered_rows%NOTFOUND; + end loop; + close a_filtered_rows; + + for i in ( select /*+ no_parallel */sp.schema_name,sp.object_name,sp.procedure_name, + sp.suite_path,sp.originated_path,sc.path + from table(a_schema_paths) sp left outer join + table(l_rows) sc on + (( upper(sp.schema_name) = upper(sc.object_owner) and upper(sp.object_name) = upper(sc.object_name) + and nvl(upper(sp.procedure_name),sc.name) = sc.name ) + or (sc.path = sp.suite_path)) + where sc.path is null) + loop + if i.suite_path is not null then + raise_application_error(ut_utils.gc_suite_package_not_found,'No suite packages found for path '||i.schema_name||':'||i.suite_path|| '.'); + elsif i.procedure_name is not null then + raise_application_error(ut_utils.gc_suite_package_not_found,'Suite test '||i.schema_name||'.'||i.object_name|| '.'||i.procedure_name||' does not exist'); + elsif i.object_name is not null then + raise_application_error(ut_utils.gc_suite_package_not_found,'Suite package '||i.schema_name||'.'||i.object_name|| ' does not exist'); + end if; + end loop; + end; + + function get_cached_suite_data( + a_schema_paths ut_path_items, + a_random_seed positive, + a_tags ut_varchar2_rows := null + ) return t_cached_suites_cursor is + l_unfiltered_rows ut_suite_cache_rows; + l_result t_cached_suites_cursor; + begin + l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_rows( + a_schema_paths, + a_random_seed, + a_tags + ); + reconcile_paths_and_suites(a_schema_paths,get_filtered_cursor(l_unfiltered_rows)); + return get_filtered_cursor(l_unfiltered_rows); + end; function can_skip_all_objects_scan( a_owner_name varchar2 @@ -452,7 +487,7 @@ create or replace package body ut_suite_manager is end; procedure add_suites_for_paths( - a_paths ut_varchar2_list, + a_schema_paths ut_path_items, a_suites in out nocopy ut_suite_items, a_random_seed positive, a_tags ut_varchar2_rows := null @@ -461,7 +496,7 @@ create or replace package body ut_suite_manager is reconstruct_from_cache( a_suites, get_cached_suite_data( - a_paths, + a_schema_paths, a_random_seed, a_tags ) @@ -530,6 +565,8 @@ create or replace package body ut_suite_manager is ) is l_paths ut_varchar2_list := a_paths; l_schema_names ut_varchar2_rows; + l_schema_paths ut_path_items; + l_reconcile_paths ut_path_items; l_schema varchar2(4000); l_suites_count pls_integer := 0; l_index varchar2(4000 char); @@ -546,9 +583,11 @@ create or replace package body ut_suite_manager is l_schema := l_schema_names.next(l_schema); end loop; + l_schema_paths := ut_suite_cache_manager.get_schema_paths(l_paths); + --We will get a single list of paths rather than loop by loop. add_suites_for_paths( - l_paths, + l_schema_paths, a_suites, a_random_seed, a_tags diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index 5ae98d72a..e4160f599 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -20,6 +20,10 @@ create or replace package ut_suite_manager authid current_user is * Resposible for building hierarhy of sutes from individual suites created by suite_builder */ + cursor c_cached_suites_cursor is select * from table(ut_suite_cache_rows()); + type tt_cached_suites is table of c_cached_suites_cursor%rowtype; + + /** * @private * From ce4df285da6cd303fd38df345b0d68389dcaf348 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 29 Mar 2022 17:30:36 +0100 Subject: [PATCH 042/187] Stage 3. Fixing error calls. --- source/core/types/ut_path_item.tpb | 9 +- source/core/types/ut_path_item.tps | 7 +- source/core/ut_suite_cache_manager.pkb | 25 ++-- source/core/ut_suite_manager.pkb | 196 ++++++++++++++++++++++--- source/core/ut_suite_manager.pks | 3 - 5 files changed, 194 insertions(+), 46 deletions(-) diff --git a/source/core/types/ut_path_item.tpb b/source/core/types/ut_path_item.tpb index 2973b3412..3878b544c 100644 --- a/source/core/types/ut_path_item.tpb +++ b/source/core/types/ut_path_item.tpb @@ -15,30 +15,27 @@ create or replace type body ut_path_item as See the License for the specific language governing permissions and limitations under the License. */ - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2, originated_path varchar2) return self as result is + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2) return self as result is begin self.schema_name := schema_name; self.object_name := object_name; self.procedure_name := procedure_name; - self.originated_path := originated_path; return; end; - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2,suite_path varchar2, originated_path varchar2) return self as result is + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2,suite_path varchar2) return self as result is begin self.schema_name := schema_name; self.suite_path := suite_path; - self.originated_path := originated_path; return; end; - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2, originated_path varchar2) return self as result is + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result is begin self.schema_name := schema_name; self.object_name := object_name; self.procedure_name := procedure_name; self.suite_path := suite_path; - self.originated_path := originated_path; return; end; end; diff --git a/source/core/types/ut_path_item.tps b/source/core/types/ut_path_item.tps index c4b751abc..f6c64195c 100644 --- a/source/core/types/ut_path_item.tps +++ b/source/core/types/ut_path_item.tps @@ -19,9 +19,8 @@ create or replace type ut_path_item as object ( object_name varchar2(250), procedure_name varchar2(250), suite_path varchar2(4000), - originated_path varchar2(4000), - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2, originated_path varchar2) return self as result, - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, suite_path varchar2, originated_path varchar2) return self as result, - constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2, originated_path varchar2) return self as result + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2) return self as result, + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, suite_path varchar2) return self as result, + constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result ) / \ No newline at end of file diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index aea6fc24b..a83be01a0 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -278,14 +278,12 @@ create or replace package body ut_suite_cache_manager is l_results.extend; if a_paths(i) like '%:%' then l_path_item := ut_path_item(schema_name => upper(regexp_substr(a_paths(i),'^[^.:]+')), - suite_path => ltrim(regexp_substr(a_paths(i),'[.:].*$'),':'), - originated_path => a_paths(i)); + suite_path => ltrim(regexp_substr(a_paths(i),'[.:].*$'),':')); l_results(l_results.last) := l_path_item; else l_path_item := ut_path_item(schema_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 1), object_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 3), - procedure_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5), - originated_path => a_paths(i)); + procedure_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5)); l_results(l_results.last) := l_path_item; end if; end loop; @@ -359,19 +357,19 @@ create or replace package body ut_suite_cache_manager is function expand_paths(a_schema_paths ut_path_items) return ut_path_items is l_schema_paths ut_path_items:= ut_path_items(); - begin + begin with paths_to_expand as ( select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(sp.object_name,c.object_name) as object_name, - sp.procedure_name as procedure_name,sp.originated_path + sp.procedure_name as procedure_name from table(a_schema_paths) sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) and c.object_name like replace(upper(sp.object_name),'*','%') and c.name like nvl(replace(upper(sp.procedure_name),'*','%'), c.name)) where sp.suite_path is null and sp.object_name is not null - group by sp.schema_name,nvl(sp.object_name,c.object_name),sp.procedure_name,sp.originated_path + group by sp.schema_name,nvl(sp.object_name,c.object_name),sp.procedure_name union all - select /*+ no_parallel */ c.path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name,sp.originated_path + select /*+ no_parallel */ c.path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name from table(a_schema_paths) sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) @@ -379,22 +377,25 @@ create or replace package body ut_suite_cache_manager is and instr(sp.suite_path,'*') > 0) where c.path like replace(sp.suite_path,'*','%') union all - select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name,sp.originated_path + select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name from table(a_schema_paths) sp where sp.suite_path is not null and instr(sp.suite_path,'*') = 0 union all - select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name,sp.originated_path + select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name from table(a_schema_paths) sp where sp.suite_path is null and sp.object_name is null ) - select ut_path_item(schema_name,object_name,procedure_name,suite_path,originated_path) + select ut_path_item(schema_name,object_name,procedure_name,suite_path) bulk collect into l_schema_paths from - (select schema_name,object_name,procedure_name,suite_path,originated_path, + (select schema_name,object_name,procedure_name,suite_path, row_number() over ( partition by schema_name,object_name,procedure_name,suite_path order by 1) r_num from paths_to_expand) where r_num = 1 ; + + + return l_schema_paths; end; diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 2f019438c..2f21cdb67 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -17,7 +17,8 @@ create or replace package body ut_suite_manager is */ gc_suitpath_error_message constant varchar2(100) := 'Suitepath exceeds 1000 CHAR on: '; - + cursor c_cached_suites_cursor is select * from table(ut_suite_cache_rows()); + type tt_cached_suites is table of c_cached_suites_cursor%rowtype; type t_cached_suites_cursor is ref cursor return c_cached_suites_cursor%rowtype; type t_item_levels is table of ut_suite_items index by binary_integer; ------------------ @@ -252,6 +253,121 @@ create or replace package body ut_suite_manager is return l_result; end; + function get_logical_suite( + a_rows ut_suite_cache_rows, + a_idx pls_integer, + a_level pls_integer, + a_prev_level pls_integer, + a_items_at_level t_item_levels + ) return ut_suite_item is + l_result ut_suite_item; + begin + case a_rows( a_idx ).self_type + when 'UT_SUITE' then + l_result := + case when a_prev_level > a_level then + ut_suite( + self_type => a_rows( a_idx ).self_type, + object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), + name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, + rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, + line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, + start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, + results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), + items => a_items_at_level(a_prev_level), + before_all_list => sort_by_seq_no( a_rows( a_idx ).before_all_list), after_all_list => sort_by_seq_no( + a_rows( a_idx ).after_all_list), tags => a_rows(a_idx).tags + ) + else + ut_suite( + self_type => a_rows( a_idx ).self_type, + object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), + name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, + rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, + line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, + start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, + results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), + items => ut_suite_items(), + before_all_list => sort_by_seq_no( a_rows( a_idx ).before_all_list), after_all_list => sort_by_seq_no( + a_rows( a_idx ).after_all_list), tags => a_rows(a_idx).tags + ) + end; + when 'UT_SUITE_CONTEXT' then + l_result := + case when a_prev_level > a_level then + ut_suite_context( + self_type => a_rows( a_idx ).self_type, + object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), + name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, + rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, + line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, + start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, + results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), + items => a_items_at_level(a_prev_level), + before_all_list => sort_by_seq_no( a_rows( a_idx ).before_all_list), after_all_list => sort_by_seq_no( + a_rows( a_idx ).after_all_list), tags => a_rows(a_idx).tags + ) + else + ut_suite_context( + self_type => a_rows( a_idx ).self_type, + object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), + name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, + rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, + line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, + start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, + results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), + items => ut_suite_items(), + before_all_list => sort_by_seq_no( a_rows( a_idx ).before_all_list), after_all_list => sort_by_seq_no( + a_rows( a_idx ).after_all_list), tags => a_rows(a_idx).tags + ) + end; + when 'UT_LOGICAL_SUITE' then + l_result := + case when a_prev_level > a_level then + ut_logical_suite( + self_type => a_rows( a_idx ).self_type, + object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), + name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, + rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, + line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, + start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, + results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), + items => a_items_at_level(a_prev_level), tags => null + ) + else + ut_logical_suite( + self_type => a_rows( a_idx ).self_type, + object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), + name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, + rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, + line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, + start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, + results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), + items => ut_suite_items(), tags => null + ) + end; + when 'UT_TEST' then + l_result := + ut_test( + self_type => a_rows(a_idx).self_type, + object_owner => a_rows(a_idx).object_owner, object_name => lower(a_rows(a_idx).object_name), + name => lower(a_rows(a_idx).name), description => a_rows(a_idx).description, path => a_rows(a_idx).path, + rollback_type => a_rows(a_idx).rollback_type, disabled_flag => a_rows(a_idx).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, + line_no => a_rows(a_idx).line_no, parse_time => a_rows(a_idx).parse_time, + start_time => null, end_time => null, result => null, warnings => a_rows(a_idx).warnings, + results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), + before_each_list => sort_by_seq_no(a_rows(a_idx).before_each_list), before_test_list => sort_by_seq_no(a_rows(a_idx).before_test_list), + item => a_rows(a_idx).item, + after_test_list => sort_by_seq_no(a_rows(a_idx).after_test_list), after_each_list => sort_by_seq_no(a_rows(a_idx).after_each_list), + all_expectations => ut_expectation_results(), failed_expectations => ut_expectation_results(), + parent_error_stack_trace => null, expected_error_codes => a_rows(a_idx).expected_error_codes, + tags => a_rows(a_idx).tags + ); + end case; + l_result.results_count.warnings_count := l_result.warnings.count; + return l_result; + end; + procedure reconstruct_from_cache( a_suites in out nocopy ut_suite_items, a_suite_data_cursor sys_refcursor @@ -298,6 +414,47 @@ create or replace package body ut_suite_manager is close a_suite_data_cursor; end reconstruct_from_cache; + procedure reconstruct_from_cache( + a_suites in out nocopy ut_suite_items, + a_suite_data_cursor ut_suite_cache_rows + ) is + c_bulk_limit constant pls_integer := 1000; + l_items_at_level t_item_levels; + l_rows ut_suite_cache_rows := a_suite_data_cursor; + l_level pls_integer; + l_prev_level pls_integer; + l_idx integer; + begin + l_idx := l_rows.first; + while l_idx is not null loop + l_level := length(l_rows(l_idx).path) - length( replace(l_rows(l_idx).path, '.') ) + 1; + if l_level > 1 then + if not l_items_at_level.exists(l_level) then + l_items_at_level(l_level) := ut_suite_items(); + end if; + l_items_at_level(l_level).extend; + pragma inline(get_logical_suite, 'YES'); + l_items_at_level(l_level)(l_items_at_level(l_level).last) := get_logical_suite(l_rows, l_idx, l_level,l_prev_level, l_items_at_level ); + else + a_suites.extend; + pragma inline(get_logical_suite, 'YES'); + a_suites(a_suites.last) := get_logical_suite(l_rows, l_idx, l_level,l_prev_level, l_items_at_level ); + end if; + if l_prev_level > l_level then + l_items_at_level(l_prev_level).delete; + end if; + l_prev_level := l_level; + l_idx := l_rows.next(l_idx); + end loop; + + reverse_list_order( a_suites ); + + for i in 1 .. a_suites.count loop + a_suites( i ).set_rollback_type( a_suites( i ).get_rollback_type ); + end loop; + end reconstruct_from_cache; + + function get_cached_suite_data( a_object_owner varchar2, a_path varchar2 := null, @@ -338,14 +495,13 @@ create or replace package body ut_suite_manager is end; function get_filtered_cursor(a_unfiltered_rows in ut_suite_cache_rows) - return t_cached_suites_cursor is - l_result t_cached_suites_cursor; + return ut_suite_cache_rows is + l_result ut_suite_cache_rows := ut_suite_cache_rows(); begin if ut_metadata.user_has_execute_any_proc() then - open l_result for - select /*+ no_parallel */ c.* from table(a_unfiltered_rows) c; + l_result := a_unfiltered_rows; else - open l_result for + for i in ( select /*+ no_parallel */ c.* from table(a_unfiltered_rows) c where sys_context( 'userenv', 'current_user' ) = upper(c.object_owner) union all @@ -358,30 +514,29 @@ create or replace package body ut_suite_manager is and a.owner = c.object_owner and a.object_type = 'PACKAGE' ) - or c.self_type = 'UT_LOGICAL_SUITE'); + or c.self_type = 'UT_LOGICAL_SUITE')) + loop + l_result.extend; + l_result(l_result.last) := ut_suite_cache_row(i.id,i.self_type,i.path,i.object_owner,i.object_name,i.name,i.line_no,i.parse_time, + i.description,i.rollback_type,i.disabled_flag,i.disabled_reason,i.warnings,i.before_all_list,i.after_all_list,i.before_each_list, + i.before_test_list,i.after_each_list,i.after_test_list,i.expected_error_codes,i.tags,i.item); + end loop; end if; return l_result; end; procedure reconcile_paths_and_suites( a_schema_paths ut_path_items, - a_filtered_rows t_cached_suites_cursor + a_filtered_rows ut_suite_cache_rows ) is l_rows_tmp tt_cached_suites:= tt_cached_suites(); l_rows tt_cached_suites := tt_cached_suites(); l_limit number := 5000; - begin - loop - fetch a_filtered_rows bulk collect into l_rows_tmp limit l_limit; - l_rows := l_rows multiset union l_rows_tmp; - exit when a_filtered_rows%NOTFOUND; - end loop; - close a_filtered_rows; - - for i in ( select /*+ no_parallel */sp.schema_name,sp.object_name,sp.procedure_name, - sp.suite_path,sp.originated_path,sc.path + begin + for i in ( select /*+ no_parallel */ sp.schema_name,sp.object_name,sp.procedure_name, + sp.suite_path,sc.path from table(a_schema_paths) sp left outer join - table(l_rows) sc on + table(a_filtered_rows) sc on (( upper(sp.schema_name) = upper(sc.object_owner) and upper(sp.object_name) = upper(sc.object_name) and nvl(upper(sp.procedure_name),sc.name) = sc.name ) or (sc.path = sp.suite_path)) @@ -401,9 +556,8 @@ create or replace package body ut_suite_manager is a_schema_paths ut_path_items, a_random_seed positive, a_tags ut_varchar2_rows := null - ) return t_cached_suites_cursor is + ) return ut_suite_cache_rows is l_unfiltered_rows ut_suite_cache_rows; - l_result t_cached_suites_cursor; begin l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_rows( a_schema_paths, diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index e4160f599..acc298516 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -20,9 +20,6 @@ create or replace package ut_suite_manager authid current_user is * Resposible for building hierarhy of sutes from individual suites created by suite_builder */ - cursor c_cached_suites_cursor is select * from table(ut_suite_cache_rows()); - type tt_cached_suites is table of c_cached_suites_cursor%rowtype; - /** * @private From 273962b39c864cfcc38616f3827d434e6fc4879b Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 30 Mar 2022 00:13:11 +0100 Subject: [PATCH 043/187] Fixing issue with a non visible tests. --- source/core/ut_suite_manager.pkb | 173 ++----------------------------- 1 file changed, 11 insertions(+), 162 deletions(-) diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 2f21cdb67..45eec7c14 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -253,121 +253,6 @@ create or replace package body ut_suite_manager is return l_result; end; - function get_logical_suite( - a_rows ut_suite_cache_rows, - a_idx pls_integer, - a_level pls_integer, - a_prev_level pls_integer, - a_items_at_level t_item_levels - ) return ut_suite_item is - l_result ut_suite_item; - begin - case a_rows( a_idx ).self_type - when 'UT_SUITE' then - l_result := - case when a_prev_level > a_level then - ut_suite( - self_type => a_rows( a_idx ).self_type, - object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), - name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, - rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, - line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, - start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, - results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), - items => a_items_at_level(a_prev_level), - before_all_list => sort_by_seq_no( a_rows( a_idx ).before_all_list), after_all_list => sort_by_seq_no( - a_rows( a_idx ).after_all_list), tags => a_rows(a_idx).tags - ) - else - ut_suite( - self_type => a_rows( a_idx ).self_type, - object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), - name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, - rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, - line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, - start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, - results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), - items => ut_suite_items(), - before_all_list => sort_by_seq_no( a_rows( a_idx ).before_all_list), after_all_list => sort_by_seq_no( - a_rows( a_idx ).after_all_list), tags => a_rows(a_idx).tags - ) - end; - when 'UT_SUITE_CONTEXT' then - l_result := - case when a_prev_level > a_level then - ut_suite_context( - self_type => a_rows( a_idx ).self_type, - object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), - name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, - rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, - line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, - start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, - results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), - items => a_items_at_level(a_prev_level), - before_all_list => sort_by_seq_no( a_rows( a_idx ).before_all_list), after_all_list => sort_by_seq_no( - a_rows( a_idx ).after_all_list), tags => a_rows(a_idx).tags - ) - else - ut_suite_context( - self_type => a_rows( a_idx ).self_type, - object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), - name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, - rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, - line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, - start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, - results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), - items => ut_suite_items(), - before_all_list => sort_by_seq_no( a_rows( a_idx ).before_all_list), after_all_list => sort_by_seq_no( - a_rows( a_idx ).after_all_list), tags => a_rows(a_idx).tags - ) - end; - when 'UT_LOGICAL_SUITE' then - l_result := - case when a_prev_level > a_level then - ut_logical_suite( - self_type => a_rows( a_idx ).self_type, - object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), - name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, - rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, - line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, - start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, - results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), - items => a_items_at_level(a_prev_level), tags => null - ) - else - ut_logical_suite( - self_type => a_rows( a_idx ).self_type, - object_owner => a_rows( a_idx ).object_owner, object_name => lower( a_rows( a_idx ).object_name), - name => lower( a_rows( a_idx ).name), description => a_rows( a_idx ).description, path => a_rows( a_idx ).path, - rollback_type => a_rows( a_idx ).rollback_type, disabled_flag => a_rows( a_idx ).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, - line_no => a_rows( a_idx ).line_no, parse_time => a_rows( a_idx ).parse_time, - start_time => null, end_time => null, result => null, warnings => a_rows( a_idx ).warnings, - results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), - items => ut_suite_items(), tags => null - ) - end; - when 'UT_TEST' then - l_result := - ut_test( - self_type => a_rows(a_idx).self_type, - object_owner => a_rows(a_idx).object_owner, object_name => lower(a_rows(a_idx).object_name), - name => lower(a_rows(a_idx).name), description => a_rows(a_idx).description, path => a_rows(a_idx).path, - rollback_type => a_rows(a_idx).rollback_type, disabled_flag => a_rows(a_idx).disabled_flag, disabled_reason => a_rows(a_idx).disabled_reason, - line_no => a_rows(a_idx).line_no, parse_time => a_rows(a_idx).parse_time, - start_time => null, end_time => null, result => null, warnings => a_rows(a_idx).warnings, - results_count => ut_results_counter(), transaction_invalidators => ut_varchar2_list(), - before_each_list => sort_by_seq_no(a_rows(a_idx).before_each_list), before_test_list => sort_by_seq_no(a_rows(a_idx).before_test_list), - item => a_rows(a_idx).item, - after_test_list => sort_by_seq_no(a_rows(a_idx).after_test_list), after_each_list => sort_by_seq_no(a_rows(a_idx).after_each_list), - all_expectations => ut_expectation_results(), failed_expectations => ut_expectation_results(), - parent_error_stack_trace => null, expected_error_codes => a_rows(a_idx).expected_error_codes, - tags => a_rows(a_idx).tags - ); - end case; - l_result.results_count.warnings_count := l_result.warnings.count; - return l_result; - end; - procedure reconstruct_from_cache( a_suites in out nocopy ut_suite_items, a_suite_data_cursor sys_refcursor @@ -414,47 +299,7 @@ create or replace package body ut_suite_manager is close a_suite_data_cursor; end reconstruct_from_cache; - procedure reconstruct_from_cache( - a_suites in out nocopy ut_suite_items, - a_suite_data_cursor ut_suite_cache_rows - ) is - c_bulk_limit constant pls_integer := 1000; - l_items_at_level t_item_levels; - l_rows ut_suite_cache_rows := a_suite_data_cursor; - l_level pls_integer; - l_prev_level pls_integer; - l_idx integer; - begin - l_idx := l_rows.first; - while l_idx is not null loop - l_level := length(l_rows(l_idx).path) - length( replace(l_rows(l_idx).path, '.') ) + 1; - if l_level > 1 then - if not l_items_at_level.exists(l_level) then - l_items_at_level(l_level) := ut_suite_items(); - end if; - l_items_at_level(l_level).extend; - pragma inline(get_logical_suite, 'YES'); - l_items_at_level(l_level)(l_items_at_level(l_level).last) := get_logical_suite(l_rows, l_idx, l_level,l_prev_level, l_items_at_level ); - else - a_suites.extend; - pragma inline(get_logical_suite, 'YES'); - a_suites(a_suites.last) := get_logical_suite(l_rows, l_idx, l_level,l_prev_level, l_items_at_level ); - end if; - if l_prev_level > l_level then - l_items_at_level(l_prev_level).delete; - end if; - l_prev_level := l_level; - l_idx := l_rows.next(l_idx); - end loop; - - reverse_list_order( a_suites ); - - for i in 1 .. a_suites.count loop - a_suites( i ).set_rollback_type( a_suites( i ).get_rollback_type ); - end loop; - end reconstruct_from_cache; - - + function get_cached_suite_data( a_object_owner varchar2, a_path varchar2 := null, @@ -529,9 +374,6 @@ create or replace package body ut_suite_manager is a_schema_paths ut_path_items, a_filtered_rows ut_suite_cache_rows ) is - l_rows_tmp tt_cached_suites:= tt_cached_suites(); - l_rows tt_cached_suites := tt_cached_suites(); - l_limit number := 5000; begin for i in ( select /*+ no_parallel */ sp.schema_name,sp.object_name,sp.procedure_name, sp.suite_path,sc.path @@ -556,16 +398,23 @@ create or replace package body ut_suite_manager is a_schema_paths ut_path_items, a_random_seed positive, a_tags ut_varchar2_rows := null - ) return ut_suite_cache_rows is + ) return t_cached_suites_cursor is l_unfiltered_rows ut_suite_cache_rows; + l_filtered_rows ut_suite_cache_rows; + l_result t_cached_suites_cursor; begin l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_rows( a_schema_paths, a_random_seed, a_tags ); - reconcile_paths_and_suites(a_schema_paths,get_filtered_cursor(l_unfiltered_rows)); - return get_filtered_cursor(l_unfiltered_rows); + + l_filtered_rows := get_filtered_cursor(l_unfiltered_rows); + reconcile_paths_and_suites(a_schema_paths,l_filtered_rows); + + open l_result for + select * from table(l_filtered_rows); + return l_result; end; function can_skip_all_objects_scan( From a753e66aa3f8062d0aa6aa3fc2d7386e61fc6176 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 30 Mar 2022 09:54:03 +0100 Subject: [PATCH 044/187] Fixing ORA-600 --- source/core/ut_suite_cache_manager.pkb | 123 ++++++++++++++++--------- 1 file changed, 80 insertions(+), 43 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index a83be01a0..154af6f0c 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -88,34 +88,12 @@ create or replace package body ut_suite_cache_manager is q'[with suite_items as ( select /*+ cardinality(c 500) */ value(c) as obj - from ut_suite_cache c, - table(:l_schema_paths) sp - where c.object_owner = upper(sp.schema_name) - and sp.suite_path is not null - and ( - sp.suite_path||'.' like c.path||'.%' /*all parents and self*/ - or - ( - c.path||'.' like sp.suite_path||'.%' /*all children and self*/ - and c.object_name like nvl(upper(sp.object_name),c.object_name) - and c.name like nvl(upper(sp.procedure_name),c.name) - ) - ) - union all - select /*+ cardinality(c 500) */ value(c) as obj - from ut_suite_cache c, - table(:l_schema_paths) sp - where c.object_owner = upper(sp.schema_name) - and sp.suite_path is null - and c.object_name like nvl(upper(replace(sp.object_name,'*','%')),c.object_name) - and c.name like nvl(upper(replace(sp.procedure_name,'*','%')),c.name) - ), - {:tags:} + from table(:suite_items) c), suitepaths as ( select distinct substr(c.obj.path,1,instr(c.obj.path,'.',-1)-1) as suitepath, c.obj.path as path, c.obj.object_owner as object_owner - from {:suite_item_name:} c + from suite_items c where c.obj.self_type = 'UT_SUITE' ), gen as ( @@ -152,7 +130,7 @@ create or replace package body ut_suite_cache_manager is from logical_suite_data s ), items as ( - select obj from {:suite_item_name:} + select obj from suite_items union all select obj from logical_suites ) @@ -404,44 +382,103 @@ create or replace package body ut_suite_cache_manager is return expand_paths(group_paths_by_schema(a_paths)); end; + function get_suite_items ( + a_schema_paths ut_path_items + ) return ut_suite_cache_rows is + l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); + begin + select /*+ cardinality(c 500) */ value(c) as obj + bulk collect into l_suite_items + from ut_suite_cache c, + table(a_schema_paths) sp + where c.object_owner = upper(sp.schema_name) + and ( + (sp.suite_path is not null and + sp.suite_path||'.' like c.path||'.%' /*all parents and self*/ + or + ( c.path||'.' like sp.suite_path||'.%' /*all children and self*/ + and c.object_name like nvl(upper(sp.object_name),c.object_name) + and c.name like nvl(upper(sp.procedure_name),c.name) ) ) + or + ( sp.suite_path is null + and c.object_name like nvl(upper(replace(sp.object_name,'*','%')),c.object_name) + and c.name like nvl(upper(replace(sp.procedure_name,'*','%')),c.name) + )); + return l_suite_items; + end; + + function get_tags_suites ( + a_suite_items ut_suite_cache_rows, + a_tags ut_varchar2_rows + ) return ut_suite_cache_rows is + l_suite_tags ut_suite_cache_rows := ut_suite_cache_rows(); + l_include_tags ut_varchar2_rows; + l_exclude_tags ut_varchar2_rows; + begin + + select /*+ no_parallel */ column_value + bulk collect into l_include_tags + from table(a_tags) + where column_value not like '-%'; + + select /*+ no_parallel */ ltrim(column_value,'-') + bulk collect into l_exclude_tags + from table(a_tags) + where column_value like '-%'; + + with included_tags as ( + select c.path as path + from table(a_suite_items) c + where c.tags multiset intersect l_include_tags is not empty or l_include_tags is empty + ), + excluded_tags as ( + select c.path as path + from table(a_suite_items) c + where c.tags multiset intersect l_exclude_tags is not empty + ) + select value(c) as obj + bulk collect into l_suite_tags + from table(a_suite_items) c + where exists ( + select 1 from included_tags t + where t.path||'.' like c.path || '.%' /*all parents and self*/ + or c.path||'.' like t.path || '.%' /*all children and self*/ + ) + and not exists ( + select 1 from excluded_tags t + where c.path||'.' like t.path || '.%' /*all children and self*/ + ); + return l_suite_tags; + end; + function get_cached_suite_rows( a_schema_paths ut_path_items, a_random_seed positive := null, a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows is l_results ut_suite_cache_rows := ut_suite_cache_rows(); + l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); l_schema_paths ut_path_items; l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); - l_include_tags ut_varchar2_rows; - l_exclude_tags ut_varchar2_rows; + l_suite_item_name varchar2(20); l_paths ut_varchar2_rows; l_schema varchar2(4000); l_sql varchar2(32767); begin - select /*+ no_parallel */ column_value - bulk collect into l_include_tags - from table(l_tags) - where column_value not like '-%'; - - select /*+ no_parallel */ ltrim(column_value,'-') - bulk collect into l_exclude_tags - from table(l_tags) - where column_value like '-%'; l_schema_paths := a_schema_paths; - --We still need to turn this into qualified SQL name....maybe as part of results ? - l_suite_item_name := case when l_tags.count > 0 then 'suite_items_tags' else 'suite_items' end; - l_sql := gc_get_bulk_cache_suite_sql; - l_sql := replace(l_sql,'{:suite_item_name:}',l_suite_item_name); - l_sql := replace(l_sql,'{:tags:}',get_tags_sql(l_tags.count)); l_sql := replace(l_sql,'{:random_seed:}',get_random_seed_sql(a_random_seed)); + l_suite_items := get_suite_items(a_schema_paths); + if l_tags.count > 0 then + l_suite_items := get_tags_suites(l_suite_items,l_tags); + end if; ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_key_anyvalues().put('l_sql',l_sql) ); - + execute immediate l_sql bulk collect into l_results - using l_schema_paths, l_schema_paths, l_include_tags, l_include_tags, l_exclude_tags, a_random_seed; + using l_suite_items, a_random_seed; return l_results; end; From 0d8d34dae7636626f30da9c285127ad4d3ecc31b Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 30 Mar 2022 13:34:12 +0100 Subject: [PATCH 045/187] Cleanup Phase1. --- source/core/ut_suite_cache_manager.pkb | 220 ++++--------------------- source/core/ut_suite_manager.pkb | 95 ++--------- 2 files changed, 41 insertions(+), 274 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 154af6f0c..b0b3f7d71 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -20,70 +20,6 @@ create or replace package body ut_suite_cache_manager is * Private code */ - gc_get_cache_suite_sql constant varchar2(32767) := - q'[with - suite_items as ( - select /*+ cardinality(c 500) */ value(c) as obj - from ut_suite_cache c - where 1 = 1 - and c.object_owner = :l_object_owner - and ( {:path:} - and {:object_name:} - and {:procedure_name:} - ) - ) - ), - {:tags:} - suitepaths as ( - select distinct substr(c.obj.path,1,instr(c.obj.path,'.',-1)-1) as suitepath, - c.obj.path as path, - c.obj.object_owner as object_owner - from {:suite_item_name:} c - where c.obj.self_type = 'UT_SUITE' - ), - gen as ( - select rownum as pos - from xmltable('1 to 20') - ), - suitepath_part AS ( - select distinct - substr(b.suitepath, 1, instr(b.suitepath || '.', '.', 1, g.pos) -1) as path, - object_owner - from suitepaths b - join gen g - on g.pos <= regexp_count(b.suitepath, '\w+') - ), - logical_suite_data as ( - select 'UT_LOGICAL_SUITE' as self_type, p.path, p.object_owner, - upper( substr(p.path, instr( p.path, '.', -1 ) + 1 ) ) as object_name, - cast(null as ut_executables) as x, - cast(null as ut_varchar2_rows) as y, - cast(null as ut_executable_test) as z - from suitepath_part p - where p.path - not in (select s.path from suitepaths s) - ), - logical_suites as ( - select ut_suite_cache_row( - null, - s.self_type, s.path, s.object_owner, s.object_name, - s.object_name, null, null, null, null, 0,null, - ut_varchar2_rows(), - s.x, s.x, s.x, s.x, s.x, s.x, - s.y, null, s.z - ) as obj - from logical_suite_data s - ), - items as ( - select obj from {:suite_item_name:} - union all - select obj from logical_suites - ) - select /*+ no_parallel */ c.obj - from items c - order by c.obj.object_owner,{:random_seed:}]'; - - gc_get_bulk_cache_suite_sql constant varchar2(32767) := q'[with suite_items as ( @@ -157,61 +93,6 @@ create or replace package body ut_suite_cache_manager is return l_result; end; - - function get_path_sql(a_path in varchar2) return varchar2 is - begin - return case when a_path is not null then q'[ - :l_path||'.' like c.path || '.%' /*all parents and self*/ - or ( c.path||'.' like :l_path || '.%' /*all children and self*/ - ]' - else ' :l_path is null and ( :l_path is null ' end; - end; - - function get_object_name_sql(a_object_name in varchar2) return varchar2 is - begin - return case when a_object_name is not null - then ' c.object_name = :a_object_name ' - else ' :a_object_name is null' end; - end; - - function get_procedure_name_sql(a_procedure_name in varchar2) return varchar2 is - begin - return case when a_procedure_name is not null - then ' c.name = :a_procedure_name' - else ' :a_procedure_name is null' end; - end; - - function get_tags_sql(a_tags_count in integer) return varchar2 is - begin - return case when a_tags_count > 0 then - q'[included_tags as ( - select c.obj.path as path - from suite_items c - where c.obj.tags multiset intersect :a_include_tag_list is not empty or :a_include_tag_list is empty - ), - excluded_tags as ( - select c.obj.path as path - from suite_items c - where c.obj.tags multiset intersect :a_exclude_tag_list is not empty - ), - suite_items_tags as ( - select c.* - from suite_items c - where exists ( - select 1 from included_tags t - where t.path||'.' like c.obj.path || '.%' /*all parents and self*/ - or c.obj.path||'.' like t.path || '.%' /*all children and self*/ - ) - and not exists ( - select 1 from excluded_tags t - where c.obj.path||'.' like t.path || '.%' /*all children and self*/ - ) - ),]' - else - q'[dummy as (select 'x' from dual where :a_include_tag_list is null and :a_include_tag_list is null and :a_exclude_tag_list is null),]' - end; - end; - function get_random_seed_sql(a_random_seed positive) return varchar2 is begin return case @@ -269,70 +150,6 @@ create or replace package body ut_suite_cache_manager is return l_results; end; - - - /* - * Public code - */ - function get_cached_suite_rows( - a_object_owner varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, - a_random_seed positive := null, - a_tags ut_varchar2_rows := null - ) return ut_suite_cache_rows is - l_path varchar2(4000); - l_results ut_suite_cache_rows := ut_suite_cache_rows(); - l_sql varchar2(32767); - l_suite_item_name varchar2(20); - l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); - l_include_tags ut_varchar2_rows; - l_exclude_tags ut_varchar2_rows; - l_object_owner varchar2(250) := ut_utils.qualified_sql_name(a_object_owner); - l_object_name varchar2(250) := ut_utils.qualified_sql_name(a_object_name); - l_procedure_name varchar2(250) := ut_utils.qualified_sql_name(a_procedure_name); - begin - - select /*+ no_parallel */ column_value - bulk collect into l_include_tags - from table(l_tags) - where column_value not like '-%'; - - select /*+ no_parallel */ ltrim(column_value,'-') - bulk collect into l_exclude_tags - from table(l_tags) - where column_value like '-%'; - - if a_path is null and a_object_name is not null then - select /*+ no_parallel */ min(c.path) - into l_path - from ut_suite_cache c - where c.object_owner = upper(l_object_owner) - and c.object_name = upper(l_object_name) - and c.name = nvl(upper(l_procedure_name), c.name); - else - l_path := lower(ut_utils.qualified_sql_name(a_path)); - end if; - l_suite_item_name := case when l_tags.count > 0 then 'suite_items_tags' else 'suite_items' end; - - l_sql := gc_get_cache_suite_sql; - l_sql := replace(l_sql,'{:suite_item_name:}',l_suite_item_name); - l_sql := replace(l_sql,'{:object_owner:}',upper(l_object_owner)); - l_sql := replace(l_sql,'{:path:}',get_path_sql(l_path)); - l_sql := replace(l_sql,'{:object_name:}',get_object_name_sql(l_object_name)); - l_sql := replace(l_sql,'{:procedure_name:}',get_procedure_name_sql(l_procedure_name)); - l_sql := replace(l_sql,'{:tags:}',get_tags_sql(l_tags.count)); - l_sql := replace(l_sql,'{:random_seed:}',get_random_seed_sql(a_random_seed)); - - ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_key_anyvalues().put('l_sql',l_sql) ); - - execute immediate l_sql - bulk collect into l_results - using upper(l_object_owner), l_path, l_path, upper(a_object_name), upper(a_procedure_name), l_include_tags, l_include_tags, l_exclude_tags, a_random_seed; - return l_results; - end; - function expand_paths(a_schema_paths ut_path_items) return ut_path_items is l_schema_paths ut_path_items:= ut_path_items(); begin @@ -371,17 +188,9 @@ create or replace package body ut_suite_cache_manager is row_number() over ( partition by schema_name,object_name,procedure_name,suite_path order by 1) r_num from paths_to_expand) where r_num = 1 ; - - - return l_schema_paths; end; - - function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items is - begin - return expand_paths(group_paths_by_schema(a_paths)); - end; - + function get_suite_items ( a_schema_paths ut_path_items ) return ut_suite_cache_rows is @@ -451,6 +260,33 @@ create or replace package body ut_suite_cache_manager is return l_suite_tags; end; + /* + * Public code + */ + + function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items is + begin + return expand_paths(group_paths_by_schema(a_paths)); + end; + + function get_cached_suite_rows( + a_object_owner varchar2, + a_path varchar2 := null, + a_object_name varchar2 := null, + a_procedure_name varchar2 := null, + a_random_seed positive := null, + a_tags ut_varchar2_rows := null + ) return ut_suite_cache_rows is + l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); + l_object_owner varchar2(250) := ut_utils.qualified_sql_name(a_object_owner); + l_object_name varchar2(250) := ut_utils.qualified_sql_name(a_object_name); + l_procedure_name varchar2(250) := ut_utils.qualified_sql_name(a_procedure_name); + l_schema_paths ut_path_items; + begin + l_schema_paths := ut_path_items(ut_path_item(a_object_owner,a_object_name,a_procedure_name,a_path)); + return get_cached_suite_rows(l_schema_paths,a_random_seed,l_tags); + end; + function get_cached_suite_rows( a_schema_paths ut_path_items, a_random_seed positive := null, diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 45eec7c14..16beb0e36 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -299,51 +299,14 @@ create or replace package body ut_suite_manager is close a_suite_data_cursor; end reconstruct_from_cache; - - function get_cached_suite_data( - a_object_owner varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, - a_skip_all_objects boolean := false, - a_random_seed positive, - a_tags ut_varchar2_rows := null - ) return t_cached_suites_cursor is - l_unfiltered_rows ut_suite_cache_rows; - l_result t_cached_suites_cursor; - begin - l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_rows( - a_object_owner, - a_path, - a_object_name, - a_procedure_name, - a_random_seed, - a_tags - ); - if a_skip_all_objects then - open l_result for - select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c; - else - open l_result for - select /*+ no_parallel */ c.* from table(l_unfiltered_rows) c - where exists - ( select 1 - from all_objects a - where a.object_name = c.object_name - and a.owner = c.object_owner - and a.object_type = 'PACKAGE' - ) - or c.self_type = 'UT_LOGICAL_SUITE'; - end if; - - return l_result; - end; - - function get_filtered_cursor(a_unfiltered_rows in ut_suite_cache_rows) + function get_filtered_cursor( + a_unfiltered_rows in ut_suite_cache_rows, + a_skip_all_objects boolean := false + ) return ut_suite_cache_rows is l_result ut_suite_cache_rows := ut_suite_cache_rows(); begin - if ut_metadata.user_has_execute_any_proc() then + if ut_metadata.user_has_execute_any_proc() or a_skip_all_objects then l_result := a_unfiltered_rows; else for i in ( @@ -397,7 +360,8 @@ create or replace package body ut_suite_manager is function get_cached_suite_data( a_schema_paths ut_path_items, a_random_seed positive, - a_tags ut_varchar2_rows := null + a_tags ut_varchar2_rows := null, + a_skip_all_objects boolean := false ) return t_cached_suites_cursor is l_unfiltered_rows ut_suite_cache_rows; l_filtered_rows ut_suite_cache_rows; @@ -409,7 +373,7 @@ create or replace package body ut_suite_manager is a_tags ); - l_filtered_rows := get_filtered_cursor(l_unfiltered_rows); + l_filtered_rows := get_filtered_cursor(l_unfiltered_rows,a_skip_all_objects); reconcile_paths_and_suites(a_schema_paths,l_filtered_rows); open l_result for @@ -519,19 +483,17 @@ create or replace package body ut_suite_manager is a_skip_all_objects boolean := false ) return ut_suite_items is l_suites ut_suite_items := ut_suite_items(); + l_schema_paths ut_path_items; begin build_and_cache_suites(a_owner_name, a_annotated_objects); - + l_schema_paths := ut_path_items(ut_path_item(a_owner_name,a_object_name,a_procedure_name,a_path)); reconstruct_from_cache( l_suites, get_cached_suite_data( - a_owner_name, - a_path, - a_object_name, - a_procedure_name, - a_skip_all_objects, + l_schema_paths, null, - null + null, + a_skip_all_objects ) ); return l_suites; @@ -596,37 +558,6 @@ create or replace package body ut_suite_manager is a_tags ); - /* - l_schema := l_schema_paths.first; - while l_schema is not null loop - l_path_items := l_schema_paths(l_schema); - for i in 1 .. l_path_items.count loop - l_path_item := l_path_items(i); - add_suites_for_path( - upper(l_schema), - l_path_item.suite_path, - l_path_item.object_name, - l_path_item.procedure_name, - a_suites, - a_random_seed, - a_tags - ); - if a_suites.count = l_suites_count then - if l_path_item.suite_path is not null then - raise_application_error(ut_utils.gc_suite_package_not_found,'No suite packages found for path '||l_schema||':'||l_path_item.suite_path|| '.'); - elsif l_path_item.procedure_name is not null then - raise_application_error(ut_utils.gc_suite_package_not_found,'Suite test '||l_schema||'.'||l_path_item.object_name|| '.'||l_path_item.procedure_name||' does not exist'); - elsif l_path_item.object_name is not null then - raise_application_error(ut_utils.gc_suite_package_not_found,'Suite package '||l_schema||'.'||l_path_item.object_name|| ' does not exist'); - end if; - end if; - l_index := a_suites.first; - l_suites_count := a_suites.count; - end loop; - l_schema := l_schema_paths.next(l_schema); - end loop;*/ - - --propagate rollback type to suite items after organizing suites into hierarchy for i in 1 .. a_suites.count loop a_suites(i).set_rollback_type( a_suites(i).get_rollback_type() ); From 95ddec1e535aa720a4383affecdb7ac158cba91e Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 31 Mar 2022 11:53:03 +0100 Subject: [PATCH 046/187] Adding tests. modifying code to cater for path with wildcard that can result in large item duplication due to parent/child search. --- source/core/ut_suite_cache_manager.pkb | 65 +++++--- source/core/ut_suite_manager.pks | 1 - test/ut3_tester/core/test_suite_manager.pkb | 162 ++++++++++++++++++++ test/ut3_tester/core/test_suite_manager.pks | 22 ++- 4 files changed, 225 insertions(+), 25 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index b0b3f7d71..fe0aaabae 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -127,7 +127,6 @@ create or replace package body ut_suite_cache_manager is end; end; - --Possible move logic to type function group_paths_by_schema(a_paths ut_varchar2_list) return ut_path_items is c_package_path_regex constant varchar2(100) := '^([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_\*]+))?(\.([A-Za-z0-9$#_\*]+))?$'; l_results ut_path_items := ut_path_items(); @@ -152,34 +151,41 @@ create or replace package body ut_suite_cache_manager is function expand_paths(a_schema_paths ut_path_items) return ut_path_items is l_schema_paths ut_path_items:= ut_path_items(); - begin + begin with paths_to_expand as ( - select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(sp.object_name,c.object_name) as object_name, - sp.procedure_name as procedure_name + /* + The object name is populate but suitepath not + We will use that object and try to match. + We can pass also a wildcard this will result in one to many. + */ + select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(c.object_name,sp.object_name) as object_name, + nvl2(sp.procedure_name,c.name,null) as procedure_name from table(a_schema_paths) sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) and c.object_name like replace(upper(sp.object_name),'*','%') and c.name like nvl(replace(upper(sp.procedure_name),'*','%'), c.name)) - where sp.suite_path is null - and sp.object_name is not null - group by sp.schema_name,nvl(sp.object_name,c.object_name),sp.procedure_name + where sp.suite_path is null and sp.object_name is not null + group by sp.schema_name,nvl(c.object_name,sp.object_name),nvl2(sp.procedure_name,c.name,null) union all - select /*+ no_parallel */ c.path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name + select /*+ no_parallel */ nvl(c.path,sp.suite_path) as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name from table(a_schema_paths) sp left outer join ut_suite_cache c on - ( c.object_owner = upper(sp.schema_name) - and sp.suite_path is not null - and instr(sp.suite_path,'*') > 0) - where c.path like replace(sp.suite_path,'*','%') + ( c.object_owner = upper(sp.schema_name) + and c.path like replace(sp.suite_path,'*','%')) + where sp.suite_path is not null and instr(sp.suite_path,'*') > 0 union all + /* + Get all data that do not have an wildcard and not require expanding. + We will take them as they are. + a)suite path is populated + b)suite path and object is empty so schema name is by default ( or passed) + */ select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name from table(a_schema_paths) sp - where sp.suite_path is not null - and instr(sp.suite_path,'*') = 0 - union all - select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name - from table(a_schema_paths) sp - where sp.suite_path is null and sp.object_name is null + where + (sp.suite_path is not null and instr(sp.suite_path,'*') = 0) + or + (sp.suite_path is null and sp.object_name is null) ) select ut_path_item(schema_name,object_name,procedure_name,suite_path) bulk collect into l_schema_paths @@ -190,14 +196,25 @@ create or replace package body ut_suite_cache_manager is where r_num = 1 ; return l_schema_paths; end; - + + /* + Get a suite items rows that matching our criteria like + path,object_name etc. + We need to consider also an wildcard character on our procedures and object + names. + Were the path is populated we need to make sure we dont return duplicates + as the wildcard can produce multiple results from same path and + parents and child for each can be same resulting in duplicates + TODO: Verify that this not duplicate with a expand paths. + */ function get_suite_items ( a_schema_paths ut_path_items ) return ut_suite_cache_rows is l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); begin - select /*+ cardinality(c 500) */ value(c) as obj - bulk collect into l_suite_items + select obj bulk collect into l_suite_items + from ( + select /*+ cardinality(c 500) */ value(c) as obj,row_number() over ( partition by path order by path asc) r_num from ut_suite_cache c, table(a_schema_paths) sp where c.object_owner = upper(sp.schema_name) @@ -212,10 +229,14 @@ create or replace package body ut_suite_cache_manager is ( sp.suite_path is null and c.object_name like nvl(upper(replace(sp.object_name,'*','%')),c.object_name) and c.name like nvl(upper(replace(sp.procedure_name,'*','%')),c.name) - )); + ))) where r_num = 1; return l_suite_items; end; + /* + Having a base set of suites we will do a further filter down if there are + any tags defined. + */ function get_tags_suites ( a_suite_items ut_suite_cache_rows, a_tags ut_varchar2_rows diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index acc298516..5ae98d72a 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -20,7 +20,6 @@ create or replace package ut_suite_manager authid current_user is * Resposible for building hierarhy of sutes from individual suites created by suite_builder */ - /** * @private * diff --git a/test/ut3_tester/core/test_suite_manager.pkb b/test/ut3_tester/core/test_suite_manager.pkb index c8b4a9453..48ecf91f0 100644 --- a/test/ut3_tester/core/test_suite_manager.pkb +++ b/test/ut3_tester/core/test_suite_manager.pkb @@ -945,6 +945,26 @@ end;]'; ut.expect(sqlerrm).to_be_like('%failing_non_existing%'); end; + procedure test_search_nonex_pck_wild is + l_objects_to_run ut3_develop.ut_suite_items; + begin + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list('ut3_develop.failing_non_*')); + ut.fail('Non existing package did not raise exception'); + exception + when others then + ut.expect(sqlerrm).to_be_like('%failing_non_*%'); + end; + + procedure test_search_nonex_path_wild is + l_objects_to_run ut3_develop.ut_suite_items; + begin + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list('ut3_develop:failing_non_*')); + ut.fail('Non existing path did not raise exception'); + exception + when others then + ut.expect(sqlerrm).to_be_like('%:failing_non_*%'); + end; + procedure test_search_nonexist_sch_pck is l_objects_to_run ut3_develop.ut_suite_items; begin @@ -1560,5 +1580,147 @@ end;]'; end; + procedure test_wild_card_obj_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.test_package_*'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test2_suite ut3_develop.ut_logical_suite; + l_ctx_suite ut3_develop.ut_logical_suite; + l_test_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(3); + + + for i in 1 .. 3 loop + l_test_suite := treat(l_objects_to_run(i) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name in ('test_package_with_ctx','tests', 'tests2')).to_be_true; + + case l_test_suite.name + when 'test_package_with_ctx' then + ut.expect(l_test_suite.items.count).to_equal(1); + l_ctx_suite:= treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_ctx_suite.name).to_equal('some_context'); + ut.expect(l_ctx_suite.description).to_equal('Some context description'); + ut.expect(l_ctx_suite.items.count).to_equal(1); + l_test_proc := treat(l_ctx_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test_proc.name).to_equal('test1'); + when 'tests' then + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_1'); + ut.expect(l_test1_suite.items.count).to_equal(3); + ut.expect(l_test1_suite.rollback_type).to_equal(ut3_develop.ut_utils.gc_rollback_manual); + l_test2_suite := treat(l_test1_suite.items(1) as ut3_develop.ut_logical_suite); + + ut.expect(l_test2_suite.name).to_equal('test_package_2'); + ut.expect(l_test2_suite.items.count).to_equal(3); + ut.expect(l_test2_suite.rollback_type).to_equal(ut3_develop.ut_utils.gc_rollback_manual); + when 'tests2' then + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_3'); + ut.expect(l_test1_suite.items.count).to_equal(3); + end case; + + end loop; + + end; + + procedure test_wild_card_prc_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.test_package_1.test*'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('tests'); + + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_1'); + ut.expect(l_test1_suite.items.count).to_equal(2); + + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('test1'); + + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('test2'); + end; + + procedure test_wild_card_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':tests*'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test2_suite ut3_develop.ut_logical_suite; + l_test3_suite ut3_develop.ut_logical_suite; + l_ctx_suite ut3_develop.ut_logical_suite; + l_test_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(2); + + + for i in 1 .. 2 loop + l_test_suite := treat(l_objects_to_run(i) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name in ('tests', 'tests2')).to_be_true; + + case l_test_suite.name + when 'tests' then + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_1'); + ut.expect(l_test1_suite.items.count).to_equal(3); + + for i in 1 ..3 loop + --l_test2_suite := treat(l_test1_suite.items(i) as ut3_develop.ut_logical_suite); + --ut.expect(l_test2_suite.name).to_equal('test_package_2'); + --ut.expect(l_test2_suite.items.count).to_equal(3); + case l_test1_suite.items(i).self_type + when 'UT_SUITE' then + l_test2_suite := treat(l_test1_suite.items(i) as ut3_develop.ut_logical_suite); + ut.expect(l_test2_suite.name).to_equal('test_package_2'); + ut.expect(l_test2_suite.items.count).to_equal(3); + + l_test_proc := treat(l_test2_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2','context_test')).to_be_true; + + l_test_proc := treat(l_test2_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2','context_test')).to_be_true; + + l_test_proc := treat(l_test2_suite.items(3) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2','context_test')).to_be_true; + + when 'UT_TEST' then + l_test_proc := treat(l_test1_suite.items(i) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2')).to_be_true; + end case; + end loop; + when 'tests2' then + ut.expect(l_test_suite.items.count).to_equal(1); + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test_package_3'); + ut.expect(l_test1_suite.items.count).to_equal(3); + for i in 1 .. 3 loop + l_test_proc := treat(l_test1_suite.items(i) as ut3_develop.ut_test); + ut.expect(l_test_proc.name in ('test1', 'test2','disabled_test')).to_be_true; + end loop; + end case; + + end loop; + + end; + end test_suite_manager; / diff --git a/test/ut3_tester/core/test_suite_manager.pks b/test/ut3_tester/core/test_suite_manager.pks index 154df9ca6..bea8faf96 100644 --- a/test/ut3_tester/core/test_suite_manager.pks +++ b/test/ut3_tester/core/test_suite_manager.pks @@ -75,8 +75,14 @@ create or replace package test_suite_manager is --%test(Prepare runner for nonexisting package with schema) procedure test_search_nonexisting_pck; - - --%test(Prepare runner for nonexisting package without schema) + + --%test(Prepare runner for nonexisting package using wildcard filter) + procedure test_search_nonex_pck_wild; + + --%test(Prepare runner for nonexisting path using wildcard filter) + procedure test_search_nonex_path_wild; + + --%test(Prepare runner for nonexisting package without schema) procedure test_search_nonexist_sch_pck; --%test(Test description with comma) @@ -185,6 +191,18 @@ create or replace package test_suite_manager is --%aftertest(clean_remove_annot_test) procedure test_rem_cache_on_crt_anno; + --%context(wildcard_filters) + + --%test(Execute test_packages using a object_name with wildcard ) + procedure test_wild_card_obj_name; + + --%test(Execute test_packages using a procedure name with wildcard ) + procedure test_wild_card_prc_name; + + --%test(Execute test_packages using a path name with wildcard ) + procedure test_wild_card_path_name; + + --%endcontext end test_suite_manager; / From 83dbdaa4ba7ef57dcc8d86771cdb66d6eec19e7c Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 31 Mar 2022 15:40:28 +0100 Subject: [PATCH 047/187] Updating documentation. Adding get_suites_info override. --- docs/userguide/querying_suites.md | 10 +++++ docs/userguide/running-unit-tests.md | 28 +++++++++++++ source/api/ut_runner.pkb | 23 ++++++++++- source/api/ut_runner.pks | 9 ++++- source/core/ut_suite_cache_manager.pkb | 42 ++++++++++---------- source/core/ut_suite_cache_manager.pks | 9 +++-- source/core/ut_suite_manager.pkb | 55 ++++++++++++-------------- source/core/ut_suite_manager.pks | 10 ++--- 8 files changed, 122 insertions(+), 64 deletions(-) diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 2d947f391..b47b62083 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -39,6 +39,16 @@ To get a full information about suite `TEST_STUFF` including suite description, select * from table(ut_runner.get_suites_info(USER, 'TEST_STUFF')) where item_type = 'UT_TEST'; ``` +To get a full information about suites that have a path like `ut3:tests.test_package_*` including suite description, all contexts and tests in a suite +```sql +select * from table(ut_runner.get_suites_info('ut3:tests.test_package_*') where item_type = 'UT_TEST'; +``` + +To get a full information about suites that have object name like `test_package_*` including suite description, all contexts and tests in a suite +```sql +select * from table(ut_runner.get_suites_info('test_package_*')); +``` + ## Checking if schema contains tests Function `ut_runner.has_suites(a_owner)` returns boolean value indicating if given schema contains test suites. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index f392dd1e5..2a8f8e151 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -45,6 +45,10 @@ The **functions** can only be used in SELECT statements. They execute the specif ## ut.run procedures The examples below illustrate different ways and options to invoke `ut.run` procedures. +As part of the syntax you can use a wildcard character `*` to call test by part of his name or to call few tests that match a call. +Schema name is still mandatory and cannot contain a wildcard character whether is a suitepath or object. + + ```sql alter session set current_schema=hr; @@ -75,6 +79,14 @@ end; Executes all tests from all packages that are on the _com.my_org.my_project_ suitepath. Check the [annotations documentation](annotations.md) to find out about suitepaths and how they can be used to organize test packages for your project. +```sql +set serveroutput on +begin + ut.run('hr:com*'); +end; +``` + +Executes all tests from all packages that are on suitepath starting with _com_. ```sql set serveroutput on @@ -124,6 +136,22 @@ Using a list of items to execute allows you to execute a fine-grained set of tes List can be passed as a comma separated list or a list of *ut_varchar2_list objects* or as a list within ut_varchar2_list. +```sql +set serveroutput on +begin + ut.run('hr.test*'); +end; +``` +Executes all tests from schema _hr_ starting with name _test_. + +```sql +set serveroutput on +begin + ut.run('hr.test_apply_bonus.bonus_*'); +end; +``` +Executes all test procedures from package _hr.test_apply_bonus_ that starting with _bonus_. + **Note:** diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index cbf1971e7..c49f895a3 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -172,12 +172,31 @@ create or replace package body ut_runner is ut_annotation_manager.purge_cache(a_object_owner, a_object_type); end; - function get_suites_info(a_owner varchar2 := null, a_package_name varchar2 := null) return ut_suite_items_info pipelined is + function get_suites_info(a_owner varchar2, a_package_name varchar2) return ut_suite_items_info pipelined is l_cursor sys_refcursor; l_results ut_suite_items_info; c_bulk_limit constant integer := 100; + l_path varchar2(4000) := nvl(a_owner,sys_context('userenv', 'current_schema'))||'.'||nvl(a_package_name,'*'); begin - l_cursor := ut_suite_manager.get_suites_info( nvl(a_owner,sys_context('userenv', 'current_schema')), a_package_name ); + + l_cursor := ut_suite_manager.get_suites_info(ut_varchar2_list(l_path)); + loop + fetch l_cursor bulk collect into l_results limit c_bulk_limit; + for i in 1 .. l_results.count loop + pipe row (l_results(i)); + end loop; + exit when l_cursor%notfound; + end loop; + close l_cursor; + return; + end; + + function get_suites_info(a_path varchar2 := null) return ut_suite_items_info pipelined is + l_cursor sys_refcursor; + l_results ut_suite_items_info; + c_bulk_limit constant integer := 100; + begin + l_cursor := ut_suite_manager.get_suites_info(ut_varchar2_list(nvl(a_path,sys_context('userenv', 'current_schema')))); loop fetch l_cursor bulk collect into l_results limit c_bulk_limit; for i in 1 .. l_results.count loop diff --git a/source/api/ut_runner.pks b/source/api/ut_runner.pks index 3170dedee..e5afce691 100644 --- a/source/api/ut_runner.pks +++ b/source/api/ut_runner.pks @@ -104,7 +104,14 @@ create or replace package ut_runner authid current_user is * @param a_package_name name of unit test package to retrieve (optional), if NULL all unit test packages are returned * @return ut_suite_items_info table of objects */ - function get_suites_info(a_owner varchar2 := null, a_package_name varchar2 := null) return ut_suite_items_info pipelined; + function get_suites_info(a_owner varchar2, a_package_name varchar2) return ut_suite_items_info pipelined; + + /** + * Returns a pipelined collection containing information about unit test suites and the tests contained in them + * + * @param a_path a path from which we lookg for object or suite + */ + function get_suites_info(a_path varchar2 := null) return ut_suite_items_info pipelined; /** diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index fe0aaabae..95615e2d5 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -148,16 +148,20 @@ create or replace package body ut_suite_cache_manager is return l_results; end; - + /* + The object name is populate but suitepath not + We will use that object and try to match. + We can pass also a wildcard this will result in one to many. + + Get all data that do not have an wildcard and not require expanding. + We will take them as they are. + a)suite path is populated + b)suite path and object is empty so schema name is by default ( or passed) + */ function expand_paths(a_schema_paths ut_path_items) return ut_path_items is l_schema_paths ut_path_items:= ut_path_items(); begin - with paths_to_expand as ( - /* - The object name is populate but suitepath not - We will use that object and try to match. - We can pass also a wildcard this will result in one to many. - */ + with paths_to_expand as ( select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(c.object_name,sp.object_name) as object_name, nvl2(sp.procedure_name,c.name,null) as procedure_name from table(a_schema_paths) sp left outer join ut_suite_cache c @@ -174,12 +178,6 @@ create or replace package body ut_suite_cache_manager is and c.path like replace(sp.suite_path,'*','%')) where sp.suite_path is not null and instr(sp.suite_path,'*') > 0 union all - /* - Get all data that do not have an wildcard and not require expanding. - We will take them as they are. - a)suite path is populated - b)suite path and object is empty so schema name is by default ( or passed) - */ select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name from table(a_schema_paths) sp where @@ -205,7 +203,6 @@ create or replace package body ut_suite_cache_manager is Were the path is populated we need to make sure we dont return duplicates as the wildcard can produce multiple results from same path and parents and child for each can be same resulting in duplicates - TODO: Verify that this not duplicate with a expand paths. */ function get_suite_items ( a_schema_paths ut_path_items @@ -484,22 +481,25 @@ create or replace package body ut_suite_cache_manager is end; function get_cached_suite_info( - a_object_owner varchar2, - a_object_name varchar2 + a_schema_paths ut_path_items + ) return ut_suite_cache_rows is + begin + return get_cached_suite_rows( a_schema_paths ); + end; + + function get_suite_items_info( + a_suite_cache_items ut_suite_cache_rows ) return ut_suite_items_info is - l_cache_rows ut_suite_cache_rows; l_results ut_suite_items_info; begin - l_cache_rows := get_cached_suite_rows( a_object_owner => a_object_owner, a_object_name =>a_object_name ); select /*+ no_parallel */ ut_suite_item_info( c.object_owner, c.object_name, c.name, c.description, c.self_type, c.line_no, c.path, c.disabled_flag, c.disabled_reason, c.tags ) bulk collect into l_results - from table(l_cache_rows) c; - - return l_results; + from table(a_suite_cache_items) c; + return l_results; end; function get_cached_packages( diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 3e2ac6451..05bff7af9 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -68,10 +68,13 @@ create or replace package ut_suite_cache_manager authid definer is * Not to be used publicly. Used internally for building suites info. */ function get_cached_suite_info( - a_object_owner varchar2, - a_object_name varchar2 + a_schema_paths ut_path_items + ) return ut_suite_cache_rows; + + function get_suite_items_info( + a_suite_cache_items ut_suite_cache_rows ) return ut_suite_items_info; - + /* * Retrieves list of cached suite packages. * Returned data is not filtered by user access rights. diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 16beb0e36..cab24e607 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -533,8 +533,6 @@ create or replace package body ut_suite_manager is l_schema_paths ut_path_items; l_reconcile_paths ut_path_items; l_schema varchar2(4000); - l_suites_count pls_integer := 0; - l_index varchar2(4000 char); begin ut_event_manager.trigger_event('configure_execution_by_path - start'); a_suites := ut_suite_items(); @@ -567,37 +565,34 @@ create or replace package body ut_suite_manager is end configure_execution_by_path; function get_suites_info( - a_owner_name varchar2, - a_package_name varchar2 := null + a_paths ut_varchar2_list ) return sys_refcursor is - l_result sys_refcursor; - l_all_suite_info ut_suite_items_info; - l_owner_name varchar2(250) := ut_utils.qualified_sql_name(a_owner_name); - l_package_name varchar2(250) := ut_utils.qualified_sql_name(a_package_name); + l_result sys_refcursor; + l_all_suite_info ut_suite_items_info; + l_schema_names ut_varchar2_rows; + l_schema_paths ut_path_items; + l_paths ut_varchar2_list := a_paths; + l_schema varchar2(4000); + l_unfiltered_rows ut_suite_cache_rows; + l_filtered_rows ut_suite_cache_rows; + begin + l_schema_names := resolve_schema_names(l_paths); + --refresh cache + l_schema := l_schema_names.first; + while l_schema is not null loop + refresh_cache(upper(l_schema_names(l_schema))); + l_schema := l_schema_names.next(l_schema); + end loop; + l_schema_paths := ut_suite_cache_manager.get_schema_paths(l_paths); + l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_info(l_schema_paths); + l_filtered_rows := get_filtered_cursor(l_unfiltered_rows); + l_all_suite_info := ut_suite_cache_manager.get_suite_items_info(l_filtered_rows); + open l_result for + select /*+ no_parallel */ value(c) + from table(l_all_suite_info) c + order by c.object_owner, c.object_name, c.item_line_no; - refresh_cache(l_owner_name); - - l_all_suite_info := ut_suite_cache_manager.get_cached_suite_info( l_owner_name, l_package_name ); - if can_skip_all_objects_scan( l_owner_name ) then - open l_result for - select /*+ no_parallel */ value(c) - from table(l_all_suite_info) c - order by c.object_owner, c.object_name, c.item_line_no; - else - open l_result for - select /*+ no_parallel */ value(c) - from table(l_all_suite_info) c - where exists - ( select 1 - from all_objects a - where a.object_name = c.object_name - and a.owner = c.object_owner - and a.object_type = 'PACKAGE' - ) - or c.item_type = 'UT_LOGICAL_SUITE' - order by c.object_owner, c.object_name, c.item_line_no; - end if; return l_result; end; diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index 5ae98d72a..6c96500b3 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -79,15 +79,11 @@ create or replace package ut_suite_manager authid current_user is /** * Returns a ref cursor containing information about unit test suites and the tests contained in them * - * @param a_owner owner of unit tests to retrieve - * @param a_package_name name of test package (optional) - * @param a_procedure_name name of test procedure (optional) - * @return ut_suite_items_info table of objects + * @param a_paths list of paths to be resolved and return a suites. */ function get_suites_info( - a_owner_name varchar2, - a_package_name varchar2 := null - ) return sys_refcursor; + a_paths ut_varchar2_list + ) return sys_refcursor; /** * Returns true if given suite item exists From 52c0307bbb5d9c7de5d3a6bc334558377f424f4e Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 1 Apr 2022 00:33:09 +0100 Subject: [PATCH 048/187] Addresing sonar issues --- source/api/ut_runner.pkb | 5 ++++- source/core/ut_suite_cache_manager.pkb | 17 ++++++++--------- source/core/ut_suite_manager.pkb | 6 +----- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index c49f895a3..b05e93056 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -195,12 +195,15 @@ create or replace package body ut_runner is l_cursor sys_refcursor; l_results ut_suite_items_info; c_bulk_limit constant integer := 100; + i pls_integer; begin l_cursor := ut_suite_manager.get_suites_info(ut_varchar2_list(nvl(a_path,sys_context('userenv', 'current_schema')))); loop fetch l_cursor bulk collect into l_results limit c_bulk_limit; - for i in 1 .. l_results.count loop + i := l_results.first; + while (i is not null) loop pipe row (l_results(i)); + i := l_results.next(i); end loop; exit when l_cursor%notfound; end loop; diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 95615e2d5..ba4510e62 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -131,8 +131,10 @@ create or replace package body ut_suite_cache_manager is c_package_path_regex constant varchar2(100) := '^([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_\*]+))?(\.([A-Za-z0-9$#_\*]+))?$'; l_results ut_path_items := ut_path_items(); l_path_item ut_path_item; + i pls_integer; begin - for i in 1 .. a_paths.count loop + i := a_paths.first; + while (i is not null) loop l_results.extend; if a_paths(i) like '%:%' then l_path_item := ut_path_item(schema_name => upper(regexp_substr(a_paths(i),'^[^.:]+')), @@ -143,7 +145,8 @@ create or replace package body ut_suite_cache_manager is object_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 3), procedure_name => regexp_substr(a_paths(i), c_package_path_regex, subexpression => 5)); l_results(l_results.last) := l_path_item; - end if; + end if; + i := a_paths.next(i); end loop; return l_results; @@ -189,7 +192,7 @@ create or replace package body ut_suite_cache_manager is bulk collect into l_schema_paths from (select schema_name,object_name,procedure_name,suite_path, - row_number() over ( partition by schema_name,object_name,procedure_name,suite_path order by 1) r_num + row_number() over ( partition by schema_name,object_name,procedure_name,suite_path order by 1) as r_num from paths_to_expand) where r_num = 1 ; return l_schema_paths; @@ -211,7 +214,7 @@ create or replace package body ut_suite_cache_manager is begin select obj bulk collect into l_suite_items from ( - select /*+ cardinality(c 500) */ value(c) as obj,row_number() over ( partition by path order by path asc) r_num + select /*+ cardinality(c 500) */ value(c) as obj,row_number() over ( partition by path order by path asc) as r_num from ut_suite_cache c, table(a_schema_paths) sp where c.object_owner = upper(sp.schema_name) @@ -301,7 +304,7 @@ create or replace package body ut_suite_cache_manager is l_procedure_name varchar2(250) := ut_utils.qualified_sql_name(a_procedure_name); l_schema_paths ut_path_items; begin - l_schema_paths := ut_path_items(ut_path_item(a_object_owner,a_object_name,a_procedure_name,a_path)); + l_schema_paths := ut_path_items(ut_path_item(l_object_owner,l_object_name,l_procedure_name,a_path)); return get_cached_suite_rows(l_schema_paths,a_random_seed,l_tags); end; @@ -314,10 +317,6 @@ create or replace package body ut_suite_cache_manager is l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); l_schema_paths ut_path_items; l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); - - l_suite_item_name varchar2(20); - l_paths ut_varchar2_rows; - l_schema varchar2(4000); l_sql varchar2(32767); begin diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index cab24e607..43df7f255 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -82,12 +82,9 @@ create or replace package body ut_suite_manager is l_schema := sys.dbms_assert.schema_name(upper(l_object)); exception when sys.dbms_assert.invalid_schema_name then - if l_object like '%*%' then + if l_object like '%*%' or ut_metadata.package_exists_in_cur_schema(upper(l_object)) then a_paths(i) := c_current_schema || '.' || a_paths(i); l_schema := c_current_schema; - elsif ut_metadata.package_exists_in_cur_schema(upper(l_object)) then - a_paths(i) := c_current_schema || '.' || a_paths(i); - l_schema := c_current_schema; else raise; end if; @@ -531,7 +528,6 @@ create or replace package body ut_suite_manager is l_paths ut_varchar2_list := a_paths; l_schema_names ut_varchar2_rows; l_schema_paths ut_path_items; - l_reconcile_paths ut_path_items; l_schema varchar2(4000); begin ut_event_manager.trigger_event('configure_execution_by_path - start'); From 8f8d257fc9de8f71eb6ed83bb62194f9fadef359 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 1 Apr 2022 01:02:39 +0100 Subject: [PATCH 049/187] Extra tests and cleanup of old code. --- source/core/ut_suite_cache_manager.pkb | 18 --------------- source/core/ut_suite_cache_manager.pks | 11 +-------- test/ut3_user/api/test_ut_runner.pkb | 32 ++++++++++++++++++++++++++ test/ut3_user/api/test_ut_runner.pks | 5 ++++ 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index ba4510e62..c045310c0 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -290,24 +290,6 @@ create or replace package body ut_suite_cache_manager is return expand_paths(group_paths_by_schema(a_paths)); end; - function get_cached_suite_rows( - a_object_owner varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, - a_random_seed positive := null, - a_tags ut_varchar2_rows := null - ) return ut_suite_cache_rows is - l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); - l_object_owner varchar2(250) := ut_utils.qualified_sql_name(a_object_owner); - l_object_name varchar2(250) := ut_utils.qualified_sql_name(a_object_name); - l_procedure_name varchar2(250) := ut_utils.qualified_sql_name(a_procedure_name); - l_schema_paths ut_path_items; - begin - l_schema_paths := ut_path_items(ut_path_item(l_object_owner,l_object_name,l_procedure_name,a_path)); - return get_cached_suite_rows(l_schema_paths,a_random_seed,l_tags); - end; - function get_cached_suite_rows( a_schema_paths ut_path_items, a_random_seed positive := null, diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 05bff7af9..6b12e7439 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -46,22 +46,13 @@ create or replace package ut_suite_cache_manager authid definer is * Not to be used publicly. Used internally for building suites at runtime. */ function get_cached_suite_rows( - a_object_owner varchar2, - a_path varchar2 := null, - a_object_name varchar2 := null, - a_procedure_name varchar2 := null, + a_schema_paths ut_path_items, a_random_seed positive := null, a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows; function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items; - function get_cached_suite_rows( - a_schema_paths ut_path_items, - a_random_seed positive := null, - a_tags ut_varchar2_rows := null - ) return ut_suite_cache_rows; - /* * Retrieves suite item info rows from cache. * Returned data is not filtered by user access rights. diff --git a/test/ut3_user/api/test_ut_runner.pkb b/test/ut3_user/api/test_ut_runner.pkb index 80b1cd60b..b6b7c67e7 100644 --- a/test/ut3_user/api/test_ut_runner.pkb +++ b/test/ut3_user/api/test_ut_runner.pkb @@ -344,6 +344,38 @@ end;'; ut.expect(l_actual).to_equal(l_expected); end; + procedure test_get_suites_info_by_path is + l_expected sys_refcursor; + l_actual sys_refcursor; + begin + --Arrange + open l_expected for + select + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'DUMMY_TEST_PACKAGE' item_name, + 'dummy_test_suite' item_description, 'UT_SUITE' item_type, 2 item_line_no, + 'some.path.dummy_test_package' path, 0 disabled_flag, null disabled_reason,null tags + from dual union all + select + 'UT3_USER' object_owner, 'DUMMY_TEST_PACKAGE' object_name, 'SOME_DUMMY_TEST_PROCEDURE' item_name, + 'dummy_test' item_description, 'UT_TEST' item_type, 6 item_line_no, + 'some.path.dummy_test_package.some_dummy_test_procedure' path, 0 disabled_flag, null disabled_reason,null tags + from dual union all + select + 'UT3_USER' object_owner, 'PATH' object_name, 'PATH' item_name, + null item_description, 'UT_LOGICAL_SUITE' item_type, null item_line_no, + 'some.path' path, 0 disabled_flag, null disabled_reason, null tags + from dual union all + select + 'UT3_USER' object_owner, 'SOME' object_name, 'SOME' item_name, + null item_description, 'UT_LOGICAL_SUITE' item_type, null item_line_no, + 'some' path, 0 disabled_flag, null disabled_reason, null tags + from dual; + --Act + open l_actual for select * from table(ut3_develop.ut_runner.get_suites_info('ut3_user:some.path.dummy_test_package')); + --Assert + ut.expect(l_actual).to_equal(l_expected); + end; + procedure test_get_reporters_list is l_expected sys_refcursor; l_actual sys_refcursor; diff --git a/test/ut3_user/api/test_ut_runner.pks b/test/ut3_user/api/test_ut_runner.pks index 08282e997..e003ba852 100644 --- a/test/ut3_user/api/test_ut_runner.pks +++ b/test/ut3_user/api/test_ut_runner.pks @@ -65,6 +65,11 @@ create or replace package test_ut_runner is --%aftertest(cleanup_cache) procedure test_get_suites_info_twotag; + --%test(get_suites_info returns a cursor containing records for a newly created test with passed path) + --%beforetest(setup_cache_objects) + --%aftertest(cleanup_cache) + procedure test_get_suites_info_by_path; + --%test(get_reporters_list returns a cursor containing all built-in reporters and information about output-reporter) --%beforetest(setup_cache_objects) --%aftertest(cleanup_cache) From 12be1234bdff3e0abd5b48e237a68519d5466b99 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 1 Apr 2022 07:39:34 +0100 Subject: [PATCH 050/187] Adding extra tests --- test/ut3_tester/core/test_suite_manager.pkb | 10 ++++++++++ test/ut3_tester/core/test_suite_manager.pks | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/test/ut3_tester/core/test_suite_manager.pkb b/test/ut3_tester/core/test_suite_manager.pkb index 48ecf91f0..5baf5779d 100644 --- a/test/ut3_tester/core/test_suite_manager.pkb +++ b/test/ut3_tester/core/test_suite_manager.pkb @@ -955,6 +955,16 @@ end;]'; ut.expect(sqlerrm).to_be_like('%failing_non_*%'); end; + procedure test_search_nonex_prc_wild is + l_objects_to_run ut3_develop.ut_suite_items; + begin + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list('ut3_develop.test_package_1.nonexist*')); + ut.fail('Non existing package did not raise exception'); + exception + when others then + ut.expect(sqlerrm).to_be_like('%failing_non_*%'); + end; + procedure test_search_nonex_path_wild is l_objects_to_run ut3_develop.ut_suite_items; begin diff --git a/test/ut3_tester/core/test_suite_manager.pks b/test/ut3_tester/core/test_suite_manager.pks index bea8faf96..ccd4d586c 100644 --- a/test/ut3_tester/core/test_suite_manager.pks +++ b/test/ut3_tester/core/test_suite_manager.pks @@ -78,7 +78,10 @@ create or replace package test_suite_manager is --%test(Prepare runner for nonexisting package using wildcard filter) procedure test_search_nonex_pck_wild; - + + --%test(Prepare runner for nonexisting procedure using wildcard filter) + procedure test_search_nonex_prc_wild; + --%test(Prepare runner for nonexisting path using wildcard filter) procedure test_search_nonex_path_wild; From d5ee6cad38b05e94e58e3811ba0917ca3d8f6d2c Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 1 Apr 2022 11:19:11 +0100 Subject: [PATCH 051/187] Updating SQL to expand paths and extract suites. --- source/core/ut_suite_cache_manager.pkb | 50 +++++++++++++-------- test/ut3_tester/core/test_suite_manager.pkb | 4 +- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index c045310c0..7bd8e3423 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -151,28 +151,41 @@ create or replace package body ut_suite_cache_manager is return l_results; end; + /* - The object name is populate but suitepath not - We will use that object and try to match. - We can pass also a wildcard this will result in one to many. + First SQL queries for objects where procedure is null or its only wildcard. + We split that due to fact that we can use func min to combine rows. + + Second union is responsible expanding paths where the procedure filter is given + We cannot select min here as filter can cover only half of tests within + package. Even if the filter doesnt return anything we still capture a proc filter + name for error reporting later on. - Get all data that do not have an wildcard and not require expanding. - We will take them as they are. - a)suite path is populated - b)suite path and object is empty so schema name is by default ( or passed) + Third SQL cover scenario where a suitapath only is populated and wildcard is given + + Fourth SQL cover scenario where suitepath is populated with no filters */ function expand_paths(a_schema_paths ut_path_items) return ut_path_items is l_schema_paths ut_path_items:= ut_path_items(); begin with paths_to_expand as ( select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(c.object_name,sp.object_name) as object_name, - nvl2(sp.procedure_name,c.name,null) as procedure_name + null as procedure_name + from table(a_schema_paths) sp left outer join ut_suite_cache c + on ( c.object_owner = upper(sp.schema_name) + and c.object_name like replace(upper(sp.object_name),'*','%')) + where sp.suite_path is null and sp.object_name is not null + and ( sp.procedure_name is null or sp.procedure_name = '*') + group by sp.schema_name,nvl(c.object_name,sp.object_name) + union all + select /*+ no_parallel */ path as suite_path,sp.schema_name as schema_name,nvl(c.object_name,sp.object_name) as object_name, + nvl(c.name,sp.procedure_name) as procedure_name from table(a_schema_paths) sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) and c.object_name like replace(upper(sp.object_name),'*','%') and c.name like nvl(replace(upper(sp.procedure_name),'*','%'), c.name)) where sp.suite_path is null and sp.object_name is not null - group by sp.schema_name,nvl(c.object_name,sp.object_name),nvl2(sp.procedure_name,c.name,null) + and (sp.procedure_name is not null and sp.procedure_name != '*') union all select /*+ no_parallel */ nvl(c.path,sp.suite_path) as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name from @@ -218,18 +231,17 @@ create or replace package body ut_suite_cache_manager is from ut_suite_cache c, table(a_schema_paths) sp where c.object_owner = upper(sp.schema_name) - and ( - (sp.suite_path is not null and - sp.suite_path||'.' like c.path||'.%' /*all parents and self*/ - or - ( c.path||'.' like sp.suite_path||'.%' /*all children and self*/ - and c.object_name like nvl(upper(sp.object_name),c.object_name) - and c.name like nvl(upper(sp.procedure_name),c.name) ) ) + and ((sp.suite_path is not null and sp.suite_path||'.' like c.path||'.%' /*all parents and self*/ + or + ( + c.path||'.' like sp.suite_path||'.%' /*all children and self*/ + and c.object_name like nvl(upper(sp.object_name),c.object_name) + and c.name like nvl(upper(sp.procedure_name),c.name) + )) or ( sp.suite_path is null - and c.object_name like nvl(upper(replace(sp.object_name,'*','%')),c.object_name) - and c.name like nvl(upper(replace(sp.procedure_name,'*','%')),c.name) - ))) where r_num = 1; + and c.object_name = nvl(upper(sp.object_name),c.object_name) + and c.name = nvl(upper(sp.procedure_name),c.name)))) where r_num =1; return l_suite_items; end; diff --git a/test/ut3_tester/core/test_suite_manager.pkb b/test/ut3_tester/core/test_suite_manager.pkb index 5baf5779d..684cc14fe 100644 --- a/test/ut3_tester/core/test_suite_manager.pkb +++ b/test/ut3_tester/core/test_suite_manager.pkb @@ -958,11 +958,11 @@ end;]'; procedure test_search_nonex_prc_wild is l_objects_to_run ut3_develop.ut_suite_items; begin - l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list('ut3_develop.test_package_1.nonexist*')); + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list('ut3_tester.test_package_1.nonexist*')); ut.fail('Non existing package did not raise exception'); exception when others then - ut.expect(sqlerrm).to_be_like('%failing_non_*%'); + ut.expect(sqlerrm).to_be_like('%nonexist*%'); end; procedure test_search_nonex_path_wild is From 2db8d635765b2c8e0d4d891a28bfce4d3d3f10ca Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 7 Apr 2022 00:24:16 +0100 Subject: [PATCH 052/187] Addressing issue with reconstruct_cache knocking off other levels. Solution was to introduce a sort order that work from bottom to top. --- source/core/ut_suite_cache_manager.pkb | 54 +++++++++++++++++++++----- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 7bd8e3423..8777910b9 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -64,15 +64,10 @@ create or replace package body ut_suite_cache_manager is s.y, null, s.z ) as obj from logical_suite_data s - ), - items as ( - select obj from suite_items - union all - select obj from logical_suites ) - select /*+ no_parallel */ c.obj - from items c - order by c.obj.object_owner,{:random_seed:}]'; + select /*+ no_parallel */obj from suite_items + union all + select /*+ no_parallel */ obj from logical_suites]'; function get_missing_cache_objects(a_object_owner varchar2) return ut_varchar2_rows is l_result ut_varchar2_rows; @@ -293,6 +288,43 @@ create or replace package body ut_suite_cache_manager is return l_suite_tags; end; + /* + We will sort a suites in hierarchical structure. + Sorting from bottom to top so when we consolidate + we will go in proper order. + For random seed we will add an extra sort that can be null + */ + procedure sort_and_randomize_tests( + a_suite_rows in out ut_suite_cache_rows, + a_random_seed positive := null) + is + l_suite_rows ut_suite_cache_rows; + begin + with + extract_parent_child as ( + select s.path, substr(s.path,1,instr(s.path,'.',-1,1)-1) as parent_path,s.object_owner,s.line_no,a_random_seed random_seed + from table(a_suite_rows) s), + t1(path,parent_path,object_owner,line_no,random_seed) as ( + --Anchor memeber + select s.path, parent_path,s.object_owner,s.line_no,random_seed + from extract_parent_child s + where parent_path is null + union all + --Recursive member + select t2.path, t2.parent_path,t2.object_owner,t2.line_no,t2.random_seed + from t1,extract_parent_child t2 + where t2.parent_path = t1.path + and t1.object_owner = t2.object_owner) + search depth first by line_no desc,random_seed set order1 + select value(i) as obj + bulk collect into l_suite_rows + from t1 c + join table(a_suite_rows) i on i.object_owner = c.object_owner and i.path = c.path + order by order1 desc; + + a_suite_rows := l_suite_rows; + end; + /* * Public code */ @@ -308,6 +340,7 @@ create or replace package body ut_suite_cache_manager is a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows is l_results ut_suite_cache_rows := ut_suite_cache_rows(); + l_results2 ut_suite_cache_rows := ut_suite_cache_rows(); l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); l_schema_paths ut_path_items; l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); @@ -316,7 +349,6 @@ create or replace package body ut_suite_cache_manager is l_schema_paths := a_schema_paths; l_sql := gc_get_bulk_cache_suite_sql; - l_sql := replace(l_sql,'{:random_seed:}',get_random_seed_sql(a_random_seed)); l_suite_items := get_suite_items(a_schema_paths); if l_tags.count > 0 then l_suite_items := get_tags_suites(l_suite_items,l_tags); @@ -325,7 +357,9 @@ create or replace package body ut_suite_cache_manager is execute immediate l_sql bulk collect into l_results - using l_suite_items, a_random_seed; + using l_suite_items; + + sort_and_randomize_tests(l_results,a_random_seed); return l_results; end; From d3396fef1fce55d8e25828e99aa2556ad3e336e5 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 7 Apr 2022 11:27:59 +0100 Subject: [PATCH 053/187] Update tests for random order --- source/core/ut_suite_cache_manager.pkb | 40 +++----------------------- test/ut3_user/api/test_ut_run.pkb | 2 +- 2 files changed, 5 insertions(+), 37 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 8777910b9..c76260212 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -88,40 +88,6 @@ create or replace package body ut_suite_cache_manager is return l_result; end; - function get_random_seed_sql(a_random_seed positive) return varchar2 is - begin - return case - when a_random_seed is null then q'[ - nlssort( - replace( - /*suite path until objects name (excluding contexts and test path) with trailing dot (full stop)*/ - substr( c.obj.path, 1, instr( c.obj.path, lower(c.obj.object_name), -1 ) + length(c.obj.object_name) ), - '.', - /*'.' replaced with chr(0) to assure that child elements come before parent when sorting in descending order*/ - chr(0) - ), - 'nls_sort=binary' - )desc nulls last, - case when c.obj.self_type = 'UT_SUITE_CONTEXT' then - ( select /*+ no_parallel */ max( x.line_no ) + 1 - from ut_suite_cache x - where c.obj.object_owner = x.object_owner - and c.obj.object_name = x.object_name - and x.path like c.obj.path || '.%' - ) - else - c.obj.line_no - end, - /*assures that child contexts come before parent contexts*/ - regexp_count(c.obj.path,'\.') desc, - :a_random_seed]' - else - ' ut_runner.hash_suite_path( - c.obj.path, :a_random_seed - ) desc nulls last' - end; - end; - function group_paths_by_schema(a_paths ut_varchar2_list) return ut_path_items is c_package_path_regex constant varchar2(100) := '^([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_\*]+))?(\.([A-Za-z0-9$#_\*]+))?$'; l_results ut_path_items := ut_path_items(); @@ -302,7 +268,9 @@ create or replace package body ut_suite_cache_manager is begin with extract_parent_child as ( - select s.path, substr(s.path,1,instr(s.path,'.',-1,1)-1) as parent_path,s.object_owner,s.line_no,a_random_seed random_seed + select s.path, substr(s.path,1,instr(s.path,'.',-1,1)-1) as parent_path,s.object_owner, + case when a_random_seed is null then s.line_no else null end line_no, + case when a_random_seed is null then null else ut_runner.hash_suite_path(s.path, a_random_seed) end random_seed from table(a_suite_rows) s), t1(path,parent_path,object_owner,line_no,random_seed) as ( --Anchor memeber @@ -315,7 +283,7 @@ create or replace package body ut_suite_cache_manager is from t1,extract_parent_child t2 where t2.parent_path = t1.path and t1.object_owner = t2.object_owner) - search depth first by line_no desc,random_seed set order1 + search depth first by line_no desc,random_seed desc nulls last set order1 select value(i) as obj bulk collect into l_suite_rows from t1 c diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 492efcba2..41b969359 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -854,7 +854,7 @@ Failures:% l_results ut3_develop.ut_varchar2_list; begin select * bulk collect into l_random_results - from table ( ut3_develop.ut.run( 'ut3_tester_helper.test_package_1', a_random_test_order_seed => 3 ) ) + from table ( ut3_develop.ut.run( 'ut3_tester_helper.test_package_1', a_random_test_order_seed => 6 ) ) where trim(column_value) is not null and column_value not like 'Finished in %' and column_value not like '%Tests were executed with random order %'; From 02d41a64b391781b911bca572f0f835bc1cee929 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 7 Apr 2022 11:39:03 +0100 Subject: [PATCH 054/187] Removing a hash function from api into utils package which is more suited for it. --- source/api/ut_runner.pkb | 31 -------------------------- source/api/ut_runner.pks | 5 ----- source/core/ut_suite_cache_manager.pkb | 2 +- source/core/ut_utils.pkb | 31 ++++++++++++++++++++++++++ source/core/ut_utils.pks | 5 +++++ 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index b05e93056..b69a51a04 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -265,37 +265,6 @@ create or replace package body ut_runner is end loop; end; - function hash_suite_path(a_path varchar2, a_random_seed positiven) return varchar2 is - l_start_pos pls_integer := 1; - l_end_pos pls_integer := 1; - l_result varchar2(4000); - l_item varchar2(4000); - l_at_end boolean := false; - begin - if a_random_seed is null then - l_result := a_path; - end if; - if a_path is not null then - loop - l_end_pos := instr(a_path,'.',l_start_pos); - if l_end_pos = 0 then - l_end_pos := length(a_path)+1; - l_at_end := true; - end if; - l_item := substr(a_path,l_start_pos,l_end_pos-l_start_pos); - if l_item is not null then - l_result := - l_result || - ut_utils.get_hash( to_char( dbms_utility.get_hash_value( l_item, 1, a_random_seed ) ) ); - end if; - exit when l_at_end; - l_result := l_result || chr(0); - l_start_pos := l_end_pos + 1; - end loop; - end if; - return l_result; - end; - procedure coverage_start(a_coverage_run_id raw) is begin ut_coverage.coverage_start(a_coverage_run_id); diff --git a/source/api/ut_runner.pks b/source/api/ut_runner.pks index e5afce691..85eff1c93 100644 --- a/source/api/ut_runner.pks +++ b/source/api/ut_runner.pks @@ -151,11 +151,6 @@ create or replace package ut_runner authid current_user is */ function get_reporters_list return tt_reporters_info pipelined; - /* - * Returns a hash value of suitepath based on input path and random seed - */ - function hash_suite_path(a_path varchar2, a_random_seed positiven) return varchar2; - procedure coverage_start(a_coverage_run_id raw); procedure coverage_stop; diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index c76260212..d76a6412e 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -270,7 +270,7 @@ create or replace package body ut_suite_cache_manager is extract_parent_child as ( select s.path, substr(s.path,1,instr(s.path,'.',-1,1)-1) as parent_path,s.object_owner, case when a_random_seed is null then s.line_no else null end line_no, - case when a_random_seed is null then null else ut_runner.hash_suite_path(s.path, a_random_seed) end random_seed + case when a_random_seed is null then null else ut_utils.hash_suite_path(s.path, a_random_seed) end random_seed from table(a_suite_rows) s), t1(path,parent_path,object_owner,line_no,random_seed) as ( --Anchor memeber diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 3675e834d..10d9d2393 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -892,6 +892,37 @@ create or replace package body ut_utils is return case when a_data is null then null else dbms_crypto.hash(a_data, a_hash_type) end; end; + function hash_suite_path(a_path varchar2, a_random_seed positiven) return varchar2 is + l_start_pos pls_integer := 1; + l_end_pos pls_integer := 1; + l_result varchar2(4000); + l_item varchar2(4000); + l_at_end boolean := false; + begin + if a_random_seed is null then + l_result := a_path; + end if; + if a_path is not null then + loop + l_end_pos := instr(a_path,'.',l_start_pos); + if l_end_pos = 0 then + l_end_pos := length(a_path)+1; + l_at_end := true; + end if; + l_item := substr(a_path,l_start_pos,l_end_pos-l_start_pos); + if l_item is not null then + l_result := + l_result || + ut_utils.get_hash( to_char( dbms_utility.get_hash_value( l_item, 1, a_random_seed ) ) ); + end if; + exit when l_at_end; + l_result := l_result || chr(0); + l_start_pos := l_end_pos + 1; + end loop; + end if; + return l_result; + end; + function qualified_sql_name(a_name varchar2) return varchar2 is begin return diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index aeff16dd8..e5f48eb95 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -452,6 +452,11 @@ create or replace package ut_utils authid definer is */ function get_hash(a_data clob, a_hash_type binary_integer := dbms_crypto.hash_sh1) return t_hash; + /* + * Returns a hash value of suitepath based on input path and random seed + */ + function hash_suite_path(a_path varchar2, a_random_seed positiven) return varchar2; + /* * Verifies that the input string is a qualified SQL name using sys.dbms_assert.qualified_sql_name * If null value passed returns null From 274d80a3b93cad1401a305509b41df4a34a83215 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 7 Apr 2022 12:38:41 +0100 Subject: [PATCH 055/187] Fixing ordering --- source/core/ut_suite_cache_manager.pkb | 6 +++--- source/core/ut_suite_manager.pkb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index d76a6412e..d1d5b2e5c 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -259,6 +259,7 @@ create or replace package body ut_suite_cache_manager is Sorting from bottom to top so when we consolidate we will go in proper order. For random seed we will add an extra sort that can be null + TODO: Verify object owner join */ procedure sort_and_randomize_tests( a_suite_rows in out ut_suite_cache_rows, @@ -281,14 +282,13 @@ create or replace package body ut_suite_cache_manager is --Recursive member select t2.path, t2.parent_path,t2.object_owner,t2.line_no,t2.random_seed from t1,extract_parent_child t2 - where t2.parent_path = t1.path - and t1.object_owner = t2.object_owner) + where t2.parent_path = t1.path) search depth first by line_no desc,random_seed desc nulls last set order1 select value(i) as obj bulk collect into l_suite_rows from t1 c join table(a_suite_rows) i on i.object_owner = c.object_owner and i.path = c.path - order by order1 desc; + order by order1 desc; a_suite_rows := l_suite_rows; end; diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 43df7f255..bcf2fc417 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -279,7 +279,7 @@ create or replace package body ut_suite_manager is pragma inline(get_logical_suite, 'YES'); a_suites(a_suites.last) := get_logical_suite(l_rows, l_idx, l_level,l_prev_level, l_items_at_level ); end if; - if l_prev_level > l_level then + if l_prev_level > l_level then l_items_at_level(l_prev_level).delete; end if; l_prev_level := l_level; From 39377379eaed235e47962465f5240fee706f46cf Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 7 Apr 2022 13:00:02 +0100 Subject: [PATCH 056/187] Fixing a documentation --- docs/userguide/running-unit-tests.md | 8 +++----- source/core/types/ut_path_item.tpb | 2 +- source/core/types/ut_path_item.tps | 2 +- source/core/ut_suite_cache_manager.pkb | 6 ++++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 2a8f8e151..8a43e8386 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -45,10 +45,8 @@ The **functions** can only be used in SELECT statements. They execute the specif ## ut.run procedures The examples below illustrate different ways and options to invoke `ut.run` procedures. -As part of the syntax you can use a wildcard character `*` to call test by part of his name or to call few tests that match a call. -Schema name is still mandatory and cannot contain a wildcard character whether is a suitepath or object. - - +You can use a wildcard character `*` to call tests by part of their name or to call tests that are located on paths matched by part of path string. +Schema name cannot contain a wildcard character whether is in a suitepath call or call by object name. ```sql alter session set current_schema=hr; @@ -142,7 +140,7 @@ begin ut.run('hr.test*'); end; ``` -Executes all tests from schema _hr_ starting with name _test_. +Executes all tests in schema `hr` located in packages starting with name `test`. ```sql set serveroutput on diff --git a/source/core/types/ut_path_item.tpb b/source/core/types/ut_path_item.tpb index 3878b544c..6cdb2b8ad 100644 --- a/source/core/types/ut_path_item.tpb +++ b/source/core/types/ut_path_item.tpb @@ -39,4 +39,4 @@ create or replace type body ut_path_item as return; end; end; -/ \ No newline at end of file +/ diff --git a/source/core/types/ut_path_item.tps b/source/core/types/ut_path_item.tps index f6c64195c..c8ec81be5 100644 --- a/source/core/types/ut_path_item.tps +++ b/source/core/types/ut_path_item.tps @@ -23,4 +23,4 @@ create or replace type ut_path_item as object ( constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, suite_path varchar2) return self as result, constructor function ut_path_item(self in out nocopy ut_path_item, schema_name varchar2, object_name varchar2,procedure_name varchar2,suite_path varchar2) return self as result ) -/ \ No newline at end of file +/ diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index d1d5b2e5c..f7e89eb96 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -258,8 +258,10 @@ create or replace package body ut_suite_cache_manager is We will sort a suites in hierarchical structure. Sorting from bottom to top so when we consolidate we will go in proper order. - For random seed we will add an extra sort that can be null - TODO: Verify object owner join + For random seed we will add an extra sort that can be null. + The object owner is irrelevant on joing via path as we already + resolved a list of test we want to use so as long they share a suitepath + they are correct. */ procedure sort_and_randomize_tests( a_suite_rows in out ut_suite_cache_rows, From 9296f382dc5a858032ed292a46611abe4cd91a3f Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 7 Apr 2022 13:24:42 +0100 Subject: [PATCH 057/187] Fixing indent --- source/core/ut_utils.pkb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 10d9d2393..162e50f8f 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -901,7 +901,7 @@ create or replace package body ut_utils is begin if a_random_seed is null then l_result := a_path; - end if; + end if; if a_path is not null then loop l_end_pos := instr(a_path,'.',l_start_pos); From 6ff7f38ba80a1bbc063feb7b696d0236f243dd40 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 12 Apr 2022 23:14:15 +0100 Subject: [PATCH 058/187] Peer review changes --- source/core/ut_suite_cache_manager.pkb | 27 ++++++++--------- source/core/ut_suite_cache_manager.pks | 9 ++++++ source/core/ut_suite_manager.pkb | 40 ++++++++++++-------------- source/core/ut_suite_manager.pks | 1 + source/create_grants.sql | 1 + 5 files changed, 42 insertions(+), 36 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index f7e89eb96..4f8cb8f62 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -19,12 +19,11 @@ create or replace package body ut_suite_cache_manager is /* * Private code */ - - gc_get_bulk_cache_suite_sql constant varchar2(32767) := - q'[with + cursor c_get_bulk_cache_suite(cp_suite_items in ut_suite_cache_rows) is + with suite_items as ( select /*+ cardinality(c 500) */ value(c) as obj - from table(:suite_items) c), + from table(cp_suite_items) c), suitepaths as ( select distinct substr(c.obj.path,1,instr(c.obj.path,'.',-1)-1) as suitepath, c.obj.path as path, @@ -65,9 +64,9 @@ create or replace package body ut_suite_cache_manager is ) as obj from logical_suite_data s ) - select /*+ no_parallel */obj from suite_items + select /*+ no_parallel */ obj from suite_items union all - select /*+ no_parallel */ obj from logical_suites]'; + select /*+ no_parallel */ obj from logical_suites; function get_missing_cache_objects(a_object_owner varchar2) return ut_varchar2_rows is l_result ut_varchar2_rows; @@ -126,6 +125,9 @@ create or replace package body ut_suite_cache_manager is Fourth SQL cover scenario where suitepath is populated with no filters */ + + --TODO: Przenies w osobny with clause z nazwami jako opis. + -- i with clause na tablice. function expand_paths(a_schema_paths ut_path_items) return ut_path_items is l_schema_paths ut_path_items:= ut_path_items(); begin @@ -310,26 +312,21 @@ create or replace package body ut_suite_cache_manager is a_tags ut_varchar2_rows := null ) return ut_suite_cache_rows is l_results ut_suite_cache_rows := ut_suite_cache_rows(); - l_results2 ut_suite_cache_rows := ut_suite_cache_rows(); l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); l_schema_paths ut_path_items; l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); - l_sql varchar2(32767); begin l_schema_paths := a_schema_paths; - l_sql := gc_get_bulk_cache_suite_sql; l_suite_items := get_suite_items(a_schema_paths); if l_tags.count > 0 then l_suite_items := get_tags_suites(l_suite_items,l_tags); end if; - ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_key_anyvalues().put('l_sql',l_sql) ); - - execute immediate l_sql - bulk collect into l_results - using l_suite_items; + + open c_get_bulk_cache_suite(l_suite_items); + fetch c_get_bulk_cache_suite bulk collect into l_results; + close c_get_bulk_cache_suite; - sort_and_randomize_tests(l_results,a_random_seed); return l_results; end; diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 6b12e7439..974babca5 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -40,6 +40,15 @@ create or replace package ut_suite_cache_manager authid definer is */ procedure remove_missing_objs_from_cache(a_schema_name varchar2); + /* + * We will sort a suites in hierarchical structure. + * Sorting from bottom to top so when we consolidate + * we will go in proper order. + */ + procedure sort_and_randomize_tests( + a_suite_rows in out ut_suite_cache_rows, + a_random_seed positive := null); + /* * Retrieves suite items data from cache. * Returned data is not filtered by user access rights. diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index bcf2fc417..b29b8134c 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -295,7 +295,8 @@ create or replace package body ut_suite_manager is end loop; close a_suite_data_cursor; end reconstruct_from_cache; - + + --TODO: daj do public ut_suite_cache_rows i zmienic na SQL function get_filtered_cursor( a_unfiltered_rows in ut_suite_cache_rows, a_skip_all_objects boolean := false @@ -306,26 +307,21 @@ create or replace package body ut_suite_manager is if ut_metadata.user_has_execute_any_proc() or a_skip_all_objects then l_result := a_unfiltered_rows; else - for i in ( - select /*+ no_parallel */ c.* from table(a_unfiltered_rows) c - where sys_context( 'userenv', 'current_user' ) = upper(c.object_owner) - union all - select /*+ no_parallel */ c.* from table(a_unfiltered_rows) c - where sys_context( 'userenv', 'current_user' ) != upper(c.object_owner) - and ( exists - ( select 1 - from all_objects a - where a.object_name = c.object_name - and a.owner = c.object_owner - and a.object_type = 'PACKAGE' - ) - or c.self_type = 'UT_LOGICAL_SUITE')) - loop - l_result.extend; - l_result(l_result.last) := ut_suite_cache_row(i.id,i.self_type,i.path,i.object_owner,i.object_name,i.name,i.line_no,i.parse_time, - i.description,i.rollback_type,i.disabled_flag,i.disabled_reason,i.warnings,i.before_all_list,i.after_all_list,i.before_each_list, - i.before_test_list,i.after_each_list,i.after_test_list,i.expected_error_codes,i.tags,i.item); - end loop; + select obj bulk collect into l_result + from ( + select /*+ no_parallel */ value(c) as obj from table(a_unfiltered_rows) c + where sys_context( 'userenv', 'current_user' ) = upper(c.object_owner) + union all + select /*+ no_parallel */ value(c) as obj from table(a_unfiltered_rows) c + where sys_context( 'userenv', 'current_user' ) != upper(c.object_owner) + and ( exists + ( select 1 + from all_objects a + where a.object_name = c.object_name + and a.owner = c.object_owner + and a.object_type = 'PACKAGE' + ) + or c.self_type = 'UT_LOGICAL_SUITE')); end if; return l_result; end; @@ -373,6 +369,8 @@ create or replace package body ut_suite_manager is l_filtered_rows := get_filtered_cursor(l_unfiltered_rows,a_skip_all_objects); reconcile_paths_and_suites(a_schema_paths,l_filtered_rows); + ut_suite_cache_manager.sort_and_randomize_tests(l_filtered_rows,a_random_seed); + open l_result for select * from table(l_filtered_rows); return l_result; diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index 6c96500b3..170b83f05 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -39,6 +39,7 @@ create or replace package ut_suite_manager authid current_user is * @return array containing root suites-ready to be executed * */ + --TODO:Zerknij czy mozna wywalic function configure_execution_by_path(a_paths ut_varchar2_list, a_random_seed positive := null) return ut_suite_items; /** diff --git a/source/create_grants.sql b/source/create_grants.sql index 6401b1522..8a44ab371 100644 --- a/source/create_grants.sql +++ b/source/create_grants.sql @@ -60,6 +60,7 @@ grant execute on &&ut3_owner..ut_file_mapping to &ut3_user; grant execute on &&ut3_owner..ut_file_mapper to &ut3_user; grant execute on &&ut3_owner..ut_suite_items_info to &ut3_user; grant execute on &&ut3_owner..ut_suite_item_info to &ut3_user; +grant execute on &&ut3_owner..ut_suite_cache_rows to &ut3_user; grant execute on &&ut3_owner..ut_run_info to &ut3_user; grant execute on &&ut3_owner..ut_coverage_options to &ut3_user; From ee7a98b97357667fd7229c3f6711e4bd7cb2576c Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 12 Apr 2022 23:24:56 +0100 Subject: [PATCH 059/187] Moving a SQL to be more readable. --- source/core/ut_suite_cache_manager.pkb | 38 +++++++++++++++++--------- source/core/ut_suite_manager.pkb | 1 - 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 4f8cb8f62..ae34e1344 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -125,51 +125,63 @@ create or replace package body ut_suite_cache_manager is Fourth SQL cover scenario where suitepath is populated with no filters */ - - --TODO: Przenies w osobny with clause z nazwami jako opis. - -- i with clause na tablice. function expand_paths(a_schema_paths ut_path_items) return ut_path_items is l_schema_paths ut_path_items:= ut_path_items(); begin - with paths_to_expand as ( + with + schema_paths as ( + select * from table(a_schema_paths) + ), + paths_for_object as ( select /*+ no_parallel */ min(path) as suite_path,sp.schema_name as schema_name,nvl(c.object_name,sp.object_name) as object_name, null as procedure_name - from table(a_schema_paths) sp left outer join ut_suite_cache c + from schema_paths sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) and c.object_name like replace(upper(sp.object_name),'*','%')) where sp.suite_path is null and sp.object_name is not null and ( sp.procedure_name is null or sp.procedure_name = '*') group by sp.schema_name,nvl(c.object_name,sp.object_name) - union all + ), + paths_for_procedures as ( select /*+ no_parallel */ path as suite_path,sp.schema_name as schema_name,nvl(c.object_name,sp.object_name) as object_name, nvl(c.name,sp.procedure_name) as procedure_name - from table(a_schema_paths) sp left outer join ut_suite_cache c + from schema_paths sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) and c.object_name like replace(upper(sp.object_name),'*','%') and c.name like nvl(replace(upper(sp.procedure_name),'*','%'), c.name)) where sp.suite_path is null and sp.object_name is not null and (sp.procedure_name is not null and sp.procedure_name != '*') - union all + ), + paths_for_suite_path_with_ast as ( select /*+ no_parallel */ nvl(c.path,sp.suite_path) as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name - from - table(a_schema_paths) sp left outer join ut_suite_cache c on + from schema_paths sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) and c.path like replace(sp.suite_path,'*','%')) where sp.suite_path is not null and instr(sp.suite_path,'*') > 0 - union all + ), + straigth_suite_paths as ( select /*+ no_parallel */ sp.suite_path as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name - from table(a_schema_paths) sp + from schema_paths sp where (sp.suite_path is not null and instr(sp.suite_path,'*') = 0) or (sp.suite_path is null and sp.object_name is null) + ), + all_suitepaths_together as ( + select * from paths_for_object + union all + select * from paths_for_procedures + union all + select * from paths_for_suite_path_with_ast + union all + select * from straigth_suite_paths ) select ut_path_item(schema_name,object_name,procedure_name,suite_path) bulk collect into l_schema_paths from (select schema_name,object_name,procedure_name,suite_path, row_number() over ( partition by schema_name,object_name,procedure_name,suite_path order by 1) as r_num - from paths_to_expand) + from all_suitepaths_together) where r_num = 1 ; return l_schema_paths; end; diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index b29b8134c..4c3542f23 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -296,7 +296,6 @@ create or replace package body ut_suite_manager is close a_suite_data_cursor; end reconstruct_from_cache; - --TODO: daj do public ut_suite_cache_rows i zmienic na SQL function get_filtered_cursor( a_unfiltered_rows in ut_suite_cache_rows, a_skip_all_objects boolean := false From a53cefa29e9d49d6b60255f0ded327e843c4502f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20G=C4=99bal?= Date: Wed, 13 Apr 2022 10:46:57 +0100 Subject: [PATCH 060/187] Apply suggestions from code review --- docs/userguide/running-unit-tests.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 8a43e8386..1a26ca203 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -84,7 +84,7 @@ begin end; ``` -Executes all tests from all packages that are on suitepath starting with _com_. +Executes all tests in schema `hr` from all packages that are on suitepath starting with `com`. ```sql set serveroutput on @@ -148,7 +148,7 @@ begin ut.run('hr.test_apply_bonus.bonus_*'); end; ``` -Executes all test procedures from package _hr.test_apply_bonus_ that starting with _bonus_. +Executes test procedures with names starting with `bonus` in package `hr.test_apply_bonus` . **Note:** From 011970f8f642e2d63d94c0f02027d7e59cf74cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20G=C4=99bal?= Date: Wed, 13 Apr 2022 17:16:18 +0300 Subject: [PATCH 061/187] Apply suggestions from code review --- source/core/ut_suite_cache_manager.pkb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index ae34e1344..4c738ab64 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -258,12 +258,12 @@ create or replace package body ut_suite_cache_manager is from table(a_suite_items) c where exists ( select 1 from included_tags t - where t.path||'.' like c.path || '.%' /*all parents and self*/ - or c.path||'.' like t.path || '.%' /*all children and self*/ + where t.path||'.' like c.path || '.%' /*all ancestors and self*/ + or c.path||'.' like t.path || '.%' /*all descendants and self*/ ) and not exists ( select 1 from excluded_tags t - where c.path||'.' like t.path || '.%' /*all children and self*/ + where c.path||'.' like t.path || '.%' /*all descendants and self*/ ); return l_suite_tags; end; From 3437b689e2097b1bdae4b0daf22b09549e5eabee Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 15 Apr 2022 23:25:52 +0300 Subject: [PATCH 062/187] Fixed issue where schema last parse time was wrongly populated --- source/core/annotations/ut_annotation_manager.pkb | 8 +++----- source/core/ut_suite_cache_manager.pkb | 2 +- source/core/ut_suite_manager.pkb | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/source/core/annotations/ut_annotation_manager.pkb b/source/core/annotations/ut_annotation_manager.pkb index 95d944843..16923bc23 100644 --- a/source/core/annotations/ut_annotation_manager.pkb +++ b/source/core/annotations/ut_annotation_manager.pkb @@ -61,15 +61,15 @@ create or replace package body ut_annotation_manager as l_refresh_needed boolean; l_objects_view varchar2(200) := ut_metadata.get_objects_view_name(); l_cached_objects ut_annotation_objs_cache_info; - l_result ut_annotation_objs_cache_info; + l_result ut_annotation_objs_cache_info := ut_annotation_objs_cache_info(); begin - ut_event_manager.trigger_event( 'get_objects_to_refresh - start' ); + ut_event_manager.trigger_event( 'get_objects_to_refresh - start', ut_key_anyvalues().put('ut_trigger_check.is_alive()',ut_trigger_check.is_alive()) ); l_refresh_needed := ( ut_trigger_check.is_alive() = false ) or a_modified_after is null; - l_cached_objects := ut_annotation_cache_manager.get_cached_objects_list( a_object_owner, a_object_type, a_modified_after ); if l_refresh_needed then --limit the list to objects that exist and are visible to the invoking user --enrich the list by info about cache validity + l_cached_objects := ut_annotation_cache_manager.get_cached_objects_list( a_object_owner, a_object_type, a_modified_after ); execute immediate 'select /*+ no_parallel cardinality(i '||ut_utils.scale_cardinality(cardinality(l_cached_objects))||') */ '||l_ut_owner||q'[.ut_annotation_obj_cache_info( @@ -94,8 +94,6 @@ create or replace package body ut_annotation_manager as else 'o.last_ddl_time >= cast(:a_modified_after as date)' end bulk collect into l_result using l_cached_objects, a_modified_after; - else - l_result := l_cached_objects; end if; ut_event_manager.trigger_event('get_objects_to_refresh - end (count='||l_result.count||')'); return l_result; diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index ad1634c10..1023a515b 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -297,7 +297,7 @@ create or replace package body ut_suite_cache_manager is if a_parse_time > l_cached_parse_time or l_cached_parse_time is null then update /*+ no_parallel */ ut_suite_cache_schema t - set t.parse_time = a_parse_time + set t.parse_time = greatest(t.parse_time,a_parse_time) where object_owner = l_object_owner; if sql%rowcount = 0 then diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 4bcb83afa..a11b0249c 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -366,7 +366,7 @@ create or replace package body ut_suite_manager is ) or c.self_type = 'UT_LOGICAL_SUITE'; end if; - + return l_result; end; @@ -578,7 +578,7 @@ create or replace package body ut_suite_manager is a_suites(i).set_rollback_type( a_suites(i).get_rollback_type() ); end loop; - ut_event_manager.trigger_event('configure_execution_by_path - start'); + ut_event_manager.trigger_event('configure_execution_by_path - end'); end configure_execution_by_path; function get_suites_info( From 6751290e503b45c589d83931743a2fa7dc402b12 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 Apr 2022 22:19:15 +0100 Subject: [PATCH 063/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index ad0cad34c..4594b9864 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 9641132fd..746421e4a 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index c1eefa2dd..590fce081 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 5812e2cab..6400be9d1 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 140c3e3dd..e1a5cd7dd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 9e4528342..085c06221 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index a2612c3b8..68a26ce8b 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 9c90a1865..645eda5f1 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 2c262abbf..0112c44d8 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 27dfc6c1f..a84d80f11 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 8e1872497..9dabeb2fd 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 3aa97dcb8..c29a40c7b 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 08308bc8a..1c631d0d5 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 11e08be1d..976630ae9 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 373830f95..8f4d0765a 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index d3fcfd520..e2f308c47 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index bf5cf8c7b..a5fb8a669 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.3943--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 027a06c21..3635bccad 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.3943-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4003-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 221c2de768de9120dd3031a795dae82c5f6a6586 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 16 Apr 2022 02:31:56 +0100 Subject: [PATCH 064/187] Address issue of not recognizing a correct nested level of suitepath. Added extra tests for different scenarios. --- source/core/ut_suite_cache_manager.pkb | 3 +- test/ut3_tester/core/test_suite_manager.pkb | 495 +++++++++++++++++++- test/ut3_tester/core/test_suite_manager.pks | 36 +- 3 files changed, 525 insertions(+), 9 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 4c738ab64..b12f415d2 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -156,7 +156,8 @@ create or replace package body ut_suite_cache_manager is select /*+ no_parallel */ nvl(c.path,sp.suite_path) as suite_path,sp.schema_name,sp.object_name,sp.procedure_name as procedure_name from schema_paths sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) - and c.path like replace(sp.suite_path,'*','%')) + --and c.path like replace(sp.suite_path,'*','%')) + and regexp_like(c.path,'^'||replace(sp.suite_path,'*','[A-Za-z0-9$#_]*'))) where sp.suite_path is not null and instr(sp.suite_path,'*') > 0 ), straigth_suite_paths as ( diff --git a/test/ut3_tester/core/test_suite_manager.pkb b/test/ut3_tester/core/test_suite_manager.pkb index 684cc14fe..fbac0f3f5 100644 --- a/test/ut3_tester/core/test_suite_manager.pkb +++ b/test/ut3_tester/core/test_suite_manager.pkb @@ -278,8 +278,167 @@ end test_package_with_ctx;]'; end; end test_package_with_ctx;]'; + + execute immediate q'[create or replace package test1_frontwildcard is + + --%suite + --%displayname(test1_frontwildcard) + --%suitepath(front_wildcard) + --%rollback(manual) + + --%test + --%displayname(Test1 from test test1_frontwildcard) + procedure first_test; + + --%test + --%displayname(Test2 from test test1_frontwildcard) + procedure second_test; + +end test1_frontwildcard;]'; + + execute immediate q'[create or replace package body test1_frontwildcard is + + procedure first_test is + begin + ut.expect(1).to_equal(1); + end; + + procedure second_test is + begin + ut.expect(1).to_equal(2); + end; + +end test1_frontwildcard;]'; + + execute immediate q'[create or replace package test2_frontwildcard is + + --%suite + --%displayname(test2_frontwildcard) + --%suitepath(front_wildcard) + --%rollback(manual) + + --%test + --%displayname(Test1 from test package test2_frontwildcard) + procedure first_test; + +end test2_frontwildcard;]'; + + execute immediate q'[create or replace package body test2_frontwildcard is + + procedure first_test is + begin + ut.expect(1).to_equal(1); + end; + +end test2_frontwildcard;]'; + + execute immediate q'[create or replace package middle_test1_wildcard is + + --%suite + --%displayname(middle_test1_wildcard) + --%suitepath(wild_middle_card) + --%rollback(manual) + + --%test + --%displayname(Test1 from test middle_test1_wildcard) + procedure middle_first_test; + + --%test + --%displayname(Test2 from test middle_test1_wildcard) + procedure middle_second_test; + +end middle_test1_wildcard;]'; + + execute immediate q'[create or replace package body middle_test1_wildcard is + + procedure middle_first_test is + begin + ut.expect(1).to_equal(1); + end; + + procedure middle_second_test is + begin + ut.expect(1).to_equal(2); end; +end middle_test1_wildcard;]'; + + execute immediate q'[create or replace package middle_test2_wildcard is + + --%suite + --%displayname(middle_test2_wildcard) + --%suitepath(wild_middle_card) + --%rollback(manual) + + --%test + --%displayname(Test1 from test package middle_test2_wildcard) + procedure middle_first_test; + +end middle_test2_wildcard;]'; + + execute immediate q'[create or replace package body middle_test2_wildcard is + + procedure middle_first_test is + begin + ut.expect(1).to_equal(1); + end; + +end middle_test2_wildcard;]'; + + execute immediate q'[create or replace package test1_multi_wildcard is + + --%suite + --%displayname(test1_multi_wildcard) + --%suitepath(wildcard_multi_asterisks) + --%rollback(manual) + + --%test + --%displayname(Test1 from test test1_multi_wildcard) + procedure first_multi_test1; + + --%test + --%displayname(Test2 from test test1_multi_wildcard) + procedure second_multi_test2; + +end test1_multi_wildcard;]'; + + execute immediate q'[create or replace package body test1_multi_wildcard is + + procedure first_multi_test1 is + begin + ut.expect(1).to_equal(1); + end; + + procedure second_multi_test2 is + begin + ut.expect(1).to_equal(2); + end; + +end test1_multi_wildcard;]'; + + execute immediate q'[create or replace package test2_multi_wildcard is + + --%suite + --%displayname(test2_multi_wildcard) + --%suitepath(wildcard_multi_asterisks) + --%rollback(manual) + + --%test + --%displayname(Test1 from test package test2_multi_wildcard) + procedure first_multi_test1; + +end test2_multi_wildcard;]'; + + execute immediate q'[create or replace package body test2_multi_wildcard is + + procedure first_multi_test1 is + begin + ut.expect(1).to_equal(1); + end; + +end test2_multi_wildcard;]'; + + end; procedure drop_dummy_packages is pragma autonomous_transaction; @@ -288,6 +447,12 @@ end test_package_with_ctx;]'; execute immediate 'drop package test_package_2'; execute immediate 'drop package test_package_3'; execute immediate 'drop package test_package_with_ctx'; + execute immediate 'drop package test1_frontwildcard'; + execute immediate 'drop package test2_frontwildcard'; + execute immediate 'drop package middle_test1_wildcard'; + execute immediate 'drop package middle_test2_wildcard'; + execute immediate 'drop package test1_multi_wildcard'; + execute immediate 'drop package test2_multi_wildcard'; end; procedure test_schema_run is @@ -1671,8 +1836,7 @@ end;]'; l_objects_to_run ut3_develop.ut_suite_items; l_test_suite ut3_develop.ut_logical_suite; l_test1_suite ut3_develop.ut_logical_suite; - l_test2_suite ut3_develop.ut_logical_suite; - l_test3_suite ut3_develop.ut_logical_suite; + l_test2_suite ut3_develop.ut_logical_suite; l_ctx_suite ut3_develop.ut_logical_suite; l_test_proc ut3_develop.ut_test; begin @@ -1694,9 +1858,6 @@ end;]'; ut.expect(l_test1_suite.items.count).to_equal(3); for i in 1 ..3 loop - --l_test2_suite := treat(l_test1_suite.items(i) as ut3_develop.ut_logical_suite); - --ut.expect(l_test2_suite.name).to_equal('test_package_2'); - --ut.expect(l_test2_suite.items.count).to_equal(3); case l_test1_suite.items(i).self_type when 'UT_SUITE' then l_test2_suite := treat(l_test1_suite.items(i) as ut3_develop.ut_logical_suite); @@ -1732,5 +1893,329 @@ end;]'; end; + procedure test_wild_card_front_obj_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.*_frontwildcard'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('front_wildcard'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_frontwildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_test'); + when 'test2_frontwildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + end case; + + end loop; + end; + + procedure test_wild_card_front_prc_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.test1_frontwildcard.*_test'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('front_wildcard'); + + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test1_frontwildcard'); + ut.expect(l_test1_suite.items.count).to_equal(2); + + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_test'); + end; + + procedure test_wild_card_front_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':*_wildcard'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('front_wildcard'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_frontwildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_test'); + when 'test2_frontwildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_test'); + end case; + + end loop; + end; + + procedure test_wild_card_mid_obj_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.middle_*_wildcard'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wild_middle_card'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'middle_test1_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('middle_second_test'); + when 'middle_test2_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + end case; + + end loop; + end; + + procedure test_wild_card_mid_prc_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.middle_test1_wildcard.middle_*_test'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wild_middle_card'); + + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('middle_test1_wildcard'); + ut.expect(l_test1_suite.items.count).to_equal(2); + + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('middle_second_test'); + end; + + procedure test_wild_card_mid_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':wild_*card'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wild_middle_card'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'middle_test1_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('middle_second_test'); + when 'middle_test2_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('middle_first_test'); + end case; + + end loop; + end; + + procedure test_wild_card_mul_obj_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.*_multi_*card'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wildcard_multi_asterisks'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_multi_test2'); + when 'test2_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + end case; + + end loop; + end; + + procedure test_wild_card_mul_prc_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||'.test1_multi_wildcard.*_multi_*'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wildcard_multi_asterisks'); + + l_test1_suite := treat(l_test_suite.items(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test1_suite.name).to_equal('test1_multi_wildcard'); + ut.expect(l_test1_suite.items.count).to_equal(2); + + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_multi_test2'); + end; + + procedure test_wild_card_mul_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':wild*_multi_*risks'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wildcard_multi_asterisks'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(2); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + l_test2_proc := treat(l_test1_suite.items(2) as ut3_develop.ut_test); + ut.expect(l_test2_proc.name).to_equal('second_multi_test2'); + when 'test2_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + end case; + + end loop; + end; + + procedure tst_wild_card_mul_lv_path_name is + c_path varchar2(100) := sys_context('USERENV', 'CURRENT_USER')||':wild*_multi_*risks.*_multi_wildcard.*_multi_test1'; + l_objects_to_run ut3_develop.ut_suite_items; + l_test_suite ut3_develop.ut_logical_suite; + l_test1_suite ut3_develop.ut_logical_suite; + l_test1_proc ut3_develop.ut_test; + l_test2_proc ut3_develop.ut_test; + begin + --Act + l_objects_to_run := ut3_develop.ut_suite_manager.configure_execution_by_path(ut3_develop.ut_varchar2_list(c_path)); + + --Assert + ut.expect(l_objects_to_run.count).to_equal(1); + l_test_suite := treat(l_objects_to_run(1) as ut3_develop.ut_logical_suite); + ut.expect(l_test_suite.name).to_equal('wildcard_multi_asterisks'); + ut.expect(l_test_suite.items.count).to_equal(2); + + for i in 1 .. 2 loop + l_test1_suite := treat(l_test_suite.items(i) as ut3_develop.ut_logical_suite); + case l_test1_suite.name + when 'test1_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + when 'test2_multi_wildcard' then + ut.expect(l_test1_suite.items.count).to_equal(1); + l_test1_proc := treat(l_test1_suite.items(1) as ut3_develop.ut_test); + ut.expect(l_test1_proc.name).to_equal('first_multi_test1'); + end case; + + end loop; + end; + end test_suite_manager; / diff --git a/test/ut3_tester/core/test_suite_manager.pks b/test/ut3_tester/core/test_suite_manager.pks index ccd4d586c..d9d4efc09 100644 --- a/test/ut3_tester/core/test_suite_manager.pks +++ b/test/ut3_tester/core/test_suite_manager.pks @@ -196,15 +196,45 @@ create or replace package test_suite_manager is --%context(wildcard_filters) - --%test(Execute test_packages using a object_name with wildcard ) + --%test(Execute test_packages using a object_name with wildcard at the end ) procedure test_wild_card_obj_name; - --%test(Execute test_packages using a procedure name with wildcard ) + --%test(Execute test_packages using a procedure name with wildcard at the end) procedure test_wild_card_prc_name; - --%test(Execute test_packages using a path name with wildcard ) + --%test(Execute test_packages using a path name with wildcard at the end) procedure test_wild_card_path_name; + --%test(Execute test_packages using a object_name with wildcard in the front) + procedure test_wild_card_front_obj_name; + + --%test(Execute test_packages using a procedure name with wildcard in the front) + procedure test_wild_card_front_prc_name; + + -- %test(Execute test_packages using a path name with wildcard in the front) + procedure test_wild_card_front_path_name; + + --%test(Execute test_packages using a object_name with wildcard in the middle) + procedure test_wild_card_mid_obj_name; + + --%test(Execute test_packages using a procedure name with wildcard in the middle) + procedure test_wild_card_mid_prc_name; + + -- %test(Execute test_packages using a path name with wildcard in the middle) + procedure test_wild_card_mid_path_name; + + --%test(Execute test_packages using a object_name with multiple wildcards) + procedure test_wild_card_mul_obj_name; + + --%test(Execute test_packages using a procedure name with multiple wildcards) + procedure test_wild_card_mul_prc_name; + + -- %test(Execute test_packages using a path name with multiple wildcards) + procedure test_wild_card_mul_path_name; + + -- %test(Execute test_packages using a path name with multiple wildcards on different level) + procedure tst_wild_card_mul_lv_path_name; + --%endcontext end test_suite_manager; From 51439d8eb4b81c1e1ab53c2430692c8db3c6eae7 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 16 Apr 2022 02:39:48 +0100 Subject: [PATCH 065/187] Update documentation --- docs/userguide/running-unit-tests.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index c0efeba52..2288bf3f1 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -46,6 +46,7 @@ The **functions** can only be used in SELECT statements. They execute the specif The examples below illustrate different ways and options to invoke `ut.run` procedures. You can use a wildcard character `*` to call tests by part of their name or to call tests that are located on paths matched by part of path string. +Wildcard character can be placed anywhere on the path and can occur mutliple times. Schema name cannot contain a wildcard character whether is in a suitepath call or call by object name. ```sql @@ -86,6 +87,15 @@ end; Executes all tests in schema `hr` from all packages that are on suitepath starting with `com`. +```sql +set serveroutput on +begin + ut.run('hr:co*.my_*.my_*'); +end; +``` + +Executes all tests in schema `hr` from all packages that starting with `my_` and all tests starting with `my_*` that are on suitepath starting with `co` . + ```sql set serveroutput on begin From 0fc7ff6d4717e7208ce2fd73d831b55e2c4316f8 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 16 Apr 2022 16:22:09 +0100 Subject: [PATCH 066/187] Fixing issue where parition by only path caused a duplicate level 1 across two owners being removed. --- source/core/ut_suite_cache_manager.pkb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index e525be7ea..6ed4f50f0 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -203,7 +203,7 @@ create or replace package body ut_suite_cache_manager is begin select obj bulk collect into l_suite_items from ( - select /*+ cardinality(c 500) */ value(c) as obj,row_number() over ( partition by path order by path asc) as r_num + select /*+ cardinality(c 500) */ value(c) as obj,row_number() over ( partition by path,object_owner order by path,object_owner asc) as r_num from ut_suite_cache c, table(a_schema_paths) sp where c.object_owner = upper(sp.schema_name) From 647b830df119f6931347bf5d37475e645c252896 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 17 Apr 2022 03:33:30 +0300 Subject: [PATCH 067/187] Fixed issue with suites getting duplicated when running tests across multiple schemas --- source/core/ut_suite_cache_manager.pkb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 6ed4f50f0..d3e832a9b 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -287,11 +287,11 @@ create or replace package body ut_suite_cache_manager is with extract_parent_child as ( select s.path, substr(s.path,1,instr(s.path,'.',-1,1)-1) as parent_path,s.object_owner, - case when a_random_seed is null then s.line_no else null end line_no, - case when a_random_seed is null then null else ut_utils.hash_suite_path(s.path, a_random_seed) end random_seed + case when a_random_seed is null then s.line_no end line_no, + case when a_random_seed is not null then ut_utils.hash_suite_path(s.path, a_random_seed) end random_seed from table(a_suite_rows) s), t1(path,parent_path,object_owner,line_no,random_seed) as ( - --Anchor memeber + --Anchor member select s.path, parent_path,s.object_owner,s.line_no,random_seed from extract_parent_child s where parent_path is null @@ -299,7 +299,8 @@ create or replace package body ut_suite_cache_manager is --Recursive member select t2.path, t2.parent_path,t2.object_owner,t2.line_no,t2.random_seed from t1,extract_parent_child t2 - where t2.parent_path = t1.path) + where t2.parent_path = t1.path + and t2.object_owner = t1.object_owner) search depth first by line_no desc,random_seed desc nulls last set order1 select value(i) as obj bulk collect into l_suite_rows From 58f69979f8676aa1808b09ff09af30aa9f9e6f9d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 23 Apr 2022 10:47:40 +0100 Subject: [PATCH 068/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 4594b9864..d0998977b 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 746421e4a..77de81572 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 590fce081..446fface8 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 6400be9d1..cc759f3ff 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index e1a5cd7dd..e3cd96e35 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 085c06221..08301acfe 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 68a26ce8b..7e40371fc 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 645eda5f1..48da86cac 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 0112c44d8..d3b0d3fee 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index a84d80f11..19a6e2da7 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 9dabeb2fd..23bfa4105 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index c29a40c7b..8fab1969a 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 1c631d0d5..4c334ae8a 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 0cfd513f3..460d024c6 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 8f4d0765a..3bd5662cf 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 2288bf3f1..6029aced1 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index a5fb8a669..e13a7e59d 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4003--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 995d83c10..21f6424d8 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4003-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4014-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From d88dd2d740919856853edd208ca11bb03133d515 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 26 May 2022 12:31:28 +0300 Subject: [PATCH 069/187] Updated slack link in feature request --- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- docs/about/support.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 4cd72f51c..681bc7f3a 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -23,4 +23,4 @@ Add any other context or screenshots about the feature request here. > Please do not create issues for generic SQL or PL/SQL questions. There are other forums and communities to help you with those. See [ASKTom](https://asktom.oracle.com) for example. **Want to discuss** -If you want to discuss your issue, join [our SLACK chat](https://join.slack.com/t/utplsql/shared_invite/zt-d6zor80g-WWqAhbLWioJZUtLYeXetzA). +If you want to discuss your issue, join [our SLACK chat](https://join.slack.com/t/utplsql/shared_invite/zt-xwm68udy-4cF_3PNEyczYEbWr38W5ww). diff --git a/docs/about/support.md b/docs/about/support.md index cc759f3ff..178412fdb 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -3,4 +3,4 @@ # How to get support - Feel free to post questions, bugs or issues in the [issues area of GitHub](https://github.com/utPLSQL/utPLSQL/issues) -- [Join](https://join.slack.com/t/utplsql/shared_invite/zt-xwm68udy-4cF_3PNEyczYEbWr38W5ww) developers team on utPLSQL [Slack](https://utplsql.slack.com/) +- [Join](https://join.slack.com/t/utplsql/shared_invite/zt-xwm68udy-4cF_3PNEyczYEbWr38W5ww) developers team on [utPLSQL Slack](https://utplsql.slack.com/) From fc5c4af28ad9416de894670a92cdc3fe9081f4f4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 26 May 2022 10:50:51 +0100 Subject: [PATCH 070/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index d0998977b..1de762d74 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 77de81572..5030fff0a 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 446fface8..71178988b 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 178412fdb..1c0679440 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index e3cd96e35..b79c845f5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 08301acfe..2faf98dec 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 7e40371fc..933b1b119 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 48da86cac..85a4351ce 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index d3b0d3fee..b66b5dff7 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 19a6e2da7..6a8b3d4e3 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 23bfa4105..20f641e45 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 8fab1969a..cd2f41af6 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 4c334ae8a..fbe3b44a1 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 460d024c6..136770405 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 3bd5662cf..14d411aa6 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 6029aced1..d833b6c94 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index e13a7e59d..14e35a5b5 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4014--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 21f6424d8..6ef2c4a9a 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4014-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4015-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 4f944a6d223e9a5d037e42e97dad8c5e92e88b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20G=C4=99bal?= Date: Thu, 28 Jul 2022 12:52:39 +0100 Subject: [PATCH 071/187] Fix uninstall scripts Fixing problem with uninstall script buffer overflow on DBMS_OUTPUT. Reolves: #1220 --- source/uninstall_objects.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index ab4069497..571d187a2 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -1,5 +1,4 @@ set echo off -set serverout on declare procedure drop_if_exists(a_object_type varchar2, a_object_name varchar2) is l_count integer; From aa9d2737be7c789c6d779a481edc6175d81677d2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 8 Aug 2022 13:24:24 +0100 Subject: [PATCH 072/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 1de762d74..50660b2f2 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 5030fff0a..87d1283e6 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 71178988b..f05c9c428 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 1c0679440..fd4009308 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index b79c845f5..90deef32c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 2faf98dec..74fbdd89f 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 933b1b119..4bd01a6d3 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 85a4351ce..efbdae53c 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index b66b5dff7..f623877f7 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 6a8b3d4e3..644cad22e 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 20f641e45..fc8355f64 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index cd2f41af6..2a61ee10b 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index fbe3b44a1..eca9fd6d6 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 136770405..9e21d3635 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 14d411aa6..68b7694cd 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index d833b6c94..0f1e182ad 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 14e35a5b5..707ff8f4e 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4015--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 6ef2c4a9a..f7493229f 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4015-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4018-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 4e82973abad2e1b6dc8d91088f71a5a15d08f29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kukie=C5=82a?= <53443372+kukimik@users.noreply.github.com> Date: Mon, 8 Aug 2022 14:55:49 +0200 Subject: [PATCH 073/187] Fix dropped synonyms counter. --- source/uninstall_synonyms.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/uninstall_synonyms.sql b/source/uninstall_synonyms.sql index 569e5057d..2c96c03a4 100644 --- a/source/uninstall_synonyms.sql +++ b/source/uninstall_synonyms.sql @@ -15,10 +15,10 @@ begin and not exists (select 1 from all_objects o where o.owner = s.table_owner and o.object_name = s.table_name) ) loop - i := i + 1; begin execute immediate 'drop '||syn.syn_name; dbms_output.put_line('Dropped '||syn.syn_name||' for object '||syn.for_object); + i := i + 1; exception when others then dbms_output.put_line('FAILED to drop '||syn.syn_name||' for object '||syn.for_object); From 1bd302881bcadeefc4501f69c1aca9caafbf73fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 15 Aug 2022 11:41:39 +0100 Subject: [PATCH 074/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 50660b2f2..a465b7968 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 87d1283e6..208f59141 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index f05c9c428..a538b25f3 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index fd4009308..6416b668a 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 90deef32c..7c71123d4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 74fbdd89f..ac712002c 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 4bd01a6d3..8dd117676 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index efbdae53c..acfc0559f 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index f623877f7..303a1a6d7 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 644cad22e..5a8cf3361 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index fc8355f64..65b9af484 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 2a61ee10b..c4dccfb51 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index eca9fd6d6..56f4d573b 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 9e21d3635..f3f4f3c1c 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 68b7694cd..3b4802357 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 0f1e182ad..5946f70b0 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 707ff8f4e..3d5b9d7ce 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4018--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index f7493229f..bc5d28826 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4018-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4021-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 53dc4d8526fa0a562fd11172315412da18168906 Mon Sep 17 00:00:00 2001 From: kukimik Date: Sun, 14 Aug 2022 22:52:34 +0200 Subject: [PATCH 075/187] Add a section on custom reporters. --- docs/userguide/reporters.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 68b7694cd..8431582a4 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -161,5 +161,20 @@ Some of the information in debug log might be redundant. > - db object names > - etc. - - \ No newline at end of file +# Custom reporters + +It is possible to add your own reporters by creating an appropriate object type. In principle, it has to be a subtype of `ut_reporter_base`. However, if the reporter is expected to produce output consumable by a client oustside of the database (e.g. the data has to be reported to the screen or to a file), then you should base it on `ut_output_reporter_base` (which is a subtype of `ut_reporter_base`). In contrast, if you would like to create a reporter that, for example, saves the data to a database table, then it should be based directly on `ut_reporter_base`. (Currently, all reporters in the utPLSQL framework are based on `ut_output_reporter_base`.) Coverage reporters are based on `ut_coverage_reporter_base` (a subtype of `ut_output_reporter_base`). + +If need to produce a colored text output from the custom reporter, then you can build it basing on `ut_console_reporter_base` (a subtype of `ut_output_reporter_base`). In many cases it may also be more convenient to create the custom reporter type under a more specialized type, like `ut_documentation_reporter` or `ut_junit_reporter`, and override just some of the functionality. + +It is recommended to create the reporter type in the schema where utPLSQL is installed (by default it is the `UT3` schema). Note that before running the utPLSQL uninstall scripts, all custom reporters should be dropped (cf. [the installation documentation](install.md)). In particular, when upgrading to a newer version of utPLSQL, one has to drop the custom reporters and recreate them after the upgrade. + +**Note:** +> It is possible, but cumbersome, to use another schema for storing the custom reporters. This requires to create a synonym for the base reporter type in the schema that is going to own the custom reporter, and to provide appropriate grants both to the owner of the custom reporter and to the user running the reporter. After upgrading or reinstalling utPLSQL, the extra privileges need to be recreated. This approach is not recommended. + +Assuming that the custom reporter type is created in the `UT3` schema, to run the tests using a custom reporter just call: `exec ut.run(ut3.custom_reporter_name());`, optionally providing parameter values to the `custom_reporter_name` constructor. + +One may get acquainted with the source code of the standard reporters bundled with utPLSQL (including the coverage reporters) by browsing the [`source/reporters/`](https://github.com/utPLSQL/utPLSQL/tree/develop/source/reporters) directory. The base reporter types `ut_reporter_base`, `ut_output_reporter_base` and `ut_console_reporter_base` are defined in [`source/core/types`](https://github.com/utPLSQL/utPLSQL/tree/develop/source/core/types). The base coverage reporter type `ut_coverage_reporter_base` is in [`source/core/coverage`](https://github.com/utPLSQL/utPLSQL/tree/develop/source/core/coverage). There are also two examples of custom reporters in [`examples/custom_reporters/`](https://github.com/utPLSQL/utPLSQL/tree/develop/examples/custom_reporters), both extending the functionality of `ut_documentation_reporter`: + +* `ut_custom_reporter` accepts an integer parameter `a_tab_size`; it alters the behaviour of `ut_documentation_reporter` by changing the size of the indentation according to the parameter value (by default the indentation is increased). +* `ut_expectations_reporter` accepts a `varchar2` parameter `a_report_all_expectations`; if its value is `'Y'` (which is the default), then the reporter shows the results of all expectations that are run. This stays in contrast with `ut_documentation_reporter`, which shows the results of all tests that are run, but only of the expectations that failed (keep in mind that a single test may consist of several expectations). From 3b003561e5f0a3eba46a4e4983e4970d9cc064aa Mon Sep 17 00:00:00 2001 From: Neil Barsema Date: Wed, 31 Aug 2022 11:21:34 +0200 Subject: [PATCH 076/187] Add explicit grants for public packages The privileges on the referenced packages are often revoked from PUBLIC as database hardening. Not relying on these grants being available makes the install script more robust. --- source/create_utplsql_owner.sql | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/create_utplsql_owner.sql b/source/create_utplsql_owner.sql index 1af2cf168..64bcb52ce 100644 --- a/source/create_utplsql_owner.sql +++ b/source/create_utplsql_owner.sql @@ -41,6 +41,11 @@ end; / grant execute on dbms_crypto to &ut3_owner_schema; +grant execute on dbms_lob to &ut3_owner_schema; +grant execute on dbms_xmlgen to &ut3_owner_schema; +grant execute on dbms_sql to &ut3_owner_schema; +grant execute on dbms_random to &ut3_owner_schema; + grant alter session to &ut3_owner_schema; From 4cdc7d424a8851b25b8c48bf15c22d6177c783d6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 9 Sep 2022 13:24:54 +0100 Subject: [PATCH 077/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index a465b7968..d5edb4d77 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 208f59141..ec84e3b88 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index a538b25f3..d1734ae77 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 6416b668a..53b96d4b1 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 7c71123d4..0985a7c28 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index ac712002c..93e5fba8a 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 8dd117676..00f0303e7 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index acfc0559f..04d24629b 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 303a1a6d7..fca2bcbc7 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 5a8cf3361..7ddbde478 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 65b9af484..9121fa721 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index c4dccfb51..4294ebd2a 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 56f4d573b..37dc6c163 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index f3f4f3c1c..ccb5fea24 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 0d3626a04..cc23ca67f 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 5946f70b0..22d1ce405 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 3d5b9d7ce..bde427999 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4021--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index bc5d28826..029bc17f3 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4021-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4036-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From b77ae3c119d58e4a0042eb7ac74f56d4fb3702c5 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 19 Sep 2022 13:49:16 +0300 Subject: [PATCH 078/187] Fixing utPLSQL-cli download script documentation --- docs/userguide/running-unit-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 22d1ce405..ca8ab0b4a 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -24,7 +24,7 @@ You may download the latest release of the command line client from [here](https ```bash #!/bin/bash # Get the url to latest release "zip" file -DOWNLOAD_URL=$(curl --silent https://api.github.com/repos/utPLSQL/utPLSQL-cli/releases/latest | awk '/zipball_url/ { print $2 }' | sed -r 's/"|,//g') +DOWNLOAD_URL=$(curl --silent https://api.github.com/repos/utPLSQL/utPLSQL-cli/releases/latest | awk '/browser_download_url/ { print $2 }' | grep ".zip\"" | sed 's/"//g') # Download the latest release "zip" file curl -Lk "${DOWNLOAD_URL}" -o utplsql-cli.zip # Extract downloaded "zip" file From 051c5257dd04c39561a23e7f403b778d43df094f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 19 Sep 2022 11:57:50 +0100 Subject: [PATCH 079/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index d5edb4d77..25d6fbf77 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index ec84e3b88..b860bf718 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index d1734ae77..5dad05ae0 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 53b96d4b1..2be6c96ac 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 0985a7c28..c770d7fe5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Introduction to utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 93e5fba8a..41511efed 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 00f0303e7..0f74c4692 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Annotations diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 04d24629b..422a294f0 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Best Practices diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index fca2bcbc7..430d2473e 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 7ddbde478..498ce88ef 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Exception handling and reporting diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 9121fa721..5762793b9 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Expectation concepts Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 4294ebd2a..3e5564e44 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 37dc6c163..2ba60144c 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index ccb5fea24..15f9952be 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Qyerying for test suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index cc23ca67f..b82ec7d32 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index ca8ab0b4a..7fa8263ad 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Running tests diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index bde427999..68256fa4f 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 029bc17f3..d25c365da 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4036-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4037-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From eb14593ac07e3f7a82f5bfdb4c2b8fb4a3ab3fdd Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Tue, 11 Oct 2022 22:32:46 +0300 Subject: [PATCH 080/187] Introducing MkDocs documentation --- mkdocs.yml | 74 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index f9a2687a8..e675c93f4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,17 +1,79 @@ # Format documented here # http://www.mkdocs.org/user-guide/configuration/ -site_name: utPLSQL +site_url: http://utPLSQL.org/ +site_name: utPLSQL-framework site_description: utPLSQL Ultimate Unit Testing Framework for Oracle PL/SQL -copyright: Copyright © 2016 - 2018 utPLSQL Team -repo_url: https://github.com/utPLSQL/utPLSQL -theme: mkdocs +copyright: Copyright © 2016 - 2022 utPLSQL Team +#repo_url: https://github.com/utPLSQL/utPLSQL # disable for offline docs +theme: + name: material + palette: + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/lightbulb-outline + name: Switch to dark mode + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/lightbulb + name: Switch to light mode + logo: assets/icon-transparent.png + favicon: assets/favicon.png + features: + - navigation.instant # disable for offline docs +# - navigation.indexes + - navigation.tabs + - navigation.tracking + - toc.follow + - toc.integrate + - search.suggest + - search.highlight +extra: +# homepage: http://jgebal.github.io/ +# homepage: http://utPLSQL.org/ + social: + - icon: fontawesome/brands/twitter + link: https://twitter.com/utPLSQL + - icon: fontawesome/brands/slack + link: https://join.slack.com/t/utplsql/shared_invite/zt-xwm68udy-4cF_3PNEyczYEbWr38W5ww + - icon: fontawesome/brands/github + link: https://github.com/utPLSQL + - icon: fontawesome/solid/envelope + link: mailto:utPLSQL@utPLSQL.org + consent: + title: Cookie consent + description: >- + We use cookies to recognize your repeated visits and preferences, as well + as to measure the effectiveness of our documentation and whether users + find what they're searching for. With your consent, you're helping us to + make our documentation better. + version: # disable for offline docs + provider: mike # disable for offline docs +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + - toc: + permalink: true use_directory_urls: false strict: true +plugins: + - search + - mike + - git-revision-date-localized: # disable for offline docs + enable_creation_date: true # disable for offline docs + type: datetime # disable for offline docs + nav: - - Home: index.md - User Guide: + - index.md - Installation: userguide/install.md - Getting Started: userguide/getting-started.md - Annotations: userguide/annotations.md @@ -23,8 +85,8 @@ nav: - Upgrade utPLSQL: userguide/upgrade.md - Reporting: - Using reporters: userguide/reporters.md - - Reporting errors: userguide/exception-reporting.md - Code coverage: userguide/coverage.md + - Error handling and reporting: userguide/exception-reporting.md - About: - Project Details: about/project-details.md - License: about/license.md From c5ce09bffbf02b7fd41681b0f43f6c97f0d65f4f Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Tue, 11 Oct 2022 22:50:22 +0300 Subject: [PATCH 081/187] Adjusting documentation to work well with new MkDocs --- docs/index.md | 34 ++++--------------- docs/userguide/annotations.md | 4 +-- docs/userguide/best-practices.md | 2 -- docs/userguide/coverage.md | 7 +++- docs/userguide/exception-reporting.md | 3 +- docs/userguide/expectations.md | 17 ++++++---- docs/userguide/getting-started.md | 28 ++++++++-------- docs/userguide/install.md | 47 ++++++++++++++------------- docs/userguide/querying_suites.md | 3 -- docs/userguide/reporters.md | 20 ++++++------ docs/userguide/running-unit-tests.md | 24 +++++++------- 11 files changed, 83 insertions(+), 106 deletions(-) diff --git a/docs/index.md b/docs/index.md index 0985a7c28..f9b648b43 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,39 +1,17 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Introduction to utPLSQL +## What is utPLSQL utPLSQL is a Unit Testing framework for Oracle PL/SQL. The framework follows industry standards and best patterns of modern Unit Testing frameworks like [JUnit](http://junit.org/junit4/) and [RSpec](http://rspec.info/) - - - User Guide - - [Installation](userguide/install.md) - - [Getting Started](userguide/getting-started.md) - - [Annotations](userguide/annotations.md) - - [Expectations](userguide/expectations.md) - - [Advanced data comparison](userguide/advanced_data_comparison.md) - - [Running unit tests](userguide/running-unit-tests.md) - - [Querying for test suites](userguide/querying_suites.md) - - [Testing best practices](userguide/best-practices.md) - - [Upgrade utPLSQL](userguide/upgrade.md) - - Reporting - - [Using reporters](userguide/reporters.md) - - [Reporting errors](userguide/exception-reporting.md) - - [Code coverage](userguide/coverage.md) - - [Cheat-sheet](https://www.cheatography.com/jgebal/cheat-sheets/utplsql-v3-1-2/#downloads) - - About - - [Project Details](about/project-details.md) - - [License](about/license.md) - - [Support](about/support.md) - - [Authors](about/authors.md) - - [Version 2 to Version 3 Comparison](compare_version2_to_3.md) - -# Demo project + +## Demo project Have a look at our [demo project](https://github.com/utPLSQL/utPLSQL-demo-project/). It uses [Travis CI](https://travis-ci.org/utPLSQL/utPLSQL-demo-project) to build on every commit, runs all tests, publishes test results and code coverage to [SonarCloud](https://sonarcloud.io/project/overview?id=utPLSQL:utPLSQL-demo-project). -# Three steps +## Three steps With just three simple steps you can define and run your unit tests for PLSQL code. @@ -48,7 +26,7 @@ Here is how you can simply create tested code, unit tests and execute the tests Check out the sections on [annotations](userguide/annotations.md) and [expectations](userguide/expectations.md) to see how to define your tests. -# Command line +## Command line You can use the utPLSQL command line client [utPLSQL-cli](https://github.com/utPLSQL/utPLSQL-cli) to run tests without the need for Oracle Client or any IDE like SQLDeveloper/TOAD etc. @@ -60,7 +38,7 @@ Amongst many benefits they provide ability to: Download the [latest client](https://github.com/utPLSQL/utPLSQL-cli/releases/latest) and you are good to go. See [project readme](https://github.com/utPLSQL/utPLSQL-cli/blob/develop/README.md) for details. -# Coverage +## Coverage If you want to have code coverage gathered on your code , it's best to use `ut_run` to execute your tests with multiple reporters and have both test execution report as well as coverage report saved to a file. diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 00f0303e7..0a9a2d15d 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,7 +1,5 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Annotations - Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. The framework runner searches for all the suitable annotated packages, automatically configures suites, forms the suite hierarchy, executes it and reports results in specified formats. @@ -38,7 +36,7 @@ There **can not** be any empty lines or comments between annotation line and pro There can be many annotations for a procedure. Valid procedure annotations example: -```sql +```sql linenums="1" package test_package is --%suite diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 04d24629b..a1924b8de 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,7 +1,5 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Best Practices - The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. ## Test Isolation and Dependency diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index fca2bcbc7..7d77cb7ed 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,8 +1,8 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Coverage utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: + * package bodies * type bodies * triggers @@ -15,6 +15,7 @@ Code coverage is gathered for the following source types: To obtain information about code coverage for unit tests, run utPLSQL with one of built-in code coverage reporters. The following code coverage reporters are supplied with utPLSQL: + * `ut_coverage_html_reporter` - generates a HTML coverage report providing summary and detailed information on code coverage. The HTML reporter is based on the open-source [simplecov-html](https://github.com/colszowka/simplecov-html) reporter for Ruby. It includes source code of the code that was covered (if the code is accessible for test user) * `ut_coveralls_reporter` - generates a [Coveralls compatible JSON](https://coveralls.zendesk.com/hc/en-us/articles/201774865-API-Introduction) coverage report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by cloud services like [Coveralls](https://coveralls.io) * `ut_coverage_sonar_reporter` - generates a [Sonar Compatible XML](https://docs.sonarqube.org/latest/analysis/generic-test/) coverage report providing detailed information on code coverage with line numbers. This coverage report is designed to be consumed by services like [SonarQube](https://www.sonarqube.org/) and [SonarCloud](https://about.sonarcloud.io/) @@ -23,6 +24,7 @@ The following code coverage reporters are supplied with utPLSQL: ## Security model utPLSQL code coverage uses DBMS_PROFILER to gather information about the execution of code under test and therefore follows the [DBMS_PROFILER's Security Model](https://docs.oracle.com/database/121/ARPLS/d_profil.htm#ARPLS67465). In order to be able to gather coverage information, the user executing unit tests needs to be either: + * The owner of the code that is being tested * Have the following privileges to be able to gather coverage on code owned by other users: * `create any procedure` system privilege @@ -144,6 +146,7 @@ You may specify both _include_ and _exclude_ options to gain more control over w **Important notes** The order of priority is for evaluation of include/exclude filter parameters is as follows. + - if `a_source_file_mappings` is defined then all include/exclude parameters are ignored (see section below for usage of `a_source_file_mappings` parameter ) - else if `a_include_schema_expr` or `a_include_object_expr` parameter is specified then parameters `a_coverage_schemes` and `a_include_objects` are ignored - else if `a_include_objects` is specified then the coverage is gathered only on specified database objects. @@ -300,6 +303,7 @@ They are abstracted from database, schema names, packages, procedures and functi To be able to effectively use reporters dedicated for those tools, utPLSQL provides functionality for mapping database object names to project files. There are a few significant differences when running coverage on project files compared to running coverage on schema(s). + - Coverage is only reported on objects that were successfully mapped to project files. - Project files (database objects) that were not executed at all are not reported as fully uncovered. It is up to the consumer (Sonar/Coveralls) to determine if project file should be considered as 0% coverage or just ignored. @@ -335,6 +339,7 @@ C: ``` By default, utPLSQL will convert file paths into database objects using the following regular expression `/(((\w|[$#])+)\.)?((\w|[$#])+)\.(\w{3})$` + - object owner (if it is present) is identified by the expression in the second set of brackets - object name is identified by the expression in the fourth set of brackets - object type is identified by the expression in the sixth set of brackets diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 7ddbde478..b4cb033e7 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,12 +1,11 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Exception handling and reporting - The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. To achieve rerunability, the package state invalidation exceptions (ORA-04068, ORA-04061) are not handled and test execution will be interrupted if such exceptions are encountered. This is because of how Oracle behaves on those exceptions. Test execution can fail for different reasons. The failures on different exceptions are handled as follows: + * A test package without body - each `--%test` is reported as failed with exception, nothing is executed * A test package with _invalid body_ - each `--%test` is reported as failed with exception, nothing is executed * A test package with _invalid spec_ - package is not considered a valid unit test package and is excluded from execution. When trying to run a test package with invalid spec explicitly, exception is raised. Only valid specifications are parsed for annotations diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 9121fa721..5856b77a1 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,6 +1,7 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Expectation concepts +## Expectation concepts + Validation of the code under test (the tested logic of procedure/function etc.) is performed by comparing the actual data against the expected data. utPLSQL uses expectations and matchers to perform the check on the data. @@ -82,12 +83,14 @@ SUCCESS **Note:** > The examples in the document will be only using shortcut syntax, to keep the document brief. -# Using expectations +## Using expectations + There are two ways to use expectations: - by invoking utPLSQL framework to execute suite(s) of utPLSQL tests - without invoking the utPLSQL framework - running expectations standalone ## Running expectations within utPLSQL framework + When expectations are ran as a part of a test suite, the framework tracks: - status of each expectation - outcomes (messages) produced by each expectation @@ -166,7 +169,7 @@ When expectations are invoked outside of utPLSQL framework the outputs from expe **Note:** > The examples in the document will be only using standalone expectations, to keep the document brief. -# Matchers +## Matchers utPLSQL provides the following matchers to perform checks on the expected and actual values. - `be_between( a_upper_bound {data-type}, a_lower_bound {data-type} )` @@ -312,7 +315,7 @@ FAILURE ``` Since NULL is neither *true* nor *false*, both expectations will report failure. -# Supported data types +## Supported data types The matrix below illustrates the data types supported by different matchers. @@ -336,7 +339,7 @@ The matrix below illustrates the data types supported by different matchers. | **be_within().of_()** | | | | X | X | X | X | X | | | | | | | | | **be_within_pct().of_()** | | | | | X | | | | | | | | | | | -# Expecting exceptions +## Expecting exceptions Testing is not limited to checking for happy-path scenarios. When writing tests, you often want to validate that in specific scenarios, an exception is thrown. @@ -385,7 +388,7 @@ Finished in .009229 seconds For more details see documentation of the [`--%throws` annotation.](annotations.md#throws-annotation) -# Matchers +## Matchers You can choose different matchers to validate that your PL/SQL code is working as expected. @@ -1747,7 +1750,7 @@ FAILURE at "anonymous block", line 32 ``` -# Comparing Json objects +## Comparing Json objects utPLSQL is capable of comparing json data-types of `json_element_t` **on Oracle 12.2 and above**, and also `json` **on Oracle 21 and above** diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 4294ebd2a..42b6b3641 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -7,7 +7,7 @@ utPLSQL is designed in a way that allows you to follow Below is an example of building a simple function with TDD. -# Gather requirements +## Gather requirements We have a requirement to build a function that will return a substring of a string that is passed to the function. @@ -17,12 +17,12 @@ The function should accept three parameters: - start_position - end_position -# Create a test +## Create a test We will start from the bare minimum and move step by step, executing tests every time we make minimal progress. This way, we assure we don't jump ahead too much and produce code that is untested or untestable. -## Create test package +### Create test package ```sql create or replace package test_betwnstr as @@ -43,7 +43,7 @@ Finished in .451423 seconds 0 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s) ``` -## Define specification for the test +### Define specification for the test ```sql create or replace package test_betwnstr as @@ -76,7 +76,7 @@ Finished in .509673 seconds Well our test is failing as the package specification requires a body. -## Define body of first test +### Define body of first test ```sql create or replace package body test_betwnstr as @@ -110,9 +110,9 @@ Finished in .415851 seconds Our test is failing as the test suite package body is invalid. Looks like we need to define the function we want to test. -# Implement code to fulfill the requirement +## Implement code to fulfill the requirement -## Define tested function +### Define tested function ```sql create or replace function betwnstr( a_string varchar2, a_start_pos integer, a_end_pos integer ) return varchar2 @@ -143,7 +143,7 @@ Finished in .375178 seconds So now we see that our test works but the function does not return the expected results. Let us fix this and continue from here. -## Fix the tested function +### Fix the tested function The function returned a string one character short, so we need to add 1 to the substr parameter. @@ -169,14 +169,14 @@ Finished in .006077 seconds So our test is now passing, great! -# Refactor +## Refactor Once our tests are passing, we can safely refactor (restructure) the code as we have a safety harness in place to ensure that after the restructuring and cleanup of the code, everything is still working. One thing worth mentioning is that refactoring of tests is as important as refactoring of code. Maintainability of both is equally important. -# Further requirements +## Further requirements It seems like our work is done. We have a function that returns a substring from start position to end position. As we move through the process of adding tests, it's very important to think about edge cases. @@ -195,7 +195,7 @@ Here is a list of edge cases for our function: We should define expected behavior for each of these edge cases. Once defined we can start implementing tests for those behaviors and adjust the tested function to meet the requirements specified in the tests. -## Add test for additional requirement +### Add test for additional requirement A new requirement was added: Start position zero - should be treated as start position one @@ -250,7 +250,7 @@ Finished in .232584 seconds Looks like our function does not work as expected for zero start position. -## Implementing the requirement +### Implementing the requirement Let's fix our function so that the new requirement is met @@ -281,7 +281,7 @@ Finished in .012718 seconds Great! We have made some visible progress. -## Refactoring +### Refactoring When all tests are passing we can proceed with a safe cleanup of our code. @@ -308,7 +308,7 @@ Finished in .013739 seconds 2 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s) ``` -# Remaining requirements +## Remaining requirements You may continue on with the remaining edge cases from here. diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 37dc6c163..dce1a2e2e 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,8 +1,9 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Supported database versions +## Supported database versions utPLSQL is continuously tested against following versions of Oracle databases + * 11g R2 * 12c * 12c R2 @@ -11,17 +12,17 @@ utPLSQL is continuously tested against following versions of Oracle databases We do our best to assure full compatibility with supported versions of Oracle databases [See](http://www.oracle.com/us/support/library/lifetime-support-technology-069183.pdf#page=6) -# Requirements +## Requirements utPLSQL will run on any Oracle Database version 11g relase 2 or above. -## Licensed features required +### Licensed features required utPLSQL doesn't require any extra licensed features of Oracle database. It can be installed on any Standard Edition Oracle Database. In fact, it even supports Oracle 11g XE which is a free Oracle Database version with minimal features and storage limits. -## Storage requirements +### Storage requirements utPLSQL will use tablespace for the following: - storage of annotation cache @@ -38,9 +39,9 @@ Profiler results may require regular purging to assure low space consumption. utPLSQl does not purge profiler tables as those tables can can be shared with other tools. -# Downloading utPLSQL +## Downloading utPLSQL -## Manual download +### Manual download - Go to GitHub releases page for utPLSQL [`https://github.com/utPLSQL/utPLSQL/releases`](https://github.com/utPLSQL/utPLSQL/releases) - Choose the version to download - latest is always greatest @@ -51,13 +52,13 @@ utPLSQl does not purge profiler tables as those tables can can be shared with ot The files have identical content but use different compression (tar / zip ) so choose whichever you prefer depending on your platform (Win/Mac/Unix/Linux). -## Scripted download of latest utPLSQL version +### Scripted download of latest utPLSQL version The below snippets can be used to download latest version of utPLSQL from github releases. After downloading follow the installation instructions in next sections of this document. -### Unix/Linux +#### Unix/Linux ```bash #!/bin/bash @@ -75,7 +76,7 @@ You may download with a one-liner if that is more convenient. curl -LOk $(curl --silent https://api.github.com/repos/utPLSQL/utPLSQL/releases/latest | awk '/browser_download_url/ { print $2 }' | grep ".zip\"" | sed 's/"//g') ``` -### Windows +#### Windows To run the script on windows you will need [PowerShell 3.0](https://blogs.technet.microsoft.com/heyscriptingguy/2013/06/02/weekend-scripter-install-powershell-3-0-on-windows-7/) or above. You will also need .NET 4.0 Framework or above. @@ -104,7 +105,7 @@ foreach ($i in $urlList) { } ``` -# Headless installation +## Headless installation utPLSQL can be installed with DDL trigger, to enable tracking of DDL changes to your unit test packages. This is the recommended installation approach, when you want to compile and run unit test packages in a schema containing huge amount of database packages (for example Oracle EBS installation schema). @@ -136,7 +137,7 @@ For Oracle 11g following users are excluded: > select username from all_users where oracle_maintained='Y'; >``` -## Installation without DDL trigger +### Installation without DDL trigger To install the utPLSQL into a new database schema and grant it to public, execute the script `install_headless.sql` as SYSDBA. @@ -152,7 +153,7 @@ cd source sqlplus sys/sys_pass@db as sysdba @install_headless.sql utp3 my_verySecret_password utp3_tablespace ``` -## Installation with DDL trigger +### Installation with DDL trigger To install the utPLSQL into a new database schema and grant it to public, execute the script `install_headless_with_trigger.sql` as SYSDBA. @@ -168,7 +169,7 @@ cd source sqlplus sys/sys_pass@db as sysdba @install_headless_with_trigger.sql utp3 my_verySecret_password utp3_tablespace ``` -# Recommended Schema +## Recommended Schema It is highly recommended to install utPLSQL in it's own schema. You are free to choose any name for this schema. Installing uPLSQL into a shared schema is really not recommended as you loose isolation of framework. @@ -190,9 +191,9 @@ utPLSQL is using [DBMS_PROFILER tables](https://docs.oracle.com/cd/E18283_01/app It is up to DBA to maintain the storage of the profiler tables. -# Manual installation procedure +## Manual installation procedure -## Creating schema for utPLSQL +### Creating schema for utPLSQL To create the utPLSQL schema and grant all the required privileges execute script `create_utplsql_owner.sql` from the `source` directory with parameters: - `user name` - the name of the user that will own of utPLSQL object @@ -205,7 +206,7 @@ cd source sqlplus sys/sys_password@database as sysdba @create_utPLSQL_owner.sql ut3 ut3 users ``` -## Installing utPLSQL +### Installing utPLSQL To install the utPLSQL framework into your database, go to `source` directory, run the `install.sql` providing the `schema_name` for utPLSQL as parameter. Schema must be created prior to calling the `install` script. You may install utPLSQL from any account that has sufficient privileges to create objects in other users schema. @@ -216,7 +217,7 @@ cd source sqlplus admin/admins_password@database @install.sql ut3 ``` -## Installing DDL trigger +### Installing DDL trigger To minimize startup time of utPLSQL framework (especially on a database with large schema) it is recommended to install utPLSQL DDL trigger to enable utPLSQL annotation to be updated at compile-time. It's recommended to install DDL trigger when connected as `SYSDBA` user. Trigger is created in utPLSQL schema. @@ -235,7 +236,7 @@ sqlplus admin/admins_password@database @install_ddl_trigger.sql ut3 >Trigger can be installed ant any point in time. -## Allowing other users to access the utPLSQL framework +### Allowing other users to access the utPLSQL framework In order to allow other users to access utPLSQL, synonyms must be created and privileges granted. You have two options: @@ -264,7 +265,7 @@ The following tools that support the SQL*Plus commands can be used to run the in - [SQLcl](http://www.oracle.com/technetwork/developer-tools/sqlcl/overview/index.html) - [Oracle SQL Developer](http://www.oracle.com/technetwork/developer-tools/sql-developer/overview/index.html) -# Checking environment and utPLSQL version +## Checking environment and utPLSQL version To check the framework version execute the following query: ```sql @@ -278,7 +279,7 @@ select from dual; ``` -# Additional requirements +## Additional requirements In order to use the Code Coverage functionality of utPLSQL, users executing the tests must have the CREATE privilege on the PLSQL code that the coverage is gathered on. This is a requirement of [DBMS_PROFILER package](https://docs.oracle.com/cd/E18283_01/appdev.112/e16760/d_profil.htm#i999476). @@ -286,7 +287,7 @@ This is a requirement of [DBMS_PROFILER package](https://docs.oracle.com/cd/E182 In practice, user running tests for PLSQL code that he does not own, needs to have CREATE ANY PROCEDURE/CREATE ANY TRIGGER privileges. Running code coverage on objects that the user does not own will **not produce any coverage information** without those privileges. -# Uninstalling utPLSQL +## Uninstalling utPLSQL To uninstall run `uninstall.sql` and provide `schema_name` where utPLSQL is installed. @@ -308,11 +309,11 @@ i.e. the uninstall script provided with version 3.1.11 will not work correctly Alternatively you can drop the user that owns utPLSQL and re-create it using headless install. -# Version upgrade +## Version upgrade Currently, the only way to upgrade version of utPLSQL v3.0.0 and above is to remove the previous version and install the new version. -# Working with utPLSQL v2 +## Working with utPLSQL v2 If you are using utPLSQL v2, you can still install utPLSQL v3. The only requirement is that utPLSQL v3 needs to be installed in a different schema than utPLSQL v2. diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index ccb5fea24..317b9c766 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,8 +1,5 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Qyerying for test suites - - ## Obtaining information about suites utPLSQL framework provides ability to read inforamtion about unit test suites that exist in a schema. diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index cc23ca67f..08d7252d1 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -2,7 +2,7 @@ utPLSQL provides the following reporting formats. -# Documentation reporter +## Documentation reporter The `ut_documentation_reporter` is the default reporting format used by the framework. It provides a human readable test results. @@ -26,7 +26,7 @@ The documentation report provides the following information. - Summary with total number of tests, number of tests with status and timing for the execution -## Color output from documentation reporter +### Color output from documentation reporter When invoking tests with documentation reporter and your command line supports ANSICONSOLE (default on Unix) [available for Windows](http://adoxa.altervista.org/ansicon/), you can obtain the coloured outputs from the documentation reporter. @@ -41,7 +41,7 @@ Example outputs from documentation reporter. ![doc_reporter_outputs](../images/documentation_reporter_color.png) -# JUnit reporter +## JUnit reporter Most of continuous integration servers (like Jenkins) are capable of consuming unit test execution results in [JUnit](https://en.wikipedia.org/wiki/JUnit) format. The `ut_junit_reporter` in earlier version referred as `ut_xunit_reporter` is producing outcomes as JUnit-compatible XML unit test report, that can be used by CI servers to display their custom reports and provide metrics (like tests execution trends). @@ -63,7 +63,7 @@ Example of failure report details -# Teamcity reporter +## Teamcity reporter [Teamcity](https://www.jetbrains.com/teamcity/) is a CI server by Jetbrains. It supports JUnit reporting and additionally has it's own format of reporting that allows tracking of progress of a CI step/task as it executes. The TeamCity format developed by Jetbrains is supported by utPLSQL with `ut_teamcity_reporter`. @@ -83,7 +83,7 @@ Example of failure report details ![junit_reporter_outputs_errors](../images/teamcity_report_example_errors.png) -# Sonar test reporter +## Sonar test reporter If you are using [SonarQube](https://www.sonarqube.org/) or [SonarCloud](https://about.sonarcloud.io/) to do static code analysis for you PLSQL projects, your code analysis can benefit from code coverage and test results. utPLSQL provides two reporters to for SonarQube: - `ut_sonar_test_reporter` - provides an XML output of each test executed per each project test file (package) @@ -99,7 +99,7 @@ Providing invalid paths or paths to non-existing files will result in failure wh For details on how to invoke reporter with paths, see the **Coverage reporters** section. -# TFS / VSTS Reporter +## TFS / VSTS Reporter If you are using [TFS](https://www.visualstudio.com/tfs/) or [VSTS](https://www.visualstudio.com/team-services/) to do static code analysis for you PLSQL projects and run builds, your code analysis can benefit from code coverage and test results. TFS reporter is designed specifically to [work with Microsoft Team Fundation Server](https://docs.microsoft.com/en-us/vsts/build-release/tasks/test/publish-test-results?view=vsts) report format which is very old version of [JUnit](https://github.com/windyroad/JUnit-Schema/blob/master/JUnit.xsd). Main diffrence between standard JUnit is that elements cannot be nested and attribute skipped is not present. @@ -117,12 +117,12 @@ Details: ![tfs_junit_reporter_outputs](../images/tfs_details.png) -# Coverage reporters +## Coverage reporters utPLSQL comes with a set of build-in coverage reporters. Have a look into the [coverage documentation](coverage.md) to learn more about them. -# Debug reporter +## Debug reporter The `ut_debug_reporter` provides a highly verbose output containing thorough details about framework and test execution. @@ -161,11 +161,11 @@ Some of the information in debug log might be redundant. > - db object names > - etc. -# Custom reporters +## Custom reporters It is possible to add your own reporters by creating an appropriate object type. In principle, it has to be a subtype of `ut_reporter_base`. However, if the reporter is expected to produce output consumable by a client oustside of the database (e.g. the data has to be reported to the screen or to a file), then you should base it on `ut_output_reporter_base` (which is a subtype of `ut_reporter_base`). In contrast, if you would like to create a reporter that, for example, saves the data to a database table, then it should be based directly on `ut_reporter_base`. (Currently, all reporters in the utPLSQL framework are based on `ut_output_reporter_base`.) Coverage reporters are based on `ut_coverage_reporter_base` (a subtype of `ut_output_reporter_base`). -If need to produce a colored text output from the custom reporter, then you can build it basing on `ut_console_reporter_base` (a subtype of `ut_output_reporter_base`). In many cases it may also be more convenient to create the custom reporter type under a more specialized type, like `ut_documentation_reporter` or `ut_junit_reporter`, and override just some of the functionality. +If you need to produce a colored text output from the custom reporter, then you can build it basing on `ut_console_reporter_base` (a subtype of `ut_output_reporter_base`). In many cases it may also be more convenient to create the custom reporter type under a more specialized type, like `ut_documentation_reporter` or `ut_junit_reporter`, and override just some of the functionality. It is recommended to create the reporter type in the schema where utPLSQL is installed (by default it is the `UT3` schema). Note that before running the utPLSQL uninstall scripts, all custom reporters should be dropped (cf. [the installation documentation](install.md)). In particular, when upgrading to a newer version of utPLSQL, one has to drop the custom reporters and recreate them after the upgrade. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index ca8ab0b4a..bfaa287c7 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,7 +1,5 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4036--develop-blue.svg) -# Running tests - utPLSQL framework provides two main entry points to run unit tests from within the database: - `ut.run` procedures and functions @@ -10,7 +8,7 @@ utPLSQL framework provides two main entry points to run unit tests from within t These two entry points differ in purpose and behavior. Most of the time you will want to use `ut.run` as `ut_runner.run` is designed for API integration and does not display the results to the screen. -# Running from CI servers and command line +## Running from CI servers and command line The best way to run your tests from CI server or command line is to use the [utPLSQL-cli](https://github.com/utPLSQL/utPLSQL-cli) command line client. @@ -32,7 +30,7 @@ unzip -q utplsql-cli.zip ``` -# ut.run +## ut.run The `ut` package contains overloaded `run` procedures and functions. The `run` API is designed to be called directly by a developer when using an IDE/SQL console to execute unit tests. @@ -42,7 +40,7 @@ A single line call is enough to execute a set of tests from one or more schemes. The **procedures** execute the specified tests and produce output to DBMS_OUTPUT using the specified reporter. The **functions** can only be used in SELECT statements. They execute the specified tests and produce outputs as a pipelined data stream to be consumed by a select statement. -## ut.run procedures +### ut.run procedures The examples below illustrate different ways and options to invoke `ut.run` procedures. You can use a wildcard character `*` to call tests by part of their name or to call tests that are located on paths matched by part of path string. @@ -179,7 +177,7 @@ Executes all tests from package _HR.TEST_APPLY_BONUS_ and provide outputs to DBM For details on build-in reporters look at [reporters documentation](reporters.md). -## ut.run functions +### ut.run functions The `ut.run` functions provide exactly the same functionality as the `ut.run` procedures. You may use the same sets of parameters with both functions and procedures. @@ -195,7 +193,7 @@ Example. select * from table(ut.run('hr.test_apply_bonus', ut_junit_reporter())); ``` -# ut_runner.run procedures +## ut_runner.run procedures The `ut_runner` package provides an API for integrating utPLSQL with other products. Maven, Jenkins, SQL Develper, PL/SQL Developer, TOAD and others can leverage this API to call utPLSQL. @@ -262,16 +260,16 @@ select ``` -# Order of test execution +## Order of test execution -## Default order +### Default order When unit tests are executed without random order, they are ordered by: - schema name - suite path or test package name if `--%suitepath` was not specified for that package - `--%test` line number in package -## Random order +### Random order You can force a test run to execute tests in random order by providing one of options to `ut.run`: - `a_random_test_order` - true/false for procedures and 1/0 for functions @@ -317,7 +315,7 @@ select * from table(ut.run('hr.test_apply_bonus', a_random_test_order_seed => 30 **Note** >Random order seed must be a positive number within range of 1 .. 1 000 000 000. -# Run by Tags +## Run by Tags In addition to the path, you can filter the tests to be run by specifying tags. Tags are defined in the test / context / suite with the `--%tags`-annotation ([Read more](annotations.md#tags)). Multiple tags are separated by comma. @@ -338,7 +336,7 @@ You can also exclude specific tags by adding a `-` (dash) in front of the tag select * from table(ut.run('hr.test_apply_bonus', a_tags => '-suite1')) ``` -# Keeping uncommitted data after test-run +## Keeping uncommitted data after test-run utPLSQL by default runs tests in autonomous transaction and performs automatic rollback to assure that tests do not impact one-another and do not have impact on the current session in your IDE. @@ -359,7 +357,7 @@ end; **Note:** >This option is not available when running tests using `ut.run` as a table function. -# Reports character-set encoding +## Reports character-set encoding To get properly encoded reports, when running utPLSQL with HTML/XML reports on data containing national characters you need to provide your client character set when calling `ut.run` functions and procedures. From 9afa968557aecfad696767f0301785df75e87744 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 12 Oct 2022 00:33:51 +0300 Subject: [PATCH 082/187] Adjusting MkDocs configuration --- mkdocs.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index e675c93f4..f88e451f0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,11 +1,12 @@ # Format documented here # http://www.mkdocs.org/user-guide/configuration/ +# https://squidfunk.github.io/mkdocs-material/getting-started/ site_url: http://utPLSQL.org/ site_name: utPLSQL-framework -site_description: utPLSQL Ultimate Unit Testing Framework for Oracle PL/SQL +site_description: utPLSQL Ultimate Testing Framework for Oracle PL/SQL & SQL copyright: Copyright © 2016 - 2022 utPLSQL Team -#repo_url: https://github.com/utPLSQL/utPLSQL # disable for offline docs +repo_url: https://github.com/utPLSQL/utPLSQL theme: name: material palette: @@ -70,7 +71,7 @@ plugins: - git-revision-date-localized: # disable for offline docs enable_creation_date: true # disable for offline docs type: datetime # disable for offline docs - + nav: - User Guide: - index.md @@ -81,7 +82,7 @@ nav: - Advanced data comparison: userguide/advanced_data_comparison.md - Running unit tests: userguide/running-unit-tests.md - Querying for test suites: userguide/querying_suites.md - - Testing best pracitces: userguide/best-practices.md + - Testing best practices: userguide/best-practices.md - Upgrade utPLSQL: userguide/upgrade.md - Reporting: - Using reporters: userguide/reporters.md From 169d3b259ff1eb7b05f0baadf53ed5d197ca3509 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 14 Oct 2022 23:11:01 +0300 Subject: [PATCH 083/187] Added color stylesheet for mkdocs --- docs/stylesheets/extra.css | 12 ++++++++++++ mkdocs.yml | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 docs/stylesheets/extra.css diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 000000000..7f05ab831 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,12 @@ +[data-md-color-scheme="default"] { + --md-primary-fg-color: #2f8bff; + --md-accent-fg-color: #1f5db0; + --md-accent-fg-color--transparent: #1f5db0; +} + +[data-md-color-scheme="slate"] { + --md-hue: 200; + --md-primary-fg-color: #2f8bff; + --md-accent-fg-color: #1f5db0; + --md-accent-fg-color--transparent: #1f5db0; +} diff --git a/mkdocs.yml b/mkdocs.yml index f88e451f0..ffa090034 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -6,7 +6,8 @@ site_url: http://utPLSQL.org/ site_name: utPLSQL-framework site_description: utPLSQL Ultimate Testing Framework for Oracle PL/SQL & SQL copyright: Copyright © 2016 - 2022 utPLSQL Team -repo_url: https://github.com/utPLSQL/utPLSQL +extra_css: + - stylesheets/extra.css theme: name: material palette: @@ -60,6 +61,9 @@ markdown_extensions: - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.superfences + - pymdownx.caret + - pymdownx.mark + - pymdownx.tilde - toc: permalink: true use_directory_urls: false From 1e710da8cdcac43ff18a202af3f5d6edcb1970f7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 14 Oct 2022 21:22:21 +0100 Subject: [PATCH 084/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 25d6fbf77..b376d5d4c 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index b860bf718..2e50760e4 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 5dad05ae0..dc6d9e59d 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 2be6c96ac..fd0cfce15 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 8bce25886..eeaf1b002 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 41511efed..9805b2b13 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 83fe89885..e36e37d70 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 4ed6f48be..6e3d1f0c7 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 01c27981d..453f2f794 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 362d60d3b..1aa179680 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 25b304cdf..8744077fa 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 1b6dcab3c..99409fd95 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 8c35d4ca5..bcab40387 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 46da230a4..bd3eea917 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index f55e77e88..94c13908a 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index b8fe358c5..f20d8722c 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 68256fa4f..461702a47 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4037--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index d25c365da..08a6d95c7 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4037-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4041-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 519f06b8bca56d8a7c4166b728ae0c48392d3a23 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 14 Oct 2022 23:45:08 +0300 Subject: [PATCH 085/187] Adding back repo-url --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index ffa090034..8543b4030 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -6,6 +6,7 @@ site_url: http://utPLSQL.org/ site_name: utPLSQL-framework site_description: utPLSQL Ultimate Testing Framework for Oracle PL/SQL & SQL copyright: Copyright © 2016 - 2022 utPLSQL Team +repo_url: https://github.com/utPLSQL/utPLSQL extra_css: - stylesheets/extra.css theme: From e1690f0dd2b522464129cfa063ff544bb6b91a1d Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 18 Aug 2022 21:19:12 +0300 Subject: [PATCH 086/187] Exclude Unit Test packages from coverage --- source/core/coverage/ut_coverage.pkb | 2 +- test/ut3_tester_helper/coverage_helper.pkb | 15 +++++++++++++++ .../test_coverage/test_extended_coverage.pkb | 16 ++++++++-------- .../test_coverage/test_proftab_coverage.pkb | 1 + 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index f5eccc893..2f38803ad 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -167,7 +167,7 @@ create or replace package body ut_coverage is begin if not is_develop_mode() then --skip all the utplsql framework objects and all the unit test packages that could potentially be reported by coverage. - l_skip_objects := coalesce(ut_utils.get_utplsql_objects_list(),ut_object_names()); + l_skip_objects := coalesce( ut_utils.get_utplsql_objects_list() multiset union all ut_suite_manager.get_schema_ut_packages(a_coverage_options.schema_names) , ut_object_names() ); end if; --Regex exclusion override the standard exclusion objects. diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index fdfa32364..99f26e9f8 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -48,6 +48,20 @@ create or replace package body coverage_helper is end; end;]'; + execute immediate q'[create or replace package ut3_develop.some_other_package is + procedure do_stuff(i_input in number); + end;]'; + + execute immediate q'[create or replace package body ut3_develop.some_other_package is + procedure do_stuff(i_input in number) is + begin + if i_input = 2 then dbms_output.put_line('should not get here'); elsif i_input = 1 then dbms_output.put_line('should get here'); + else + dbms_output.put_line('should not get here'); + end if; + end; + end;]'; + execute immediate q'[create or replace package ut3_develop.test_dummy_coverage is --%suite(dummy coverage test) --%suitepath(coverage_testing) @@ -77,6 +91,7 @@ create or replace package body coverage_helper is pragma autonomous_transaction; begin begin execute immediate q'[drop package ut3_develop.test_dummy_coverage]'; exception when others then null; end; + begin execute immediate q'[drop package ut3_develop.some_other_package]'; exception when others then null; end; begin execute immediate q'[drop package ut3_develop.]'||covered_package_name; exception when others then null; end; end; diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb index 3c8781bc4..af029e254 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb @@ -113,9 +113,9 @@ create or replace package body test_extended_coverage is begin --Arrange l_expected := '%' || - '%%'; + '%%'; l_not_expected := '%' || - '%%'; + '%%'; --Act l_actual := ut3_tester_helper.coverage_helper.run_tests_as_job( @@ -140,9 +140,9 @@ create or replace package body test_extended_coverage is begin --Arrange l_expected := '%' || - '%%'; + '%%'; l_not_expected := '%' || - '%%'; + '%%'; --Act l_actual := ut3_tester_helper.coverage_helper.run_tests_as_job( @@ -167,9 +167,9 @@ create or replace package body test_extended_coverage is begin --Arrange l_expected := '%' || - '%%'; + '%%'; l_not_expected := '%' || - '%%'; + '%%'; --Act l_actual := ut3_tester_helper.coverage_helper.run_tests_as_job( @@ -194,9 +194,9 @@ create or replace package body test_extended_coverage is begin --Arrange l_expected := '%' || - '%%'; + '%%'; l_not_expected := '%' || - '%%'; + '%%'; --Act l_actual := ut3_tester_helper.coverage_helper.run_tests_as_job( diff --git a/test/ut3_user/reporters/test_coverage/test_proftab_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_proftab_coverage.pkb index 7cad0a67e..f3aad5702 100644 --- a/test/ut3_user/reporters/test_coverage/test_proftab_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_proftab_coverage.pkb @@ -66,6 +66,7 @@ create or replace package body test_proftab_coverage is ); --Assert ut.expect(l_actual).to_be_like(l_expected); + ut.expect(l_actual).not_to_be_like('%%'); end; procedure coverage_for_file is From 8ac32d7b2fae363924f22f84e685f30c6e62fdc4 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Tue, 6 Sep 2022 23:34:30 +0300 Subject: [PATCH 087/187] Exclude Unit Test packages from coverage --- source/core/coverage/ut_coverage.pkb | 2 +- source/core/ut_suite_manager.pkb | 16 ++++++++++++---- source/core/ut_suite_manager.pks | 2 +- test/ut3_tester_helper/run_helper.pkb | 2 +- .../test_coverage/test_extended_coverage.pkb | 9 +++++---- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/source/core/coverage/ut_coverage.pkb b/source/core/coverage/ut_coverage.pkb index 2f38803ad..7eb5a34c2 100644 --- a/source/core/coverage/ut_coverage.pkb +++ b/source/core/coverage/ut_coverage.pkb @@ -167,7 +167,7 @@ create or replace package body ut_coverage is begin if not is_develop_mode() then --skip all the utplsql framework objects and all the unit test packages that could potentially be reported by coverage. - l_skip_objects := coalesce( ut_utils.get_utplsql_objects_list() multiset union all ut_suite_manager.get_schema_ut_packages(a_coverage_options.schema_names) , ut_object_names() ); + l_skip_objects := coalesce( ut_utils.get_utplsql_objects_list() multiset union all ut_suite_manager.get_schema_ut_packages(a_coverage_options.schema_names, a_coverage_options.include_schema_expr) , ut_object_names() ); end if; --Regex exclusion override the standard exclusion objects. diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 805fd608b..86f68c076 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -493,13 +493,21 @@ create or replace package body ut_suite_manager is return l_suites; end; - function get_schema_ut_packages(a_schema_names ut_varchar2_rows) return ut_object_names is + function get_schema_ut_packages(a_schema_names ut_varchar2_rows, a_schema_name_expr varchar2) return ut_object_names is + l_schema_names ut_varchar2_rows := a_schema_names; begin - for i in 1 .. a_schema_names.count loop - refresh_cache(a_schema_names(i)); + if a_schema_name_expr is not null then + select username + bulk collect into l_schema_names + from all_users + where regexp_like(username,a_schema_name_expr,'i'); + end if; + + for i in 1 .. l_schema_names.count loop + refresh_cache(l_schema_names(i)); end loop; - return ut_suite_cache_manager.get_cached_packages( a_schema_names ); + return ut_suite_cache_manager.get_cached_packages( l_schema_names ); end; function get_schema_names(a_paths ut_varchar2_list) return ut_varchar2_rows is diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index 170b83f05..65b3c0654 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -30,7 +30,7 @@ create or replace package ut_suite_manager authid current_user is * @param a_schema_names list of schemas to return the information for * @return array containing unit test schema and object names */ - function get_schema_ut_packages(a_schema_names ut_varchar2_rows) return ut_object_names; + function get_schema_ut_packages(a_schema_names ut_varchar2_rows, a_schema_name_expr varchar2) return ut_object_names; /** * Builds a hierarchical suites based on given suite-paths diff --git a/test/ut3_tester_helper/run_helper.pkb b/test/ut3_tester_helper/run_helper.pkb index 95f93f751..a132f4943 100644 --- a/test/ut3_tester_helper/run_helper.pkb +++ b/test/ut3_tester_helper/run_helper.pkb @@ -616,7 +616,7 @@ create or replace package body run_helper is function get_schema_ut_packages(a_owner in varchar2) return ut3_develop.ut_object_names is begin - return ut3_develop.ut_suite_manager.get_schema_ut_packages(ut3_develop.ut_varchar2_rows(a_owner)); + return ut3_develop.ut_suite_manager.get_schema_ut_packages(ut3_develop.ut_varchar2_rows(a_owner), null); end; function ut_output_buffer_tmp return t_out_buff_tab pipelined is diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb index af029e254..488ee3a20 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb @@ -112,9 +112,9 @@ create or replace package body test_extended_coverage is l_actual clob; begin --Arrange - l_expected := '%' || + l_expected := '%' || '%%'; - l_not_expected := '%' || + l_not_expected := '%' || '%%'; --Act l_actual := @@ -123,14 +123,15 @@ create or replace package body test_extended_coverage is ut3_develop.ut.run( a_paths => ut3_develop.ut_varchar2_list('ut3_develop.test_regex_dummy_cov', 'ut3_tester_helper.test_regex_dummy_cov'), a_reporter=> ut3_develop.ut_coverage_sonar_reporter( ), - a_include_schema_expr => '^ut3_develop', - a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) + a_include_schema_expr => '^ut3_tester_hel.*', + a_include_objects => ut3_develop.ut_varchar2_list( 'ut3_develop.regex_dummy_cov' ) ) ]' ); --Assert ut.expect(l_actual).to_be_like(l_expected); ut.expect(l_actual).not_to_be_like(l_not_expected); + ut.expect(l_actual).not_to_be_like('%ut3_tester_helper.test_regex_dummy_cov%'); end; procedure coverage_regex_include_object is From d825156df00b3e313ae4679d9706f09424fab17a Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 17 Oct 2022 00:45:14 +0300 Subject: [PATCH 088/187] Fixing failing test on 11g XE --- .../reporters/test_coverage/test_extended_coverage.pkb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb index 488ee3a20..d7f1b61d7 100644 --- a/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb +++ b/test/ut3_user/reporters/test_coverage/test_extended_coverage.pkb @@ -128,8 +128,10 @@ create or replace package body test_extended_coverage is ) ]' ); + --Assert - ut.expect(l_actual).to_be_like(l_expected); + --The below is a workaround for problem with large CLOB like comparison on 11g XE db. + ut.expect(to_char(substr(l_actual,instr(l_actual,''),2000))).to_be_like(l_expected); ut.expect(l_actual).not_to_be_like(l_not_expected); ut.expect(l_actual).not_to_be_like('%ut3_tester_helper.test_regex_dummy_cov%'); end; From a552566232bccb28cc266964e49e0057feceb87e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Oct 2022 08:29:01 +0100 Subject: [PATCH 089/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index b376d5d4c..d29968ea0 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 2e50760e4..3b2561064 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index dc6d9e59d..93ff86f47 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index fd0cfce15..8f5e3d012 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index eeaf1b002..4fe82c351 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 9805b2b13..71b468da7 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index e36e37d70..41532a7bb 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 6e3d1f0c7..64edde630 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 453f2f794..bc73e60b2 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 1aa179680..d1bbd9f9e 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 8744077fa..e52a4ac7d 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 99409fd95..4a949a5b5 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index bcab40387..f63c08f2a 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index bd3eea917..a52a432f8 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 94c13908a..92afa5ca3 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index f20d8722c..5cc8dcea3 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 461702a47..54381ca25 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4041--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 08a6d95c7..66e1acdfd 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4041-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4049-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 10fd9e02d23ec95f7d9fec9810587a072217c02c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Oct 2022 08:42:03 +0100 Subject: [PATCH 090/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index d29968ea0..c5624601b 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 3b2561064..7338271be 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 93ff86f47..d8b755459 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 8f5e3d012..a3a4d3de7 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 4fe82c351..a30a4d6de 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 71b468da7..fc5ba1063 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 41532a7bb..022f4896c 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 64edde630..9ac021c0e 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index bc73e60b2..62c4d75ac 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index d1bbd9f9e..e6fd25e98 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index e52a4ac7d..871bebcdf 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 4a949a5b5..aa92a6bdd 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index f63c08f2a..ade43890d 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index a52a432f8..84f87c175 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 92afa5ca3..0f3c49a59 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 5cc8dcea3..f45fb2c17 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 54381ca25..87320dd6b 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4049--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 66e1acdfd..3b6b56bbd 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4049-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4050-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 48505fbe05364660b65fca7e6934a652e4b74a03 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 17 Oct 2022 18:28:38 +0300 Subject: [PATCH 091/187] Adding support for long type names in tests. Resolves: #1235 --- .../data_values/ut_cursor_details.tpb | 4 ++++ .../expectations/test_expectation_anydata.pkb | 15 +++++++++++++++ .../expectations/test_expectation_anydata.pks | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/source/expectations/data_values/ut_cursor_details.tpb b/source/expectations/data_values/ut_cursor_details.tpb index adc705f65..b823ff944 100644 --- a/source/expectations/data_values/ut_cursor_details.tpb +++ b/source/expectations/data_values/ut_cursor_details.tpb @@ -91,7 +91,11 @@ create or replace type body ut_cursor_details as a_cursor_number in number ) return self as result is l_columns_count pls_integer; + $if dbms_db_version.version = 12 and dbms_db_version.release = 1 or dbms_db_version.version < 12 $then l_columns_desc dbms_sql.desc_tab3; + $else + l_columns_desc dbms_sql.desc_tab4; + $end l_is_collection boolean; l_hierarchy_level integer := 1; begin diff --git a/test/ut3_user/expectations/test_expectation_anydata.pkb b/test/ut3_user/expectations/test_expectation_anydata.pkb index 98938c107..bbac14ea2 100644 --- a/test/ut3_user/expectations/test_expectation_anydata.pkb +++ b/test/ut3_user/expectations/test_expectation_anydata.pkb @@ -1211,5 +1211,20 @@ Rows: [ 60 differences, showing first 20 ] ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; + + $if dbms_db_version.version = 12 and dbms_db_version.release >= 2 or dbms_db_version.version > 12 $then + procedure long_names_object_types is + pragma autonomous_transaction; + begin + execute immediate 'create or replace type tp_r_ug_sportsman_invitation_result is object ( code number(18) )'; + execute immediate 'begin ut.expect(anydata.convertObject(tp_r_ug_sportsman_invitation_result(1))).to_equal(anydata.convertObject(tp_r_ug_sportsman_invitation_result(1))); end;'; + execute immediate 'drop type tp_r_ug_sportsman_invitation_result'; + exception + when others then + execute immediate 'drop type tp_r_ug_sportsman_invitation_result'; + raise; + end; + $end + end; / \ No newline at end of file diff --git a/test/ut3_user/expectations/test_expectation_anydata.pks b/test/ut3_user/expectations/test_expectation_anydata.pks index 2abb48b7f..81dea74eb 100644 --- a/test/ut3_user/expectations/test_expectation_anydata.pks +++ b/test/ut3_user/expectations/test_expectation_anydata.pks @@ -233,5 +233,11 @@ create or replace package test_expectation_anydata is --%test ( Reports success when comparing complex nested objects ) procedure complex_nested_object_success; + + $if dbms_db_version.version = 12 and dbms_db_version.release >= 2 or dbms_db_version.version > 12 $then + --%test ( Compares object types with long names - Issue #1235 ) + procedure long_names_object_types; + $end + end; / From 1eb52e1e209945477c4066004cdd2f5293290297 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 17 Oct 2022 20:33:42 +0300 Subject: [PATCH 092/187] Fixing unit test - needs to use ut3_develop sourcecode in test. --- .../expectations/test_expectation_anydata.pkb | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/test/ut3_user/expectations/test_expectation_anydata.pkb b/test/ut3_user/expectations/test_expectation_anydata.pkb index bbac14ea2..c56c31930 100644 --- a/test/ut3_user/expectations/test_expectation_anydata.pkb +++ b/test/ut3_user/expectations/test_expectation_anydata.pkb @@ -1216,12 +1216,24 @@ Rows: [ 60 differences, showing first 20 ] procedure long_names_object_types is pragma autonomous_transaction; begin - execute immediate 'create or replace type tp_r_ug_sportsman_invitation_result is object ( code number(18) )'; - execute immediate 'begin ut.expect(anydata.convertObject(tp_r_ug_sportsman_invitation_result(1))).to_equal(anydata.convertObject(tp_r_ug_sportsman_invitation_result(1))); end;'; - execute immediate 'drop type tp_r_ug_sportsman_invitation_result'; + execute immediate q'[create or replace type + very_long_type_name_valid_for_oracle_12_so_utPLSQL_should_allow_it_definitely_well_still_not_reached_128_but_wait_we_did_it + is object ( + code number(18) + )]'; + execute immediate q'[ + begin + ut3_develop.ut.expect(anydata.convertObject( + very_long_type_name_valid_for_oracle_12_so_utPLSQL_should_allow_it_definitely_well_still_not_reached_128_but_wait_we_did_it(1) + )).to_equal(anydata.convertObject( + very_long_type_name_valid_for_oracle_12_so_utPLSQL_should_allow_it_definitely_well_still_not_reached_128_but_wait_we_did_it(1) + )); + end;]'; + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + execute immediate 'drop type very_long_type_name_valid_for_oracle_12_so_utPLSQL_should_allow_it_definitely_well_still_not_reached_128_but_wait_we_did_it'; exception when others then - execute immediate 'drop type tp_r_ug_sportsman_invitation_result'; + execute immediate 'drop type very_long_type_name_valid_for_oracle_12_so_utPLSQL_should_allow_it_definitely_well_still_not_reached_128_but_wait_we_did_it'; raise; end; $end From de65f14d2f9f9debe88437468c7544d30d357742 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 17 Oct 2022 20:36:49 +0300 Subject: [PATCH 093/187] Improvements to local development scripts --- development/cleanup.sh | 4 ++-- development/install.sh | 4 ++-- development/refresh_sources.sh | 4 ++-- development/refresh_ut3.sh | 2 +- development/template.env.sh | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/development/cleanup.sh b/development/cleanup.sh index 33358302a..65f3ab0c1 100755 --- a/development/cleanup.sh +++ b/development/cleanup.sh @@ -1,9 +1,9 @@ -#!/usr/bin/env bash +#!/bin/bash #goto git root directory git rev-parse && cd "$(git rev-parse --show-cdup)" -. development/env.sh +. ./development/env.sh "${SQLCLI}" sys/${ORACLE_PWD}@//${CONNECTION_STR} AS SYSDBA <<-SQL set echo on diff --git a/development/install.sh b/development/install.sh index f3a62b0ec..468bafd38 100755 --- a/development/install.sh +++ b/development/install.sh @@ -1,9 +1,9 @@ -#!/usr/bin/env bash +#!/bin/bash #goto git root directory git rev-parse && cd "$(git rev-parse --show-cdup)" -. development/env.sh +. ./development/env.sh header="******************************************************************************************" if ! development/cleanup.sh; then diff --git a/development/refresh_sources.sh b/development/refresh_sources.sh index 7af3aaec0..b6ef51ef9 100755 --- a/development/refresh_sources.sh +++ b/development/refresh_sources.sh @@ -1,9 +1,9 @@ -#!/usr/bin/env bash +#!/bin/bash #goto git root directory git rev-parse && cd "$(git rev-parse --show-cdup)" -. development/env.sh +. ./development/env.sh # remove sub-direcotry containing main branch shallow copy rm -rf ${UTPLSQL_DIR:-utPLSQL_latest_release} diff --git a/development/refresh_ut3.sh b/development/refresh_ut3.sh index 570d3c86a..827af827d 100755 --- a/development/refresh_ut3.sh +++ b/development/refresh_ut3.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/bash #goto git root directory git rev-parse && cd "$(git rev-parse --show-cdup)" diff --git a/development/template.env.sh b/development/template.env.sh index e69aa81aa..7761a70c4 100755 --- a/development/template.env.sh +++ b/development/template.env.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/bash export SQLCLI=sql # For sqlcl client #export SQLCLI=sqlplus # For sqlplus client From 689bbd0e365ed919315c29727bc10fbfc0dadce8 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 17 Oct 2022 22:24:40 +0300 Subject: [PATCH 094/187] Fixing documentation build process Resolves: #1237 --- .github/workflows/build.yml | 12 ++-- .github/workflows/release.yml | 40 +++---------- mkdocs.yml | 3 + mkdocs_offline.yml | 103 ++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 mkdocs_offline.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0aae6b64..078d45e3b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -245,11 +245,13 @@ jobs: git commit -m 'Updated project version after build [skip ci]' git push --quiet origin HEAD:${CI_ACTION_REF_NAME} - - name: Copy and push documentation to utPLSQL-github-io repo - id: push-documentation - env: - API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} - run: .github/scripts/push_docs_to_github_io.sh + - name: Build and publish documentation + run: | + pip install mkdocs + pip install mkdocs-git-revision-date-localized-plugin + pip install mkdocs-material + pip install mike + mike deploy -p develop dispatch: name: Dispatch downstream builds diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd977d447..acac5f1aa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,36 +10,6 @@ defaults: jobs: - publish: - name: Deploy documentation - concurrency: publish - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - uses: c-py/action-dotenv-to-setenv@v2 - with: - env-file: .github/variables/.env - - uses: FranzDiebold/github-env-vars-action@v2 #https://github.com/marketplace/actions/github-environment-variables-action - - - name: Set buid version number env variables - run: .github/scripts/set_version_numbers_env.sh - - - name: Setup git config - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - - - name: Update project version & build number in source code and documentation - run: .github/scripts/update_project_version.sh - - - name: Copy and push documentation to utPLSQL-github-io repo - env: - API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} - run: .github/scripts/push_docs_to_github_io.sh - upload_artifacts: name: Upload archives concurrency: upload @@ -54,7 +24,7 @@ jobs: env-file: .github/variables/.env - uses: FranzDiebold/github-env-vars-action@v2 #https://github.com/marketplace/actions/github-environment-variables-action - - name: Set buid version number env variables + - name: Set build version number env variables run: .github/scripts/set_version_numbers_env.sh - name: Update project version & build number in source code and documentation @@ -65,10 +35,14 @@ jobs: git config --global user.email "github-actions[bot]@users.noreply.github.com" git config --global user.name "github-actions[bot]" - - name: Build html documentation + - name: Build and publish documentation run: | pip install mkdocs - mkdocs build --clean --strict + pip install mkdocs-git-revision-date-localized-plugin + pip install mkdocs-material + pip install mike + mike deploy -p -u ${UTPLSQL_VERSION} latest + mkdocs build --clean -f mkdocs_offline.yml rm -rf docs/* cp -r -v site/* docs git add . diff --git a/mkdocs.yml b/mkdocs.yml index 8543b4030..487505097 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,7 +1,10 @@ # Format documented here # http://www.mkdocs.org/user-guide/configuration/ # https://squidfunk.github.io/mkdocs-material/getting-started/ +# See this document for list of plugins to disable for offline (local) documentation +# https://squidfunk.github.io/mkdocs-material/setup/building-for-offline-usage/ +edit_uri: "" site_url: http://utPLSQL.org/ site_name: utPLSQL-framework site_description: utPLSQL Ultimate Testing Framework for Oracle PL/SQL & SQL diff --git a/mkdocs_offline.yml b/mkdocs_offline.yml new file mode 100644 index 000000000..fe2255e59 --- /dev/null +++ b/mkdocs_offline.yml @@ -0,0 +1,103 @@ +# Format documented here +# http://www.mkdocs.org/user-guide/configuration/ +# https://squidfunk.github.io/mkdocs-material/getting-started/ +# See this document for list of plugins to disable for offline (local) documentation +# https://squidfunk.github.io/mkdocs-material/setup/building-for-offline-usage/ + +edit_uri: "" +site_url: http://utPLSQL.org/ +site_name: utPLSQL-framework +site_description: utPLSQL Ultimate Testing Framework for Oracle PL/SQL & SQL +copyright: Copyright © 2016 - 2022 utPLSQL Team +#repo_url: https://github.com/utPLSQL/utPLSQL # disable for offline docs +extra_css: + - stylesheets/extra.css +theme: + name: material + palette: + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/lightbulb-outline + name: Switch to dark mode + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/lightbulb + name: Switch to light mode + logo: assets/icon-transparent.png + favicon: assets/favicon.png + features: +# - navigation.instant # disable for offline docs +# - navigation.indexes + - navigation.tabs + - navigation.tracking + - toc.follow + - toc.integrate + - search.suggest + - search.highlight +extra: +# homepage: http://jgebal.github.io/ +# homepage: http://utPLSQL.org/ + social: + - icon: fontawesome/brands/twitter + link: https://twitter.com/utPLSQL + - icon: fontawesome/brands/slack + link: https://join.slack.com/t/utplsql/shared_invite/zt-xwm68udy-4cF_3PNEyczYEbWr38W5ww + - icon: fontawesome/brands/github + link: https://github.com/utPLSQL + - icon: fontawesome/solid/envelope + link: mailto:utPLSQL@utPLSQL.org + consent: + title: Cookie consent + description: >- + We use cookies to recognize your repeated visits and preferences, as well + as to measure the effectiveness of our documentation and whether users + find what they're searching for. With your consent, you're helping us to + make our documentation better. +# version: # disable for offline docs +# provider: mike # disable for offline docs +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + - pymdownx.caret + - pymdownx.mark + - pymdownx.tilde + - toc: + permalink: true +use_directory_urls: false +strict: true + +plugins: +# - search # disable for offline docs + - mike +# - git-revision-date-localized: # disable for offline docs +# enable_creation_date: true # disable for offline docs +# type: datetime # disable for offline docs + +nav: + - User Guide: + - index.md + - Installation: userguide/install.md + - Getting Started: userguide/getting-started.md + - Annotations: userguide/annotations.md + - Expectations: userguide/expectations.md + - Advanced data comparison: userguide/advanced_data_comparison.md + - Running unit tests: userguide/running-unit-tests.md + - Querying for test suites: userguide/querying_suites.md + - Testing best practices: userguide/best-practices.md + - Upgrade utPLSQL: userguide/upgrade.md + - Reporting: + - Using reporters: userguide/reporters.md + - Code coverage: userguide/coverage.md + - Error handling and reporting: userguide/exception-reporting.md + - About: + - Project Details: about/project-details.md + - License: about/license.md + - Support: about/support.md + - Authors: about/authors.md From 4223e0c889ca7ebbfa1003f6ee68ac0a25d8c666 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Oct 2022 20:57:02 +0100 Subject: [PATCH 095/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index c5624601b..6ca52629d 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 7338271be..9396f76fd 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index d8b755459..bbc477c40 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index a3a4d3de7..c880d0bcf 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index a30a4d6de..3ac670e12 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index fc5ba1063..348b9a0fc 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 022f4896c..1ef87e075 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 9ac021c0e..5f9695a74 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 62c4d75ac..e059fc62e 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index e6fd25e98..9490f36d0 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 871bebcdf..b4bd7af17 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index aa92a6bdd..07310dd4f 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index ade43890d..ced4f00a8 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 84f87c175..d943e01f2 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 0f3c49a59..fb19cb65c 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index f45fb2c17..b86332e13 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 87320dd6b..c1128b84c 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4050--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 3b6b56bbd..227a359bb 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4050-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4055-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 8a3554d4e28e7e50e16418a1e61797c0ab6d488f Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 17 Oct 2022 22:59:22 +0300 Subject: [PATCH 096/187] Fixing documentation build process --- .github/workflows/build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 078d45e3b..92bf0752e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -245,6 +245,11 @@ jobs: git commit -m 'Updated project version after build [skip ci]' git push --quiet origin HEAD:${CI_ACTION_REF_NAME} + - name: Setup git config + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + - name: Build and publish documentation run: | pip install mkdocs From 65cfab5dd0a47a2bb10ded89e7ea0c91e84a0d34 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Oct 2022 21:10:44 +0100 Subject: [PATCH 097/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 6ca52629d..5aba8c785 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 9396f76fd..afcd11531 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index bbc477c40..61e52a3ee 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index c880d0bcf..a152f7f22 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 3ac670e12..c95745506 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 348b9a0fc..f7eb1d054 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 1ef87e075..854190837 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 5f9695a74..afab60ca0 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index e059fc62e..efba68e78 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 9490f36d0..11526888a 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index b4bd7af17..5984f4379 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 07310dd4f..4216e832a 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index ced4f00a8..439a0fe5d 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index d943e01f2..5e037ef9d 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index fb19cb65c..9f7239f13 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index b86332e13..c095f468f 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index c1128b84c..259b03f4c 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4055--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 227a359bb..8de2fcc6f 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4055-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4056-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 4e448448b138c93b1215764bdc1e95fb1038dbbb Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 17 Oct 2022 23:32:42 +0300 Subject: [PATCH 098/187] Adding missing images --- docs/assets/favicon.png | Bin 0 -> 76887 bytes docs/assets/icon-transparent.png | Bin 0 -> 33228 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/assets/favicon.png create mode 100644 docs/assets/icon-transparent.png diff --git a/docs/assets/favicon.png b/docs/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..7c34109d0bb66a2279905822ae733eaf4c5fed6c GIT binary patch literal 76887 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%0AOejk+hE97)`ZW`d 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 Z!gMIwttjR#!iKb}bVpsTME23s{{aY_cD4Wj literal 0 HcmV?d00001 From 9f3ac159d49c8b8aa9b4922618814b45bd83c903 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Oct 2022 21:41:48 +0100 Subject: [PATCH 099/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 5aba8c785..cffceccd5 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index afcd11531..e3d36263f 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 61e52a3ee..35dd126bc 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index a152f7f22..6744fdcd7 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index c95745506..d0ed18395 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index f7eb1d054..a0ccfcb2d 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 854190837..14b757ff8 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index afab60ca0..df76c3dd2 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index efba68e78..1801468bc 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 11526888a..e0c5a0a5a 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 5984f4379..8b0431989 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 4216e832a..6ba6caefc 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 439a0fe5d..5c822c8ba 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 5e037ef9d..60907a8a8 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 9f7239f13..6736d343c 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index c095f468f..a5c7fc13b 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 259b03f4c..5fd83508b 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4056--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 8de2fcc6f..ae5bf633c 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4056-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4057-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From c94472ec42875ed026da8149dd7c8ce29052d605 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Oct 2022 21:54:12 +0100 Subject: [PATCH 100/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index cffceccd5..c71ef0f58 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index e3d36263f..bbeccc95a 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 35dd126bc..20340b643 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 6744fdcd7..dc8499a3d 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index d0ed18395..a3167d01a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index a0ccfcb2d..dd95cac2a 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 14b757ff8..121fba868 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index df76c3dd2..a1bbde32c 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 1801468bc..29439a243 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index e0c5a0a5a..7f26e718a 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 8b0431989..fd6baf7c9 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 6ba6caefc..90f4e1c83 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 5c822c8ba..dd2c718e8 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 60907a8a8..454d880c8 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 6736d343c..04f27bc8c 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index a5c7fc13b..bfdc93363 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 5fd83508b..a123610c7 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4057--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index ae5bf633c..f0ce27228 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4057-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4058-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 24fa8ffb9f204fb80e30063ba67d21af45f6de8d Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 19 Oct 2022 00:33:15 +0300 Subject: [PATCH 101/187] Ability to report coverage on long lines. Sourcecode lines that result in more than 4000 chars after conversion to HTML should be reported successfully. Resolves: #1232 --- .../ut_coverage_report_html_helper.pkb | 15 +++-- .../test_html_coverage_reporter.pkb | 65 +++++++++++++++++++ .../test_html_coverage_reporter.pks | 8 +++ 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/source/reporters/ut_coverage_report_html_helper.pkb b/source/reporters/ut_coverage_report_html_helper.pkb index 2bb9a87d9..f7e0b5ed0 100644 --- a/source/reporters/ut_coverage_report_html_helper.pkb +++ b/source/reporters/ut_coverage_report_html_helper.pkb @@ -134,9 +134,11 @@ create or replace package body ut_coverage_report_html_helper is l_file_part varchar2(32767); l_result ut_varchar2_rows := ut_varchar2_rows(); l_coverage_pct number(5, 2); - l_coverage_block_pct number(5, 2); l_hits varchar2(30); l_blocks varchar2(30); + l_line_text varchar2(32767); + e_buffer_too_small exception; + pragma exception_init ( e_buffer_too_small, -19011 ); begin l_coverage_pct := coverage_pct(a_coverage_unit.covered_lines, a_coverage_unit.uncovered_lines); @@ -148,10 +150,16 @@ create or replace package body ut_coverage_report_html_helper is ut_utils.append_to_list(l_result, l_file_part); for line_no in 1 .. a_source_code.count loop + begin + l_line_text := dbms_xmlgen.convert(a_source_code(line_no)); + exception + when e_buffer_too_small then + l_line_text := dbms_xmlgen.convert(to_clob(a_source_code(line_no))); + end; if not a_coverage_unit.lines.exists(line_no) then l_file_part := '
  • - ' || (dbms_xmlgen.convert(a_source_code(line_no))) || + ' || l_line_text || '
  • '; else l_hits := to_char(a_coverage_unit.lines(line_no).executions); @@ -188,7 +196,7 @@ create or replace package body ut_coverage_report_html_helper is ''; end if; l_file_part := l_file_part || ' - ' || (dbms_xmlgen.convert(a_source_code(line_no))) || + ' || l_line_text || ''; end if; ut_utils.append_to_list(l_result, l_file_part); @@ -222,7 +230,6 @@ create or replace package body ut_coverage_report_html_helper is l_file_part varchar2(32767); l_title varchar2(100) := 'All files'; l_coverage_pct number(5, 2); - l_coverage_block_pct number(5, 2); l_result ut_varchar2_rows; l_id varchar2(50) := object_id(a_title); l_unit_coverage ut_coverage.t_unit_coverage; diff --git a/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pkb b/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pkb index d1645acae..ad14adb8c 100644 --- a/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pkb +++ b/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pkb @@ -32,5 +32,70 @@ create or replace package body test_html_coverage_reporter is ut.expect(l_actual).to_be_like(l_expected); end; + procedure setup_long_lines is + pragma autonomous_transaction; + begin + + execute immediate q'[create or replace type string_array is table of varchar2(5 char);]'; + execute immediate q'[ + create or replace function f return integer is + l_string_array string_array; + l_count integer; + begin + -- line is 1912 chars long, 1911 characters seem to be the max. line length that works (@formatter:off) + l_string_array := string_array('aahed', 'aalii', 'aargh', 'aarti', 'abaca', 'abaci', 'abacs', 'abaft', 'abaka', 'abamp', 'aband', 'abash', 'abask', 'abaya', 'abbas', 'abbed', 'abbes', 'abcee', 'abeam', 'abear', 'abele', 'abers', 'abets', 'abies', 'abler', 'ables', 'ablet', 'ablow', 'abmho', 'abohm', 'aboil', 'aboma', 'aboon', 'abord', 'abore', 'abram', 'abray', 'abrim', 'abrin', 'abris', 'absey', 'absit', 'abuna', 'abune', 'abuts', 'abuzz', 'abyes', 'abysm', 'acais', 'acari', 'accas', 'accoy', 'acerb', 'acers', 'aceta', 'achar', 'ached', 'aches', 'achoo', 'acids', 'acidy', 'acing', 'acini', 'ackee', 'acker', 'acmes', 'acmic', 'acned', 'acnes', 'acock', 'acold', 'acred', 'acres', 'acros', 'acted', 'actin', 'acton', 'acyls', 'adaws', 'adays', 'adbot', 'addax', 'added', 'adder', 'addio', 'addle', 'adeem', 'adhan', 'adieu', 'adios', 'adits', 'adman', 'admen', 'admix', 'adobo', 'adown', 'adoze', 'adrad', 'adred', 'adsum', 'aduki', 'adunc', 'adust', 'advew', 'adyta', 'adzed', 'adzes', 'aecia', 'aedes', 'aegis', 'aeons', 'aerie', 'aeros', 'aesir', 'afald', 'afara', 'afars', 'afear', 'aflaj', 'afore', 'afrit', 'afros', 'agama', 'agami', 'agars', 'agast', 'agave', 'agaze', 'agene', 'agers', 'agger', 'aggie', 'aggri', 'aggro', 'aggry', 'aghas', 'agila', 'agios', 'agism', 'agist', 'agita', 'aglee', 'aglet', 'agley', 'agloo', 'aglus', 'agmas', 'agoge', 'agone', 'agons', 'agood', 'agora', 'agria', 'agrin', 'agros', 'agued', 'agues', 'aguna', 'aguti', 'aheap', 'ahent', 'ahigh', 'ahind', 'ahing', 'ahint', 'ahold', 'ahull', 'ahuru', 'aidas', 'aided', 'aides', 'aidoi', 'aidos', 'aiery', 'aigas', 'aight', 'ailed', 'aimed', 'aimer', 'ainee', 'ainga', 'aioli', 'aired', 'airer', 'airns', 'airth', 'airts', 'aitch', 'aitus', 'aiver', 'aiyee', 'aizle', 'ajies', 'ajiva', 'ajuga', 'ajwan', 'akees', 'akela', 'akene', 'aking', 'akita', 'akkas', 'alaap', 'alack', 'alamo', 'aland', 'alane', 'alang', 'a'); + select count(*) into l_count from table(l_string_array); + return l_count; + end;]'; + + execute immediate q'[ + create or replace package test_f is + --%suite + + --%test + procedure crashing_ut_coverage_html_reporter; + end;]'; + + execute immediate q'[ + create or replace package body test_f is + procedure crashing_ut_coverage_html_reporter is + begin + ut3_develop.ut.expect(f()).to_be_greater_or_equal(1); + end; + end; + ]'; + end; + + procedure cleanup_long_lines is + pragma autonomous_transaction; + begin + execute immediate 'drop package test_f'; + execute immediate 'drop function f'; + execute immediate 'drop type string_array force'; + end; + + procedure report_long_lines is + l_expected varchar2(32767); + l_actual clob; + l_name varchar2(250); + begin + --Arrange + l_expected := '%l_string_array := string_array%'; + + l_actual := + ut3_tester_helper.coverage_helper.run_tests_as_job( + q'[ + ut3_develop.ut.run( + a_path => 'ut3_user.test_f', + a_reporter=> ut3_develop.ut_coverage_html_reporter(), + a_include_objects => ut3_develop.ut_varchar2_list( 'UT3_USER.F' ) + ) + ]' + ); + --Assert + ut.expect(l_actual).to_be_like(l_expected); + end; + + end test_html_coverage_reporter; / diff --git a/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pks b/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pks index 629d41793..a11f3e912 100644 --- a/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pks +++ b/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pks @@ -6,5 +6,13 @@ create or replace package test_html_coverage_reporter is --%test(reports on a project file mapped to database object in extended profiler coverage) procedure report_on_file; + procedure setup_long_lines; + procedure cleanup_long_lines; + + --%test(reports on lines exceeding 4000 chars after conversion to XML) + --%beforetest(setup_long_lines) + --%aftertest(cleanup_long_lines) + procedure report_long_lines; + end test_html_coverage_reporter; / From 82707159ee485915c55506d608d0e6143bf99247 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 19 Oct 2022 00:45:25 +0300 Subject: [PATCH 102/187] Fixing name that was too long for the test before 12.2 --- .../reporters/test_coverage/test_html_coverage_reporter.pkb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pkb b/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pkb index ad14adb8c..2f2200116 100644 --- a/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pkb +++ b/test/ut3_user/reporters/test_coverage/test_html_coverage_reporter.pkb @@ -53,12 +53,12 @@ create or replace package body test_html_coverage_reporter is --%suite --%test - procedure crashing_ut_coverage_html_reporter; + procedure fail_ut_coverage_html_reporter; end;]'; execute immediate q'[ create or replace package body test_f is - procedure crashing_ut_coverage_html_reporter is + procedure fail_ut_coverage_html_reporter is begin ut3_develop.ut.expect(f()).to_be_greater_or_equal(1); end; From 7925a75de38eaddde5952e92fd8f6ba5ab8500d5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 19 Oct 2022 21:23:40 +0100 Subject: [PATCH 103/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index c71ef0f58..961ba3060 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index bbeccc95a..2b625c7d0 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 20340b643..a915f2a52 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index dc8499a3d..5d4ed97cf 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index a3167d01a..c391be166 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index dd95cac2a..2acd290c9 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 121fba868..3e95d2852 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index a1bbde32c..b39ab803b 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 29439a243..1a227d9e4 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 7f26e718a..d83142f9f 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index fd6baf7c9..1c1974319 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 90f4e1c83..e9681bb7b 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index dd2c718e8..fca38c92e 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 454d880c8..e7496320c 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 04f27bc8c..1f5ead1c5 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) utPLSQL provides the following reporting formats. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index bfdc93363..a87fe9836 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index a123610c7..a219012fd 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4058--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index f0ce27228..06b17ccbf 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4058-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4063-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 9e03e76d0c3a193611430113e9b0477712bc8cee Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 27 Oct 2022 00:20:15 +0300 Subject: [PATCH 104/187] Improving documentation --- docs/index.md | 14 +- docs/userguide/advanced_data_comparison.md | 26 +- docs/userguide/annotations.md | 338 +++++++++++---------- docs/userguide/coverage.md | 152 +++++---- docs/userguide/exception-reporting.md | 30 +- docs/userguide/expectations.md | 149 ++++----- docs/userguide/getting-started.md | 16 +- docs/userguide/install.md | 34 +-- docs/userguide/querying_suites.md | 16 +- docs/userguide/reporters.md | 46 +-- docs/userguide/running-unit-tests.md | 52 ++-- mkdocs.yml | 4 +- mkdocs_offline.yml | 4 +- 13 files changed, 475 insertions(+), 406 deletions(-) diff --git a/docs/index.md b/docs/index.md index c391be166..bc7e1e63b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -7,9 +7,15 @@ The framework follows industry standards and best patterns of modern Unit Testin ## Demo project -Have a look at our [demo project](https://github.com/utPLSQL/utPLSQL-demo-project/). +Have a look at [utPLSQL demo project](https://github.com/utPLSQL/utPLSQL-demo-project/) to see: -It uses [Travis CI](https://travis-ci.org/utPLSQL/utPLSQL-demo-project) to build on every commit, runs all tests, publishes test results and code coverage to [SonarCloud](https://sonarcloud.io/project/overview?id=utPLSQL:utPLSQL-demo-project). +- sample code and tests +- demo of deployment automation that leverages: + - Flyway / Liquidbase for scripting and deployment of DB changes + - Docker container with Oracle XE Database + - GitHub Actions and Azure Pipelines to orchestrate the deployment and testing process + - utPLSQL framework for writhing, execution of tests as well as reporting test results and code coverage + - [Sonar]((https://sonarcloud.io/project/overview?id=utPLSQL:utPLSQL-demo-project).) for code quality gate, test results and code coverage reporting ## Three steps @@ -31,6 +37,7 @@ Check out the sections on [annotations](userguide/annotations.md) and [expectati You can use the utPLSQL command line client [utPLSQL-cli](https://github.com/utPLSQL/utPLSQL-cli) to run tests without the need for Oracle Client or any IDE like SQLDeveloper/TOAD etc. Amongst many benefits they provide ability to: + * see the progress of test execution for long-running tests - real-time reporting * use many reporting formats simultaneously and save reports to files (publish) * map your project source files and test files into database objects @@ -40,8 +47,7 @@ See [project readme](https://github.com/utPLSQL/utPLSQL-cli/blob/develop/README. ## Coverage -If you want to have code coverage gathered on your code , it's best to use `ut_run` to execute your tests with multiple reporters and have both test execution report as well as coverage report saved to a file. - +It is best to use utPLSQL-cli or execute tests and gather code coverage from command line. Check out the [coverage documentation](userguide/coverage.md) for options of coverage reporting diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 2acd290c9..2e2d4af9f 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -48,7 +48,7 @@ When specifying column/attribute names, keep in mind that the names are **case s ## Excluding elements from data comparison Consider the following examples -```sql +```sql linenums="1" declare l_expected sys_refcursor; l_actual sys_refcursor; @@ -86,7 +86,7 @@ The actual data is equal/contains expected, when those columns are excluded. ## Selecting columns for data comparison Consider the following example -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -125,7 +125,7 @@ The actual data is equal/contains expected, when only those columns are included You can chain the advanced options in an expectation and mix the `varchar2` with `ut_varchar2_list` arguments. When doing so, the final list of items to include/exclude will be a concatenation of all items. -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -163,7 +163,7 @@ SUCCESS Example of `include / exclude` for anydata.convertCollection -```sql +```sql linenums="1" create or replace type person as object( name varchar2(100), age integer @@ -219,7 +219,7 @@ Unordered option allows for quick comparison of two compound data types without Result of such comparison will be limited to only information about row existing or not existing in given set without actual information about exact differences. -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -267,7 +267,7 @@ The extra or missing rows will be presented to user as well as all non-matching Join by option can be used in conjunction with include or exclude options. However if any of the join keys is part of exclude set, comparison will fail and report to user that sets could not be joined on specific key, as the key was excluded. -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -305,7 +305,7 @@ FAILURE You can use `join_by` syntax in combination with `contain` matcher. -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -322,7 +322,7 @@ end; ``` Above test will indicate that in actual data-set -```sql +```sql linenums="1" FAILURE Actual: refcursor [ count = 28 ] was expected to contain: refcursor [ count = 29 ] Diff: @@ -335,7 +335,7 @@ FAILURE You can specify multiple columns in `join_by` -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -371,7 +371,7 @@ To reference attribute as PK, use slash symbol `/` to separate nested elements. In the below example, cursors are joined using the `NAME` attribute of object in column `SOMEONE` -```sql +```sql linenums="1" create or replace type person as object( name varchar2(100), age integer @@ -414,7 +414,7 @@ FAILURE > `join_by` does not support joining on individual elements of nested table. You can still use data of the nested table as a PK value. > When collection is referenced in `join_by`, test will fail with appropriate message, as it cannot perform a join. -```sql +```sql linenums="1" create or replace type person as object( name varchar2(100), age integer @@ -463,7 +463,7 @@ You may provide items for `include`/`exclude`/`join_by` as a a ut_varchar2_list - nested table and varray items type attributes are nested under `` elements Example of a valid parameter to include columns: `RN`, `A_Column`, `SOME_COL` in data comparison. -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -494,7 +494,7 @@ Expectations that compare compound data type data with `unordered_columns` optio This option can be useful whn we have no control over the ordering of the column or the column order is not of importance from testing perspective. -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 3e95d2852..2c13fb649 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -5,20 +5,21 @@ No additional configuration files or tables are needed for test cases. The annot The framework runner searches for all the suitable annotated packages, automatically configures suites, forms the suite hierarchy, executes it and reports results in specified formats. Annotation is defined by: + - single line comment `--` (double hyphen) - followed directly by a `%` (percent) - followed by annotation name - followed by optional annotation text placed in single brackets. -All of text between first opening bracket and last closing bracket in annotation line is considered to be annotation text +All text between first opening bracket and last closing bracket in annotation line is considered to be annotation text -Examples: -`--%suite(The name of my test suite)` - represents `suite` annotation with text `The name of my test suite` +For example `--%suite(The name of my test suite)` represents `suite` annotation with `The name of my test suite` as annotation text. -utPLSQL interprets the whole line of annotation and will treat all the text from the first opening bracket in the line to the last closing bracket +utPLSQL interprets the whole line of annotation and will treat text from the first opening bracket in the line to the last closing bracket in that line as annotation text -Example: - `--%suite(Stuff) -- we should name this ( correctly )` - represents `suite` annotation with text `Stuff) -- we should name this ( correctly ` +In below example we have a `suite` annotation with `Stuff) -- we should name this ( correctly ` as the annotation text + +`--%suite(Stuff) -- we should name this ( correctly )` Do not place comments within annotation line to avoid unexpected behaviors. @@ -57,7 +58,7 @@ end; ``` Invalid procedure annotations examples: -```sql +```sql linenums="1" package test_package is --%suite @@ -88,7 +89,7 @@ Those annotations placed at any place in package except directly before procedur We strongly recommend putting package level annotations at the very top of package except for the `--%context` annotations (described below) Valid package annotations example: -```sql +```sql linenums="1" package test_package is --%suite @@ -106,7 +107,7 @@ end; ``` Invalid package annotations examples: -```sql +```sql linenums="1" package test_package is --%suite --This is wrong as suite annotation is not a procedure annotation procedure irrelevant; @@ -120,29 +121,29 @@ end; ## Supported annotations -| Annotation |Level| Description | -| --- | --- | --- | -| `--%suite()` | Package | Mandatory. Marks package as a test suite. Optional suite description can be provided (see `displayname`). | -| `--%suitepath()` | Package | Similar to java package. The annotation allows logical grouping of suites into hierarchies. | -| `--%displayname()` | Package/procedure | Human-readable and meaningful description of a context/suite/test. Overrides the `` provided with `suite`/`test`/`context` annotation. This annotation is redundant and might be removed in future releases. | -| `--%test()` | Procedure | Denotes that the annotated procedure is a unit test procedure. Optional test description can be provided (see `displayname`). | -| `--%throws([,...])`| Procedure | Denotes that the annotated test procedure must throw one of the exceptions provided. Supported forms of exceptions are: numeric literals, numeric constant names, exception constant names, predefined Oracle exception names. | -| `--%beforeall` | Procedure | Denotes that the annotated procedure should be executed once before all elements of the suite. | -| `--%beforeall([[.].][,...])` | Package | Denotes that the mentioned procedure(s) should be executed once before all elements of the suite. | -| `--%afterall` | Procedure | Denotes that the annotated procedure should be executed once after all elements of the suite. | -| `--%afterall([[.].][,...])` | Package | Denotes that the mentioned procedure(s) should be executed once after all elements of the suite. | -| `--%beforeeach` | Procedure | Denotes that the annotated procedure should be executed before each `%test` procedure in the suite. | -| `--%beforeeach([[.].][,...])` | Package | Denotes that the mentioned procedure(s) should be executed before each `%test` procedure in the suite. | -| `--%aftereach` | Procedure | Denotes that the annotated procedure should be executed after each `%test` procedure in the suite. | -| `--%aftereach([[.].][,...])` | Package | Denotes that the mentioned procedure(s) should be executed after each `%test` procedure in the suite. | -| `--%beforetest([[.].][,...])` | Procedure | Denotes that mentioned procedure(s) should be executed before the annotated `%test` procedure. | -| `--%aftertest([[.].][,...])` | Procedure | Denotes that mentioned procedure(s) should be executed after the annotated `%test` procedure. | -| `--%rollback()` | Package/procedure | Defines transaction control. Supported values: `auto`(default) - a savepoint is created before invocation of each "before block" is and a rollback to specific savepoint is issued after each "after" block; `manual` - rollback is never issued automatically. Property can be overridden for child element (test in suite) | -| `--%disabled()` | Package/procedure | Used to disable a suite, whole context or a test. Disabled suites/contexts/tests do not get executed, they are however marked and reported as disabled in a test run. The reason that will be displayed next to disabled tests is decided based on hierarchy suites -> context -> test | -| `--%context()` | Package | Denotes start of a named context (sub-suite) in a suite package an optional description for context can be provided. | -| `--%name()` | Package | Denotes name for a context. Must be placed after the context annotation and before start of nested context. | -| `--%endcontext` | Package | Denotes end of a nested context (sub-suite) in a suite package | -| `--%tags` | Package/procedure | Used to label a test or a suite for purpose of identification | +| Annotation | Level | Description | +|------------------------------------------------------------|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--%suite( )` | Package | Mandatory. Marks package as a test suite. Optional suite description can be provided (see `displayname`). | +| `--%suitepath( )` | Package | Similar to java package. The annotation allows logical grouping of suites into hierarchies. | +| `--%displayname( )` | Package/procedure | Human-readable and meaningful description of a context/suite/test. Overrides the `` provided with `suite`/`test`/`context` annotation. This annotation is redundant and might be removed in future releases. | +| `--%test( )` | Procedure | Denotes that the annotated procedure is a unit test procedure. Optional test description can be provided (see `displayname`). | +| `--%throws( [,...] )` | Procedure | Denotes that the annotated test procedure must throw one of the exceptions provided. Supported forms of exceptions are: numeric literals, numeric constant names, exception constant names, predefined Oracle exception names. | +| `--%beforeall` | Procedure | Denotes that the annotated procedure should be executed once before all elements of the suite. | +| `--%beforeall( [[.].][,...] )` | Package | Denotes that the mentioned procedure(s) should be executed once before all elements of the suite. | +| `--%afterall` | Procedure | Denotes that the annotated procedure should be executed once after all elements of the suite. | +| `--%afterall( [[.].][,...] )` | Package | Denotes that the mentioned procedure(s) should be executed once after all elements of the suite. | +| `--%beforeeach` | Procedure | Denotes that the annotated procedure should be executed before each `%test` procedure in the suite. | +| `--%beforeeach( [[.].][,...] )` | Package | Denotes that the mentioned procedure(s) should be executed before each `%test` procedure in the suite. | +| `--%aftereach` | Procedure | Denotes that the annotated procedure should be executed after each `%test` procedure in the suite. | +| `--%aftereach( [[.].][,...] )` | Package | Denotes that the mentioned procedure(s) should be executed after each `%test` procedure in the suite. | +| `--%beforetest( [[.].][,...] )` | Procedure | Denotes that mentioned procedure(s) should be executed before the annotated `%test` procedure. | +| `--%aftertest( [[.].][,...] )` | Procedure | Denotes that mentioned procedure(s) should be executed after the annotated `%test` procedure. | +| `--%rollback( )` | Package/procedure | Defines transaction control. Supported values: `auto`(default) - a savepoint is created before invocation of each "before block" is and a rollback to specific savepoint is issued after each "after" block; `manual` - rollback is never issued automatically. Property can be overridden for child element (test in suite) | +| `--%disabled( )` | Package/procedure | Used to disable a suite, whole context or a test. Disabled suites/contexts/tests do not get executed, they are however marked and reported as disabled in a test run. The reason that will be displayed next to disabled tests is decided based on hierarchy suites -> context -> test | +| `--%context( )` | Package | Denotes start of a named context (sub-suite) in a suite package an optional description for context can be provided. | +| `--%name( )` | Package | Denotes name for a context. Must be placed after the context annotation and before start of nested context. | +| `--%endcontext` | Package | Denotes end of a nested context (sub-suite) in a suite package | +| `--%tags` | Package/procedure | Used to label a test or a suite for purpose of identification | ### Suite @@ -162,13 +163,13 @@ If the parameters are placed without brackets or with incomplete brackets, they Suite package without description. -```sql +```sql linenums="1" create or replace package test_package as --%suite end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -179,13 +180,13 @@ Finished in .002415 seconds ``` Suite package with description. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -196,14 +197,14 @@ Finished in .001646 seconds ``` When multiple `--%suite` annotations are specified in package, the first annotation will be used and a warning message will appear indicating duplicate annotation. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) --%suite(Bad annotation) end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -221,14 +222,14 @@ Finished in .003318 seconds ``` When `--%suite` annotation is bound to procedure, it is ignored and results in package not getting recognized as test suite. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) procedure some_proc; end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -255,7 +256,7 @@ If `--%test` raises an unhandled exception the following will happen: - test execution will continue uninterrupted for rest of the suite Test procedure without description. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -268,7 +269,7 @@ create or replace package body test_package as end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -280,7 +281,7 @@ Finished in .004109 seconds ``` Test procedure with description. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -294,7 +295,7 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -306,7 +307,7 @@ Finished in .006828 seconds ``` When multiple `--%test` annotations are specified for a procedure, the first annotation will be used and a warning message will appear indicating duplicate annotation. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -321,7 +322,7 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -344,7 +345,7 @@ Marks annotated suite package or test procedure as disabled. You can provide the reason why the test is disabled that will be displayed in output. Disabling suite. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) --%disabled(Reason for disabling suite) @@ -365,7 +366,7 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -378,7 +379,7 @@ Finished in .001441 seconds ``` Disabling the context(s). -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -408,7 +409,7 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -423,7 +424,7 @@ Finished in .005079 seconds ``` Disabling individual test(s). -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -444,7 +445,7 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -461,7 +462,7 @@ Finished in .005868 seconds There are two possible ways to use the `--%beforeall` annotation. As a procedure level annotation: -```sql +```sql linenums="1" --%suite(Some test suite) --%beforeall @@ -473,7 +474,7 @@ procedure some_test; Marks annotated procedure to be executed before all test procedures in a suite. As a package level annotation (not associated with any procedure). -```sql +```sql linenums="1" --%suite(Some test suite) --%beforeall(to_be_executed_before_all, other_package.some_setup) @@ -490,6 +491,7 @@ Indicates that the procedure(s) mentioned as the annotation parameter are to be If `--%beforeall` raises an exception, suite content cannot be safely executed as the setup was not executed successfully for the suite. If `--%beforeall` raises an exception the following will happen: + - the `--%beforeall` procedures that follow the failed one, **will not be executed** - all `--%test` procedures and their `--%beforeeach`, `--%aftereach`, `--%beforetest` and `--%aftertest` procedures within suite package **will not be executed** - all `--%test` procedures **will be marked as failed** @@ -500,7 +502,7 @@ When multiple `--%beforeall` procedures are defined in a suite package, all of t For multiple `--%beforeall` procedures order of execution is defined by annotation position in the package specification. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -528,9 +530,10 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` + ``` Tests for a package --- SETUP_STUFF invoked --- @@ -544,7 +547,7 @@ Finished in .012292 seconds In the below example a combination pacakge and procedure level `--%beforeall` annotations is used. The order of execution of the beforeall procedures is determined by the annotation position in package. All of the `--%beforeall` procedures get invoked before any test is executed in a suite. - ```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -593,12 +596,13 @@ All of the `--%beforeall` procedures get invoked before any test is executed in procedure other_test is begin null; end; end; / - ``` +``` - ```sql +```sql linenums="1" exec ut.run('test_package'); - ``` - ``` +``` + +``` Tests for a package --- INITIAL_SETUP invoked --- --- ANOTHER_SETUP invoked --- @@ -609,11 +613,11 @@ Tests for a package Finished in .018944 seconds 2 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s) - ``` +``` When multiple `--%beforeall` annotations are specified for a procedure, the first annotation will be used and a warning message will appear indicating duplicate annotation. When procedure is annotated as both `--%beforeall` and `--%test`, the procedure will become a test and a warning message will appear indicating invalid annotation combination. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -644,10 +648,11 @@ When procedure is annotated as both `--%beforeall` and `--%test`, the procedure / ``` - ```sql +```sql linenums="1" exec ut.run('test_package'); - ``` - ``` +``` + +``` Tests for a package --- INITIAL_SETUP invoked --- Description of tested behavior [.003 sec] @@ -665,7 +670,7 @@ Warnings: Finished in .012158 seconds 2 tests, 0 failed, 0 errored, 0 disabled, 2 warning(s) - ``` +``` ### Afterall @@ -673,7 +678,7 @@ Finished in .012158 seconds There are two possible ways to use the `--%afterall` annotation. As a procedure level annotation: -```sql +```sql linenums="1" --%suite(Some test suite) --%afterall @@ -685,7 +690,7 @@ procedure some_test; Marks annotated procedure to be executed after all test procedures in a suite. As a package level annotation (not associated with any procedure). -```sql +```sql linenums="1" --%suite(Some test suite) --%afterall(to_be_executed_after_all, other_package.some_cleanup) @@ -694,11 +699,12 @@ As a package level annotation (not associated with any procedure). procedure some_test; procedure to_be_executed_after_all; - ``` + Indicates that the procedure(s) mentioned as the annotation parameter are to be executed after all test procedures in a suite. If `--%afterall` raises an exception the following will happen: + - a warning will be raised, indicating that `--%afterall` procedure has failed - execution will continue uninterrupted for rest of the suite @@ -711,7 +717,7 @@ For multiple `--%afterall` procedures order of execution is defined by annotatio All rules defined for `--%beforeall` also apply for `--%afterall` annotation. See [beforeall](#Beforeall) for more details. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -739,9 +745,10 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` + ``` Tests for a package Description of tested behavior [.003 sec] @@ -760,7 +767,7 @@ That means that the procedure will be executed as many times as there are test i There are two possible ways to use the `--%beforeeach` annotation. As a procedure level annotation: -```sql +```sql linenums="1" --%suite(Some test suite) --%beforeeach @@ -772,7 +779,7 @@ procedure some_test; Marks annotated procedure to be executed before each test procedures in a suite. As a package level annotation (not associated with any procedure). -```sql +```sql linenums="1" --%suite(Some test suite) --%beforeeach(to_be_executed_before_each, other_package.some_setup) @@ -781,14 +788,15 @@ As a package level annotation (not associated with any procedure). procedure some_test; procedure to_be_executed_before_each; - ``` + Indicates that the procedure(s) mentioned as the annotation parameter are to be executed before each test procedure in a suite. If a test is marked as disabled the `--%beforeeach` procedure is not invoked for that test. If `--%beforeeach` raises an unhandled exception the following will happen: + - the following `--%beforeeach` as well as all `--%beforetest` for that test **will not be executed** - the test will be marked as errored and exception stack trace will be captured and reported - the `--%aftertest`, `--%aftereach` procedures **will be executed** for the errored test @@ -801,7 +809,7 @@ When multiple `--%beforeeach` procedures are defined in a suite, all of them wil For multiple `--%beforeeach` procedures order of execution is defined by annotation position in the package specification. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -842,9 +850,10 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` + ``` Tests for a package ---SETUP_STUFF invoked --- @@ -871,7 +880,7 @@ That means that the procedure will be executed as many times as there are test i There are two possible ways to use the `--%aftereach` annotation. As a procedure level annotation: -```sql +```sql linenums="1" --%suite(Some test suite) --%aftereach @@ -883,7 +892,7 @@ procedure some_test; Marks annotated procedure to be executed after each test procedures in a suite. As a package level annotation (not associated with any procedure). -```sql +```sql linenums="1" --%suite(Some test suite) --%aftereach(to_be_executed_after_each, other_package.some_setup) @@ -892,13 +901,14 @@ As a package level annotation (not associated with any procedure). procedure some_test; procedure to_be_executed_after_each; - ``` + Indicates that the procedure(s) mentioned as the annotation parameter are to be executed after each test procedure in a suite. If a test is marked as disabled the `--%aftereach` procedure is not invoked for that test. If `--%aftereach` raises an unhandled exception the following will happen: + - the test will be marked as errored and exception stack trace will be captured and reported - the `--%aftertest`, `--%aftereach` procedures **will be executed** for the errored test - the `--%afterall` procedures **will be executed** @@ -910,7 +920,7 @@ For multiple `--%aftereach` procedures order of execution is defined by the anno As a rule, the `--%aftereach` gets executed even if the associated `--%beforeeach`, `--%beforetest`, `--%test` or other `--%aftereach` procedures have raised unhandled exceptions. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -950,7 +960,7 @@ create or replace package body test_package as end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -972,6 +982,7 @@ See [beforeall](#Beforeall) for more examples. ### Beforetest Indicates specific setup procedure(s) to be executed for a test. The procedure(s) can be located either: + - within current package (package name is optional) - within another package @@ -982,6 +993,7 @@ The `--%beforetest` procedures are executed after invoking all `--%beforeeach` f If a test is marked as disabled the `--%beforetest` procedures are not invoked for that test. If `--%beforetest` raises an unhandled exception the following will happen: + - the following `--%beforetest` for that test **will not be executed** - the test will be marked as errored and exception stack trace will be captured and reported - the `--%aftertest`, `--%aftereach` procedures **will be executed** for the errored test @@ -991,12 +1003,13 @@ If `--%beforetest` raises an unhandled exception the following will happen: When multiple `--%beforetest` procedures are defined for a test, all of them will be executed before invoking the test. The order of execution for `--%beforetest` procedures is defined by: + - position of procedure on the list within single annotation - annotation position As a rule, the `--%beforetest` execution gets aborted if preceding `--%beforeeach` or `--%beforetest` failed. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -1038,7 +1051,7 @@ create or replace package body test_package as end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -1060,6 +1073,7 @@ Finished in .015185 seconds ### Aftertest Indicates specific cleanup procedure(s) to be executed for a test. The procedure(s) can be located either: + - within current package (package name is optional) - within another package @@ -1068,6 +1082,7 @@ The annotation need to be placed alongside `--%test` annotation. If a test is marked as disabled the `--%aftertest` procedures are not invoked for that test. If `--%aftertest` raises an unhandled exception the following will happen: + - the test will be marked as errored and exception stack trace will be captured and reported - the following `--%aftertest` and all `--%aftereach` procedures **will be executed** for the errored test - the `--%afterall` procedures **will be executed** @@ -1076,12 +1091,13 @@ If `--%aftertest` raises an unhandled exception the following will happen: When multiple `--%aftertest` procedures are defined for a test, all of them will be executed after invoking the test. The order of execution for `--%aftertest` procedures is defined by: + - position of procedure on the list within single annotation - annotation position As a rule, the `--%aftertest` gets executed even if the associated `--%beforeeach`, `--%beforetest`, `--%test` or other `--%aftertest` procedures have raised unhandled exceptions. -```sql +```sql linenums="1" create or replace package test_package as --%suite(Tests for a package) @@ -1123,7 +1139,7 @@ create or replace package body test_package as end; / ``` -```sql +```sql linenums="1" exec ut.run('test_package'); ``` ``` @@ -1158,6 +1174,7 @@ Contexts allow for creating sub-suites within a suite package and they allow for In essence, context behaves like a suite within a suite. Context have following characteristics: + - context starts with the `--%context` annotation and ends with `--%endcontext`. Everything placed between those two annotations belongs to that context - can have a description provided as parameter for example `--%context(Some interesting stuff)`. - can have a name provided with `--%name` annotation. This is different than with `suite` and `test` annotations, where name is taken from `package/procedure` name. @@ -1175,7 +1192,7 @@ Context have following characteristics: The below example illustrates usage of `--%context` for separating tests for individual procedures of package. Sample tables and code -```sql +```sql linenums="1" create table rooms ( room_key number primary key, name varchar2(100) not null @@ -1232,11 +1249,12 @@ end; ``` Below test suite defines: + - `--%beforeall` outside of context, that will be executed before all tests - `--%context(remove_rooms_by_name)` to group tests related to `remove_rooms_by_name` functionality - `--%context(add_rooms_content)` to group tests related to `add_rooms_content` functionality -```sql +```sql linenums="1" create or replace package test_rooms_management is gc_null_value_exception constant integer := -1400; @@ -1355,8 +1373,8 @@ end; / ``` -When te tests are executed -```sql +When the tests are executed +```sql linenums="1" exec ut.run('test_rooms_management'); ``` The following report is displayed @@ -1378,7 +1396,7 @@ Finished in .035261 seconds Example of nested contexts test suite specification. *Source - [slide 145](https://www.slideshare.net/Kevlin/structure-and-interpretation-of-test-cases/145?src=clipshare) of Structure and Interpretation of Test Cases by Kevlin Henney* -```sql +```sql linenums="1" create or replace package queue_spec as --%suite(Queue specification) @@ -1468,7 +1486,7 @@ The `--%name` can be useful when you would like to run only a specific context o Consider the below example. -```sql +```sql linenums="1" create or replace package queue_spec as --%suite(Queue specification) @@ -1501,22 +1519,22 @@ end; In the above code, suitepaths, context names and context descriptions will be as follows. -| suitepath | description | name | -|-----------|------------|------| -| queue_spec | Queue specification | queue_spec | -| queue_spec.context_#1 | A new queue | context_#1 | -| queue_spec.context_#2 | An empty queue | context_#2 | -| queue_spec.context_#3 | A non empty queue | context_#3 | -| queue_spec.context_#3.context_#1 | that is not full | context_#1 | -| queue_spec.context_#3.context_#2 | that is full | context_#2 | +| suitepath | description | name | +|----------------------------------|----------------------|------------| +| queue_spec | Queue specification | queue_spec | +| queue_spec.context_#1 | A new queue | context_#1 | +| queue_spec.context_#2 | An empty queue | context_#2 | +| queue_spec.context_#3 | A non empty queue | context_#3 | +| queue_spec.context_#3.context_#1 | that is not full | context_#1 | +| queue_spec.context_#3.context_#2 | that is full | context_#2 | In order to run only the tests for the context `A non empty queue that is not full` you will need to call utPLSQL as below: -```sql +```sql linenums="1" exec ut.run(':queue_spec.context_#3.context_#1'); ``` You can use `--%name` annotation to explicitly name contexts on suitepath. -```sql +```sql linenums="1" create or replace package queue_spec as --%suite(Queue specification) @@ -1554,23 +1572,25 @@ end; In the above code, suitepaths, context names and context descriptions will be as follows. -| suitepath | description | name | -|-----------|------------|------| -| queue_spec | Queue specification | queue_spec | -| queue_spec.a_new_queue | A new queue | a_new_queue | -| queue_spec.an_empty_queue | An empty queue | an_empty_queue | -| queue_spec.a_non_empty_queue | A non empty queue | a_non_empty_queue | -| queue_spec.a_non_empty_queue.that_is_not_full | that is not full | that_is_not_full | -| queue_spec.a_non_empty_queue.that_is_full | that is full | that_is_full | +| suitepath | description | name | +|-----------------------------------------------|-----------------------|-------------------| +| queue_spec | Queue specification | queue_spec | +| queue_spec.a_new_queue | A new queue | a_new_queue | +| queue_spec.an_empty_queue | An empty queue | an_empty_queue | +| queue_spec.a_non_empty_queue | A non empty queue | a_non_empty_queue | +| queue_spec.a_non_empty_queue.that_is_not_full | that is not full | that_is_not_full | +| queue_spec.a_non_empty_queue.that_is_full | that is full | that_is_full | The `--%name` annotation is only relevant for: + - running subsets of tests by given context suitepath - some of test reports, like `ut_junit_reporter` that use suitepath or test-suite element names (not descriptions) for reporting #### Name naming convention The value of `--%name` annotation must follow the following naming rules: + - cannot contain spaces - cannot contain a `.` (full stop/dot) - is case-insensitive @@ -1583,13 +1603,13 @@ It allows for grouping of tests / suites using various categorization and place e.g. -```sql +```sql linenums="1" --%tags(batch,daily,csv) ``` or -```sql +```sql linenums="1" --%tags(online,json) --%tags(api) ``` @@ -1603,7 +1623,7 @@ When a suite/context is tagged, all of its children will automatically inherit t Sample test suite package with tags. -```sql +```sql linenums="1" create or replace package ut_sample_test is --%suite(Sample Test Suite) @@ -1643,17 +1663,17 @@ end ut_sample_test; Execution of the test is done by using the parameter `a_tags` -```sql +```sql linenums="1" select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'api')); ``` The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` -```sql +```sql linenums="1" select * from table(ut.run(a_tags => 'complex')); ``` The above call will execute only the `ut_sample_test.ut_refcursors1` test, as only the test `ut_refcursors1` is tagged with `complex` -```sql +```sql linenums="1" select * from table(ut.run(a_tags => 'fast')); ``` The above call will execute both `ut_sample_test.ut_refcursors1` and `ut_sample_test.ut_test` tests, as both tests are tagged with `fast` @@ -1677,7 +1697,7 @@ In order to do so, prefix the tag name to exclude with a `-` (dash) sign when in Examples (based on above sample test suite) -```sql +```sql linenums="1" select * from table(ut.run(a_tags => 'api,fast,-complex')); ``` The above call will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex`. @@ -1705,7 +1725,7 @@ If you want to create tests for your application it is recommended to structure The `--%suitepath` annotation is used for such grouping. Even though test packages are defined in a flat structure the `--%suitepath` is used by the framework to form them into a hierarchical structure. Your payments recognition test package might look like: -```sql +```sql linenums="1" create or replace package test_payment_recognition as --%suite(Payment recognition tests) @@ -1724,7 +1744,7 @@ end test_payment_recognition; ``` And payments set off test package: -```sql +```sql linenums="1" create or replace package test_payment_set_off as --%suite(Payment set off tests) @@ -1743,7 +1763,7 @@ When you execute tests for your application, the framework constructs a test sui The test report indicates which expectation has failed on the payments module. The payments recognition submodule is causing the failure as `recognize_by_num` has not met the expectations of the test. Grouping tests into modules and submodules using the `--%suitepath` annotation allows you to logically organize your project's flat structure of packages into functional groups. An additional advantage of such grouping is the fact that every element level of the grouping can be an actual unit test package containing a common module level setup for all of the submodules. So in addition to the packages mentioned above you could have the following package. -```sql +```sql linenums="1" create or replace package payments as --%suite(Payments) @@ -1758,6 +1778,7 @@ end payments; ``` When executing tests, `path` for executing tests can be provided in three ways: + * schema - execute all tests in the schema * [schema]:suite1[.suite2][.suite3]...[.procedure] - execute all tests by `suitepath` in all suites on path suite1[.suite2][.suite3]...[.procedure]. If schema is not provided, then the current schema is used. Example: `:all.rooms_tests` * [schema.]package[.procedure] - execute all tests in the specified test package. The whole hierarchy of suites in the schema is built before all before/after hooks or part suites for the provided suite package are executed as well. Example: `tests.test_contact.test_last_name_validator` or simply `test_contact.test_last_name_validator` if `tests` is the current schema. @@ -1798,6 +1819,7 @@ Keep in mind that when your test runs as autonomous transaction it will not see ### Throws 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)` @@ -1814,9 +1836,9 @@ 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. -​ + Example: -```sql +```sql linenums="1" create or replace package exc_pkg is c_e_option1 constant number := -20200; c_e_option2 constant varchar2(10) := '-20201'; @@ -1979,7 +2001,7 @@ Finished in .025784 seconds ## Order of execution -```sql +```sql linenums="1" create or replace package test_employee_pkg is --%suite(Employee management) @@ -2101,46 +2123,50 @@ When processing the test suite `test_employee_pkg` defined in [Example of annota rollback to savepoint 'before-suite' ``` -**Note** ->utPLSQL does not guarantee ordering of tests in suite. On contrary utPLSQL might give random order of tests/contexts in suite. -> ->Order of execution within multiple occurrences of `before`/`after` procedures is determined by the order of annotations in specific block (context/suite) of package specification. +!!! note + utPLSQL does not guarantee ordering of tests in suite. On contrary utPLSQL might give random order of tests/contexts in suite.
    + Order of execution within multiple occurrences of `before`/`after` procedures is determined by the order of annotations in specific block (context/suite) of package specification. ## sys_context It is possible to access information about currently running suite. The information is available by calling `sys_context( 'UT3_INFO', attribute )`. -It can be accessed from any procecure invoked as part of utPLSQL test execution. +It can be accessed from any procedure invoked as part of utPLSQL test execution. -**Note:** -> Context name is derived from schema name where utPLSQL is installed. -> The context name in below examples represents the default install schema -> `UT3` -> If you install utPLSQL into another schema the context name will be different. -> For example if utPLSQL is installed into `HR` schema, the context name will be `HR_INFO` +!!! note + Context name is derived from schema name where utPLSQL is installed.
    + The context name in below examples represents the default install schema -> `UT3`
    + If you install utPLSQL into another schema the context name will be different.
    + For example if utPLSQL is installed into `HR` schema, the context name will be `HR_INFO` Following attributes are populated: -- For entire duration of the test-run: - - `sys_context( 'UT3_INFO', 'COVERAGE_RUN_ID' );` - Value of COVERAGE_RUN_ID used by utPLSQL internally for coverage gathering - - `sys_context( 'UT3_INFO', 'RUN_PATHS' );` - list of suitepaths / suitenames used as input parameters for call to `ut.run(...)` or `ut_runner.run(...)` - - `sys_context( 'UT3_INFO', 'SUITE_DESCRIPTION' );` - the description of test suite that is currently being executed - - `sys_context( 'UT3_INFO', 'SUITE_PACKAGE' );` - the owner and name of test suite package that is currently being executed - - `sys_context( 'UT3_INFO', 'SUITE_PATH' );` - the suitepath for the test suite package that is currently being executed - - `sys_context( 'UT3_INFO', 'SUITE_START_TIME' );` - the execution start timestamp of test suite package that is currently being executed - - `sys_context( 'UT3_INFO', 'CURRENT_EXECUTABLE_NAME' );` - the owner.package.procedure of currently running test suite executable - - `sys_context( 'UT3_INFO', 'CURRENT_EXECUTABLE_TYPE' );` - the type of currently running test suite executable (one of: `beforeall`, `beforeeach`, `beforetest`, `test`, `aftertest`, `aftereach`, `afterall` - -- When running in suite context - - `sys_context( 'UT3_INFO', 'CONTEXT_DESCRIPTION' );` - the description of test suite context that is currently being executed - - `sys_context( 'UT3_INFO', 'CONTEXT_NAME' );` - the name of test suite context that is currently being executed - - `sys_context( 'UT3_INFO', 'CONTEXT_PATH' );` - the suitepath for the currently executed test suite context - - `sys_context( 'UT3_INFO', 'CONTEXT_START_TIME' );` - the execution start timestamp for the currently executed test suite context -- When running a suite executable procedure that is a `test` or `beforeeach`, `aftereach`, `beforetest`, `aftertest` - - `sys_context( 'UT3_INFO', 'TEST_DESCRIPTION' );` - the description of test for which the current executable is being invoked - - `sys_context( 'UT3_INFO', 'TEST_NAME' );` - the name of test for which the current executable is being invoked - - `sys_context( 'UT3_INFO', 'TEST_START_TIME' );` - the execution start timestamp of test that is currently being executed (the time when first `beforeeach`/`beforetest` was called for that test) + +| Name | Scope | Description | +|-------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| +| COVERAGE_RUN_ID | run | Value of COVERAGE_RUN_ID used by utPLSQL internally for coverage gathering | +| RUN_PATHS | run | list of suitepaths / suitenames used as input parameters for call to `ut.run(...)` or `ut_runner.run(...)` | +| SUITE_DESCRIPTION | run | the description of test suite that is currently being executed | +| SUITE_PACKAGE | run | the owner and name of test suite package that is currently being executed | +| SUITE_PATH | run | the suitepath for the test suite package that is currently being executed | +| SUITE_START_TIME | run | the execution start timestamp of test suite package that is currently being executed | +| CURRENT_EXECUTABLE_NAME | run | the owner.package.procedure of currently running test suite executable | +| CURRENT_EXECUTABLE_TYPE | run | the type of currently running test suite executable (one of: `beforeall`, `beforeeach`, `beforetest`, `test`, `aftertest`, `aftereach`, `afterall` | + | CONTEXT_DESCRIPTION | suite context | the description of test suite context that is currently being executed | + | CONTEXT_NAME | suite context | the name of test suite context that is currently being executed | + | CONTEXT_PATH | suite context | the suitepath for the currently executed test suite context | + | CONTEXT_START_TIME | suite context | the execution start timestamp for the currently executed test suite context | +| TEST_DESCRIPTION | test* | the description of test for which the current executable is being invoked | +| TEST_NAME | test* | the name of test for which the current executable is being invoked | +| TEST_START_TIME | test* | the execution start timestamp of test that is currently being executed (the time when first `beforeeach`/`beforetest` was called for that test) | + +!!! note "Scopes" + - run - context information is available in any element of test run
    + - suite context - context information is available in any element nested within a suite context
    + - test* - context information is available when executing following procedure types: test, beforetest, aftertest, beforeeach or aftereach + Example: -```sql +```sql linenums="1" create or replace procedure which_procecure_called_me is begin dbms_output.put_line( @@ -2199,7 +2225,7 @@ end; / ``` -```sql +```sql linenums="1" exec ut.run('test_call'); ``` @@ -2232,14 +2258,14 @@ If you are in a situation where your database is controlled via CI/CD server and To build the annotation cache without actually invoking any tests, call `ut_runner.rebuild_annotation_cache(a_object_owner)` for every unit test owner for which you want to have the annotation cache prebuilt. Example: -```sql +```sql linenums="1" exec ut_runner.rebuild_annotation_cache('HR'); ``` To purge the annotation cache call `ut_runner.purge_cache(a_object_owner, a_object_type)`. Both parameters are optional and if not provided, all owners/object_types will be purged. Example: -```sql +```sql linenums="1" exec ut_runner.purge_cache('HR', 'PACKAGE'); ``` diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 1a227d9e4..20707e917 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -9,9 +9,14 @@ Code coverage is gathered for the following source types: * procedures * functions -**Note** +!!! note -> The package and type specifications are excluded from code coverage analysis. This limitation is introduced to avoid false-negatives. Typically package specifications contain no executable code. The only exception is initialization of global constants and variables in package specification. Since most package specifications are not executable at all, there is no information available on the number of lines covered and those would be reported as 0% covered, which is not desirable. + The package and type specifications are excluded from code coverage analysis. + This limitation is introduced to avoid false-negatives. + Typically package specifications contain no executable code. + The only exception is initialization of global constants and variables in package specification. + Since most package specifications are not executable at all, there is no information available + on the number of lines covered and those would be reported as 0% covered, which is not desirable. To obtain information about code coverage for unit tests, run utPLSQL with one of built-in code coverage reporters. The following code coverage reporters are supplied with utPLSQL: @@ -39,7 +44,7 @@ Using the code coverage functionality is as easy as using any other [reporter](r All you need to do, is pass the constructor of the reporter to the `ut.run` procedure call. Example: -```sql +```sql linenums="1" set serveroutput on begin ut.run(ut_coverage_html_reporter()); @@ -58,7 +63,7 @@ The report allow you to navigate to each source file and inspect line by line co ![Coverage Details page](../images/coverage_html_details.png) -#### Oracle 12.2 extended coverage with profiler and block coverage +### Oracle 12.2 extended coverage with profiler and block coverage Using data collected from profiler and block coverage running parallel we are able to enrich information about coverage. For every line recorded by the profiler if we have a partially covered same line in block coverage we will display that information presenting line as partially covered, displaying number of block and how many blocks have been covered in that line.The feature will be automatically enabled in the Oracle database version 12.2 and higher, for older versions current profiler will be used. @@ -89,8 +94,8 @@ The parameters used to execute tests determine if utPLSQL will be using one appr If parameter `a_source_file_mappings` or `a_source_files` is provided, then coverage is gathered on project files provided, otherwise coverage is gathered on schemas. -**Note** -> Regardless of the options provided, all unit test packages are excluded from the coverage report. Coverage reports provide information only about the **tested** code. +!!! note + Regardless of the options provided, all unit test packages are excluded from the coverage report. Coverage reports provide information only about the **tested** code. The default behavior of coverage reporting can be altered using invocation parameters. @@ -99,17 +104,16 @@ The default behavior of coverage reporting can be altered using invocation param To gather coverage for all objects in the **current schema** execute tests with coverage report as argument. This is the default reporting option and therefore additional coverage options don't need to be provided. -```sql +```sql linenums="1" exec ut.run(ut_coverage_html_reporter()); ``` -**Note** +!!! note -> When no filters are used, the size of the coverage report will depend two factors: -> - the type of report (does the report include source code or not) -> - the amount of source code in the database schema -> ->Keep in mind that for schemas containing a lot of code, it can take quite some time to produce the coverage report. + When no filters are used, the size of the coverage report will depend two factors:
    + - the type of report (does the report include source code or not)
    + - the amount of source code in the database schema
    + Keep in mind that for schemas containing a lot of code, it can take quite some time to produce the coverage report. #### Setting coverage schema(s) @@ -117,7 +121,7 @@ By default, coverage is gathered on the schema(s) derived from suite paths provi This is a valid approach as long as your test packages and tested code share the same schema. So when you run: -```sql +```sql linenums="1" exec ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter()); ``` Coverage will be gathered on both `user_1` and `user_2` objects. @@ -126,13 +130,18 @@ If your tests live in a different schema from the tested code you may override t In the example below, coverage will still be gathered for `user_1` and `user_2` objects, even thought we run the tests located in schema `unit_test_schema` -```sql -exec ut.run('unit_test_schema', ut_coverage_html_reporter(), a_coverage_schemes => ut_varchar2_list('user_1','user_2') ); +```sql linenums="1" +begin + ut.run('unit_test_schema', ut_coverage_html_reporter(), + a_coverage_schemes => ut_varchar2_list('user_1','user_2') + ); +end; ``` #### Filtering objects in coverage reports Multiple parameters can be used to define the scope of coverage report. + - `a_source_file_mappings ( ut_file_mappings )` - map of filenames to database objects. It is used for file-based coverage - see below. - `a_include_schema_expr ( varchar(4000) )` - string of regex expression of schemas to be included in the coverage report. Case-insensitive. - `a_include_object_expr ( varchar(4000) )` - string of regex expression of objects ( without schema name ) to be included in the coverage report. Case-insensitive. @@ -144,22 +153,23 @@ Multiple parameters can be used to define the scope of coverage report. You may specify both _include_ and _exclude_ options to gain more control over what needs to be included / excluded from the coverage report. -**Important notes** -The order of priority is for evaluation of include/exclude filter parameters is as follows. -- if `a_source_file_mappings` is defined then all include/exclude parameters are ignored (see section below for usage of `a_source_file_mappings` parameter ) -- else if `a_include_schema_expr` or `a_include_object_expr` parameter is specified then parameters `a_coverage_schemes` and `a_include_objects` are ignored -- else if `a_include_objects` is specified then the coverage is gathered only on specified database objects. - - if `a_coverage_schemes` is specified then those schemas are used for objects in `a_include_objects` without schema name - - if `a_coverage_schemes` is not specified then schema from paths (`a_paths`) parameter are used for objects in `a_include_objects` without schema name -- else if, only the `a_coverage_schemes` is specified then the coverage is gathered only on specified database schemas -- else if no coverage specific parameters are provided coverage is gathered on all schemas specified in paths passed to run procedure -- else if no paths were specified, the coverage is gathered on current schema of the session running the tests +!!! warning "Important note" + The order of priority is for evaluation of include/exclude filter parameters is as follows.
    + - if `a_source_file_mappings` is defined then all include/exclude parameters are ignored (see section below for usage of `a_source_file_mappings` parameter )
    + - else if `a_include_schema_expr` or `a_include_object_expr` parameter is specified then parameters `a_coverage_schemes` and `a_include_objects` are ignored
    + - else if `a_include_objects` is specified then the coverage is gathered only on specified database objects.
    + - if `a_coverage_schemes` is specified then those schemas are used for objects in `a_include_objects` without schema name
    + - if `a_coverage_schemes` is not specified then schema from paths (`a_paths`) parameter are used for objects in `a_include_objects` without schema name
    + - else if, only the `a_coverage_schemes` is specified then the coverage is gathered only on specified database schemas
    + - else if no coverage specific parameters are provided coverage is gathered on all schemas specified in paths passed to run procedure
    + - else if no paths were specified, the coverage is gathered on current schema of the session running the tests + The exclude parameters are not mutually-exclusive and can be mixed together. All of exclude parameters are always applied. Example: Limiting coverage by schema regex. -```sql +```sql linenums="1" begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_include_schema_expr => '^ut3_develop' @@ -169,7 +179,7 @@ end; Will result in showing coverage for all schemas that match regular expression `^ut3_develop` Example: Limiting coverage by schema regex with parameter `a_include_objects` ignored. -```sql +```sql linenums="1" begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_include_schema_expr => '^ut3_develop', a_include_objects => ut_varchar2_list( 'ut3_tester_helper.regex_dummy_cov' ) @@ -179,7 +189,7 @@ end; Will result in showing coverage for all schemas that match regular expression `^ut3_develop`. Example: Limiting coverage by object regex. -```sql +```sql linenums="1" begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_include_object_expr => 'regex123' @@ -189,7 +199,7 @@ end; Will result in showing coverage for all objects that name match regular expression `regex123`. Example: Limiting coverage by object regex with parameter `a_include_objects` ignored. -```sql +```sql linenums="1" begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_include_object_expr => 'utl', a_include_objects => ut_varchar2_list( 'user_2.utils_package' ) @@ -199,7 +209,7 @@ end; Will result in showing coverage for all objects that name match regular expression `utl`. Example: Limiting coverage by excluding schema with regex. -```sql +```sql linenums="1" begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_exclude_schema_expr => 'er_1$' @@ -209,7 +219,7 @@ end; Will result in showing coverage for objects in all schema except schemas that are matching regular expression `er_1$` Example: Limiting coverage by excluding schema with regex and excluding specific object. -```sql +```sql linenums="1" begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_exclude_schema_expr => 'er_1$', a_exclude_objects => ut_varchar2_list( 'user_2.utils_package' ) @@ -220,7 +230,7 @@ Will result in showing coverage for objects in all schemas except schemas that a Will also exclude object `user_2.utils_package` from coverage report Example: Limiting coverage by excluding objects with regex. -```sql +```sql linenums="1" begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_exclude_object_expr => 'utl' @@ -230,7 +240,7 @@ end; Will result in showing coverage for all objects that name is not matching regular expression `utl`. Example: Limiting coverage by excluding objects with regex with parameter `a_exclude_objects` ignored. -```sql +```sql linenums="1" begin ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_exclude_object_expr => 'utl', a_exclude_objects => ut_varchar2_list( 'user_2.utils_package' ) @@ -242,14 +252,18 @@ Will also exclude object `user_2.utils_package` from coverage report Example: Limiting coverage by object name, for tested code located in the same schema as the unit tests. -```sql -exec ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), a_include_objects=>ut_varchar2_list('award_bonus')); +```sql linenums="1" +begin + ut.run(ut_varchar2_list('user_1','user_2'), ut_coverage_html_reporter(), + a_include_objects=>ut_varchar2_list('award_bonus') + ); +end; ``` Executes all tests in schemas: `user_1` and `user_2`. Coverage will only be reported on objects `user_1.award_bonus`, `user_2.award_bonus` Example: Limiting coverage by object name, for tested code located in different schemas than the unit tests. -```sql +```sql linenums="1" begin ut.run( 'unit_test_schema', ut_coverage_html_reporter(), @@ -262,7 +276,7 @@ Executes all tests in schema `unit_test_schema`. Coverage will only be reported Objects that do not exist in the database but were specified in `a_include_objects` will be ignored. Example: Limiting coverage by object owner and name. -```sql +```sql linenums="1" begin ut.run( 'unit_test_schema', ut_coverage_html_reporter(), @@ -275,7 +289,7 @@ Executes all tests in schema `unit_test_schema`. Coverage will only be reported The `a_exclude_objects` can be used in the same way as `a_include_objects`. Example: Excluding objects from coverage report by providing a list of object owner/name to be excluded. -```sql +```sql linenums="1" begin ut.run( 'unit_test_schema.test_award_bonus', ut_coverage_html_reporter(), @@ -285,12 +299,12 @@ end; ``` Executes test `test_award_bonus` in schema `unit_test_schema`. Coverage will be reported on all objects in schema `ut3_user` except the `betwnstr` object. -**Note** -> Filtering using `a_include_objects` and `a_exclude_objects` is only applicable when gathering coverage for a schema. Those filters are not applied when reporting coverage on project files. +!!! note + Filtering using `a_include_objects` and `a_exclude_objects` is only applicable when gathering coverage for a schema. Those filters are not applied when reporting coverage on project files. -**Note** -> When running coverage on schema objects, all source code of package bodies, functions, procedures, type bodies and triggers that were not executed will be reported as having 0% code coverage and all source code lines will show as uncovered. -> This is different from the behavior when gathering coverage on project files. +!!! note + When running coverage on schema objects, all source code of package bodies, functions, procedures, type bodies and triggers that were not executed will be reported as having 0% code coverage and all source code lines will show as uncovered. + This is different from the behavior when gathering coverage on project files. ### Project based Coverage @@ -345,16 +359,17 @@ By default, utPLSQL will convert file paths into database objects using the foll - object type is identified by the expression in the sixth set of brackets -**Note** -> utPLSQL will replace any '\\' with '/' for the purpose of mapping files to objects. The paths shown in the results will remain (contain '\' where it was present). -> This is done to simplify the syntax of regular expressions. Regular expression will always use '/' as a directory separator on a file path regardless of whether you're on a Windows or Unix system. +!!! note + utPLSQL will replace any '\\' with '/' for the purpose of mapping files to objects. The paths shown in the results will remain (contain '\' where it was present). + This is done to simplify the syntax of regular expressions. Regular expression will always use '/' as a directory separator on a file path regardless of whether you're on a Windows or Unix system. -**Note** -> Below examples assume that you have downloaded latest version of [utPLSQL-cli](https://github.com/utPLSQL/utPLSQL-cli/releases) and extracted it into your projects root directory (my_project). -> The examples assume that you run the utPLSQL-cli from `my_project` directory. +!!! note + Below examples assume that you have downloaded latest version of [utPLSQL-cli](https://github.com/utPLSQL/utPLSQL-cli/releases) + and extracted it into your projects root directory + and that you run the utPLSQL-cli from that directory. Windows: -``` +```pwsh utPLSQL-cli\bin\utplsql run test_runner/pass@db_host:db_port/db_service_name ^ -p=hr,hotel ^ -source_path=sources ^ @@ -374,6 +389,7 @@ utPLSQL-cli/bin/utplsql run test_runner/pass@db_host:db_port/db_service_name \ ``` The above commands will: + - connect as user `test_runner` - run all utPLSQL v3 tests for users `hr`, `hotel` - map database code to project files in `sources` directory and save code coverage results into `coverage.html` @@ -424,7 +440,7 @@ Note that the owner/name/type subexpressions don't need to be explicitly specifi In the below example, they were specified explicitly only for `source_path`, `test_path` doesn't have subexpressions specified and so they are default (2/3/4). Windows: -``` +```pwsh utPLSQL-cli\bin\utplsql run test_runner/pass@db_url ^ -p=hr,hotel ^ -source_path=sources ^ @@ -487,7 +503,7 @@ For the database objects mapped to `souces` directory user `code_owner` will be For the database objects mapped to `tests` directory user `tests_owner` will be used. Windows: -``` +```pwsh utPLSQL-cli\bin\utplsql run test_runner/pass@db_url ^ -p=tests_owner ^ -source_path=sources -owner=code_owner ^ @@ -506,9 +522,9 @@ utPLSQL-cli/bin/utplsql run test_runner/pass@db_url \ -f=ut_sonar_test_reporter -o=test_results.xml ``` -**Note** -> When the project folder structure does not provide any information about source code owner and test owner, you can specify the owner for tests and owner for code explicitly. -> Such project configuration supports only single-owner for source code and single owner for tests. +!!! note + When the project folder structure does not provide any information about source code owner and test owner, you can specify the owner for tests and owner for code explicitly. + Such project configuration supports only single-owner for source code and single owner for tests. Tested code is mapped to files in `coverage.html` @@ -585,7 +601,7 @@ C: Windows: -``` +```pwsh utPLSQL-cli\bin\utplsql run test_runner/pass@db_url ^ -p=hr,hotel ^ -source_path=sources ^ @@ -636,7 +652,8 @@ Unit test code is mapped to files in `test_results.xml` #### Object-file mapping rules -In order to allow deterministic and accurate mapping of database source-code into project files, the project directory and file structure needs to meet certain criteria. +In order to allow deterministic and accurate mapping of database source-code into project files, the project directory and file structure needs to meet certain criteria. + - Source code is kept separate from test code (separate directories) - Each database (source-code) object is stored in an individual file. Package/type specification is kept separate from its body. - File name (file path) contains the name of database object @@ -650,6 +667,7 @@ In order to allow deterministic and accurate mapping of database source-code int The `ut.run` command provides interface to map project into database objects when executing tests. While it is much easier to perform mapping directly from command line, it is possible to achieve similar functionality from any SQL client. The main differences when using the `ut.run(...)` command, will be: + - you can only use single reporter and therefore will get only one report from test execution - you need to provide fill list of project files rather than point to `sources` and `tests` directories @@ -701,7 +719,7 @@ C: To execute all tests and map database source code into source file names you could use the following command in any SQL client: -```sql +```sql linenums="1" begin ut.run( ut_varchar2_list('hr','hotel'), @@ -733,7 +751,7 @@ end; ``` To execute all tests and map database tests code into test file names you could use the following command in any SQL client: -```sql +```sql linenums="1" begin ut.run( ut_varchar2_list('hr','hotel'), @@ -778,7 +796,7 @@ Following API calls enable the standalone coverage reporting. - `.get_report_cursor( ... )` - coverage reporters function producing coverage report as ref-cursor Example: -```sql +```sql linenums="1" --SESSION 1 -- gather coverage on code using specific coverage_run_id value declare @@ -795,7 +813,7 @@ end; / ``` -```sql +```sql linenums="1" --SESSION 2 -- alternative approach -- gather coverage on code using specific coverage_run_id value @@ -807,7 +825,7 @@ exec ut_runner.coverage_stop(); ``` -```sql +```sql linenums="1" --SESSION 1 or SESSION2 2 or SESSION 3 -- run after calls in SESSION 1 & 2 are finished -- retrieve coverage report in HTML format coverage_run_id value @@ -821,7 +839,7 @@ select * ); ``` -```sql +```sql linenums="1" --SESSION 1 or SESSION2 2 or SESSION 3 -- run after calls in SESSION 1 & 2 are finished declare @@ -839,20 +857,20 @@ end; ``` Specification of parameters for `get_report` and `get_report_cursor` -```sql +```sql linenums="1" function get_report( a_coverage_options ut_coverage_options, a_client_character_set varchar2 := null ) return ut_varchar2_rows pipelined ``` -```sql +```sql linenums="1" function get_report_cursor( a_coverage_options ut_coverage_options, a_client_character_set varchar2 := null ) return sys_refcursor ``` -```sql +```sql linenums="1" ut_coverage_options( coverage_run_id raw, schema_names ut_varchar2_rows := null, diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index d83142f9f..c795c5421 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,23 +1,29 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) -The utPLSQL is responsible for handling exceptions wherever they occur in the test run. utPLSQL is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. -The framework provides a full stacktrace for every exception that was thrown. The stacktrace is clean and does not include any utPLSQL library calls in it. +utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. +The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. To achieve rerunability, the package state invalidation exceptions (ORA-04068, ORA-04061) are not handled and test execution will be interrupted if such exceptions are encountered. This is because of how Oracle behaves on those exceptions. Test execution can fail for different reasons. The failures on different exceptions are handled as follows: -* A test package without body - each `--%test` is reported as failed with exception, nothing is executed -* A test package with _invalid body_ - each `--%test` is reported as failed with exception, nothing is executed -* A test package with _invalid spec_ - package is not considered a valid unit test package and is excluded from execution. When trying to run a test package with invalid spec explicitly, exception is raised. Only valid specifications are parsed for annotations -* A test package that is raising an exception in `--%beforeall` - each `--%test` is reported as failed with exception, `--%test`, `--%beforeeach`, `--%beforetest`, `--%aftertest` and `--%aftereach` are not executed. `--%afterall` is executed to allow cleanup of whatever was done in `--%beforeall` -* A test package that is raising an exception in `--%beforeeach` - each `--%test` is reported as failed with exception, `--%test`, `--%beforetest` and `--%aftertest` is not executed. The `--%aftereach` and `--%afterall` blocks are getting executed to allow cleanup of whatever was done in `--%before...` blocks -* A test package that is raising an exception in `--%beforetest` - the `--%test` is reported as failed with exception, `--%test` is not executed. The `--%aftertest`, `--%aftereach` and `--%afterall` blocks are getting executed to allow cleanup of whatever was done in `--%before...` blocks -* A test package that is raising an exception in `--%test` - the `--%test` is reported as failed with exception. The execution of other blocks continues normally -* A test package that is raising an exception in `--%aftertest` - the `--%test` is reported as failed with exception. The execution of other blocks continues normally -* A test package that is raising an exception in `--%aftereach` - each `--%test` is reported as failed with exception. -* A test package that is raising an exception in `--%afterall` - all blocks of the package are executed, as the `--%afterall` is the last step of package execution. Exception in `--%afterall` is not affecting test results. A warning with exception stacktrace is displayed in the summary +| Problem / error | Framework behavior | +|----------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| A test package **without body** | each `--%test` is reported as failed with exception, nothing is executed | +| A test package with **invalid body** | each `--%test` is reported as failed with exception, nothing is executed | +| A test package with **invalid spec** | package is not considered a valid unit test package and is excluded from execution. When trying to run a test package with invalid spec explicitly, exception is raised. Only valid specifications are parsed for annotations | +| A test package that is raising an exception in `--%beforeall` | each `--%test` is reported as failed with exception, `--%test`, `--%beforeeach`, `--%beforetest`, `--%aftertest` and `--%aftereach` are not executed. `--%afterall` is executed to allow cleanup of whatever was done in `--%beforeall` | +| A test package that is raising an exception in `--%beforeeach` | each `--%test` is reported as failed with exception, `--%test`, `--%beforetest` and `--%aftertest` is not executed. The `--%aftereach` and `--%afterall` blocks are getting executed to allow cleanup of whatever was done in `--%before...` blocks | +| A test package that is raising an exception in `--%beforetest` | the `--%test` is reported as failed with exception, `--%test` is not executed. The `--%aftertest`, `--%aftereach` and `--%afterall` blocks are getting executed to allow cleanup of whatever was done in `--%before...` blocks | +| A test package that is raising an exception in `--%test` | the `--%test` is reported as failed with exception. The execution of other blocks continues normally | +| A test package that is raising an exception in `--%aftertest` | the `--%test` is reported as failed with exception. The execution of other blocks continues normally | +| A test package that is raising an exception in `--%aftereach` | each `--%test` is reported as failed with exception. | +| A test package that is raising an exception in `--%afterall` | all blocks of the package are executed, as the `--%afterall` is the last step of package execution. Exception in `--%afterall` is not affecting test results. A warning with exception stacktrace is displayed in the summary | +!!! warning + If an exception is thrown in an `afterall` procedure then **no failure reported by utPLSQL**.
    + Framework will only report a warning on the suite that the `afterall` belongs to. + Example of reporting with exception thrown in `%beforetest`: ```` Remove rooms by name diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 1c1974319..a972fa2e3 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -7,7 +7,7 @@ Validation of the code under test (the tested logic of procedure/function etc.) utPLSQL uses expectations and matchers to perform the check on the data. Example of an expectation -```sql +```sql linenums="1" begin ut.expect( 'the tested value' ).to_equal('the expected value'); end; @@ -22,6 +22,7 @@ FAILURE ``` Expectation is a combination of: + - the expected value - optional custom message for the expectation - the matcher used to perform comparison @@ -30,7 +31,7 @@ Expectation is a combination of: Matcher defines the comparison operation to be performed on expected (and actual) value. Pseudo-code: -```sql +```sql linenums="1" ut.expect( a_actual {data-type} [, a_message {varchar2}] ).to_( {matcher} ); ut.expect( a_actual {data-type} [, a_message {varchar2}] ).not_to( {matcher} ); ``` @@ -38,7 +39,7 @@ Pseudo-code: Expectations provide two variants of syntax that you can use. Both variants are functionally-equal but give different usage flexibility. Syntax where matcher is passed as parameter to the expectation: -```sql +```sql linenums="1" ut.expect( a_actual ).to_( {matcher} ); ut.expect( a_actual ).not_to( {matcher} ); -- example @@ -46,7 +47,7 @@ Syntax where matcher is passed as parameter to the expectation: ``` Shortcut syntax, where matcher is directly part of expectation: -```sql +```sql linenums="1" ut.expect( a_actual ).to_{matcher}; ut.expect( a_actual ).not_to_{matcher}; @@ -57,7 +58,7 @@ Shortcut syntax, where matcher is directly part of expectation: When using shortcut syntax you don't need to surround matcher with brackets. Shortcut syntax is provided for convenience. If you would like to perform more dynamic checks in your code, you could pass the matcher into a procedure like in the below example: -```sql +```sql linenums="1" declare procedure do_check( p_actual varchar2, p_matcher ut_matcher ) is begin @@ -80,8 +81,8 @@ SUCCESS Actual: 'Alibaba' (varchar2) was expected to match: 'ali' , modifiers 'i' ``` -**Note:** -> The examples in the document will be only using shortcut syntax, to keep the document brief. +!!! note + In order to keep the document brief, the examples in the document are only using the standalone expectations syntax. ## Using expectations @@ -91,17 +92,19 @@ There are two ways to use expectations: ## Running expectations within utPLSQL framework -When expectations are ran as a part of a test suite, the framework tracks: +When expectations are run as a part of a test suite, the framework tracks: + - status of each expectation - outcomes (messages) produced by each expectation - call stack to each expectation In this case: + - expectation results of are not sent directly to `dbms_output` - utPLSQL Reporters used when running suite decide on how the expectation results are formatted and displayed Example of test suite with an expectation: -```sql +```sql linenums="1" create or replace package test_divide as --%suite(Divide two numbers) @@ -159,15 +162,13 @@ Please read about different options for [running test suites](running-unit-tests ## Running expectations outside utPLSQL framework When expectations are invoked outside of utPLSQL framework the outputs from expectations are redirected straight to `dbms_output`. -**Note:** -> The output from expectation contains call stack trace only when expectation fails. -> Source code of the line which called the expectation is only reported when the line is part of in-database code (package) and the user calling expectation has privileges to see that source code. +!!! note + The output from expectation contains call stack trace only when expectation fails.
    + Source code of the line which called the expectation is only reported when the line is part of in-database code (package) and the user calling expectation has privileges to see that source code. -**Important** -> Please do not use expectations as part of your production code. They are not designed to be used as part of your code. Expectations are meant to be used only as part of your day-to-day testing activities. +!!! warning "**Important**" + Please do not use expectations as part of your production code. They are not designed to be used as part of your code. Expectations are meant to be used only as part of your day-to-day testing activities. -**Note:** -> The examples in the document will be only using standalone expectations, to keep the document brief. ## Matchers utPLSQL provides the following matchers to perform checks on the expected and actual values. @@ -193,7 +194,7 @@ You can provide a custom failure message by passing it as the second parameter t `ut.expect( a_actual {data-type}, a_message {varchar2} ).to_{matcher}` Example: -````sql +````sql linenums="1" exec ut.expect( 'supercat', 'checked superhero-animal was not a dog' ).to_equal('superdog'); ```` @@ -208,6 +209,7 @@ If the message is provided, it is being added to the normal failure message retu This is mostly useful when your expectations accept dynamic content, as you can provide additional context to make failing test results more readable. In most cases, there is no need to provide custom message to expectation. This is because utPLSQL identifies: + - The test used to execute the expectation - The line number where the expectation is placed in your test code - The line text of the expectation @@ -215,7 +217,7 @@ In most cases, there is no need to provide custom message to expectation. This i Custom message is useful, if your expectation is placed in a shared procedure to perform a check and your test is using the procedure multiple times. Example: -```sql +```sql linenums="1" create or replace package shared_expectation_test is --%suite @@ -265,6 +267,7 @@ Finished in .066344 seconds ``` In the tests results window you can see the list of failed expectations for a test as well as: + - the additional message for expectation - the reason why the expectation failed - the line number of the expectation @@ -276,7 +279,7 @@ In the tests results window you can see the list of failed expectations for a te Expectations provide a very convenient way to perform a check on a negated matcher. Syntax to check for matcher evaluating to true: -```sql +```sql linenums="1" begin ut.expect( a_actual {data-type} ).to_{matcher}; ut.expect( a_actual {data-type} ).to_( {matcher} ); @@ -284,7 +287,7 @@ end; ``` Syntax to check for matcher evaluating to false: -```sql +```sql linenums="1" begin ut.expect( a_actual {data-type} ).not_to_{matcher}; ut.expect( a_actual {data-type} ).not_to( {matcher} ); @@ -294,7 +297,7 @@ end; If a matcher evaluated to NULL, then both `to_` and `not_to` will cause the expectation to report failure. Example: -```sql +```sql linenums="1" declare l_actual boolean; begin @@ -346,7 +349,7 @@ Testing is not limited to checking for happy-path scenarios. When writing tests, Use the `--%throws` annotation, to test for expected exceptions. Example: -```sql +```sql linenums="1" create or replace function divide(x varchar2, y varchar2) return number is begin return x/y; @@ -397,7 +400,7 @@ You can choose different matchers to validate that your PL/SQL code is working a Validates that the actual value is between the lower and upper bound. Example: -```sql +```sql linenums="1" declare l_timestamp timestamp := current_timestamp; l_timestamp_tz timestamp with time zone := systimestamp; @@ -454,12 +457,12 @@ Unary matcher that validates if the provided dataset is empty. Can be used with `BLOB`,`CLOB`, `refcursor` or `nested table`/`varray` passed as `ANYDATA` -**Note:** -BLOB/CLOB that is initialized is not NULL but it is actually equal to `empty_blob()`/`empty_clob()`. +!!! note + BLOB/CLOB that is initialized is not NULL but it is actually equal to `empty_blob()`/`empty_clob()`. Example: -```sql +```sql linenums="1" declare l_cursor sys_refcursor; begin @@ -502,7 +505,7 @@ FAILURE Unary matcher that validates if the provided value is false. Usage: -```sql +```sql linenums="1" begin ut.expect( ( 1 = 0 ) ).to_be_false(); ut.expect( ( 1 = 1 ) ).to_( be_false() ); @@ -530,7 +533,7 @@ SUCCESS Checks if the actual value is greater or equal than the expected. Usage: -```sql +```sql linenums="1" begin ut.expect( sysdate ).to_be_greater_or_equal( sysdate - 1 ); ut.expect( sysdate ).to_( be_greater_or_equal( sysdate + 1 ) ); @@ -558,7 +561,7 @@ SUCCESS Checks if the actual value is greater than the expected. Usage: -```sql +```sql linenums="1" begin ut.expect( 2 ).to_be_greater_than( 1 ); ut.expect( 0 ).to_( be_greater_than( 1 ) ); @@ -586,7 +589,7 @@ SUCCESS Checks if the actual value is less or equal than the expected. Usage: -```sql +```sql linenums="1" begin ut.expect( 3 ).to_be_less_or_equal( 3 ); ut.expect( 4 ).to_( be_less_or_equal( 3 ) ); @@ -614,7 +617,7 @@ SUCCESS Checks if the actual value is less than the expected. Usage: -```sql +```sql linenums="1" begin ut.expect( 3 ).to_be_less_than( 2 ); ut.expect( 0 ).to_( be_less_than( 2 ) ); @@ -650,7 +653,7 @@ Parameters `a_mask` and `a_escape_char` represent valid parameters of the [Oracl If you use Oracle Database version 11.2.0.4, you may run into Oracle Bug 14402514: WRONG RESULTS WITH LIKE ON CLOB USING ESCAPE CHARACTER. In this case we recommend to use `match` instead of `be_like`. Usage: -```sql +```sql linenums="1" begin ut.expect( 'Lorem_impsum' ).to_be_like( '%rem%'); ut.expect( 'Lorem_impsum' ).to_be_like( '%rem\_i%', '\' ); @@ -680,7 +683,7 @@ SUCCESS Unary matcher that validates if the actual value is not null. Usage: -```sql +```sql linenums="1" begin ut.expect( to_clob('ABC') ).to_be_not_null(); ut.expect( to_clob('') ).to_( be_not_null() ); @@ -708,7 +711,7 @@ SUCCESS Unary matcher that validates if the actual value is null. Usage: -```sql +```sql linenums="1" begin ut.expect( '' ).to_be_null(); ut.expect( 0 ).to_( be_null() ); @@ -736,7 +739,7 @@ SUCCESS Unary matcher that validates if the provided value is true. Usage: -```sql +```sql linenums="1" begin ut.expect( ( 1 = 0 ) ).to_be_true(); ut.expect( ( 1 = 1 ) ).to_( be_true() ); @@ -766,7 +769,7 @@ Unary matcher that validates if the provided dataset count is equal to expected Can be used with `refcursor`, `json` or `table type` Usage: -```sql +```sql linenums="1" declare l_cursor sys_refcursor; l_collection ut_varchar2_list; @@ -806,7 +809,7 @@ Syntax: Parameters `a_pattern` and `a_modifiers` represent a valid regexp pattern accepted by [Oracle REGEXP_LIKE condition](https://docs.oracle.com/database/121/SQLRF/conditions007.htm#SQLRF00501) Usage: -```sql +```sql linenums="1" begin ut.expect( '123-456-ABcd' ).to_match( '\d{3}-\d{3}-[a-z]{4}', 'i' ); ut.expect( 'some value' ).to_( match( '^some.*' ) ) ; @@ -844,7 +847,7 @@ Syntax: `ut.expect( a_actual ).to_equal( a_expected [, a_nulls_are_equal])[.advanced_options]` Example usage -```sql +```sql linenums="1" declare l_actual varchar2(20); l_expected varchar2(20); @@ -911,10 +914,10 @@ FAILURE ``` -**Note:** ->**Comparing NULLs gives success by default ** -The `a_nulls_are_equal` parameter controls the behavior of a `null = null` comparison. -To change the behavior of `NULL = NULL` comparison pass the `a_nulls_are_equal => false` to the `equal` matcher. +!!! note + **by default, comparing NULL to NULL gives success**
    + The `a_nulls_are_equal` parameter controls the behavior of a `null = null` comparison.
    + To change the behavior of `NULL = NULL` comparison pass the `a_nulls_are_equal => false` to the `equal` matcher. ## contain @@ -931,7 +934,7 @@ The matcher will cause a test to fail if actual data set does not contain some o ![included_set](../images/venn21.gif) **Example 1.** -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -963,7 +966,7 @@ FAILURE When duplicate rows are present in expected data set, actual data set must also include the same amount of duplicates. **Example 2.** -```sql +```sql linenums="1" declare l_actual ut_varchar2_list; l_expected ut_varchar2_list; @@ -991,7 +994,7 @@ The negated version of `contain` ( `not_to_contain` ) is successful only when al ![not_overlapping_set](../images/venn22.gif) **Example 3.** -```sql +```sql linenums="1" declare l_actual ut_varchar2_list; l_expected ut_varchar2_list; @@ -1028,7 +1031,7 @@ FAILURE **Example 4.** -```sql +```sql linenums="1" declare l_actual ut_varchar2_list; l_expected ut_varchar2_list; @@ -1061,7 +1064,7 @@ FAILURE **Example 5.** -```sql +```sql linenums="1" declare l_actual ut_varchar2_list; l_expected ut_varchar2_list; @@ -1134,7 +1137,7 @@ The distance must be expressed as a non-negative number or non-negative interval > The behavior is similar to a call to `months_between()` function with results rounded to full monts ie. round(months_between(date, date)) **Example 1.** -```sql +```sql linenums="1" begin ut.expect(3).to_be_within(1).of_(4); end; @@ -1142,7 +1145,7 @@ end; ``` **Example 2.** -```sql +```sql linenums="1" begin ut.expect(3).to_be_within(1).of_(5); end; @@ -1160,7 +1163,7 @@ Failures: ``` **Example 3.** -```sql +```sql linenums="1" begin ut.expect(sysdate).to_be_within(interval '1' day).of_(sysdate+2); end; @@ -1190,7 +1193,7 @@ The formula used for calcuation of expectation is: ``` **Example 1.** -```sql +```sql linenums="1" begin ut.expect(9).to_be_within_pct(10).of_(10); end; @@ -1206,6 +1209,7 @@ SUCCESS ## Comparing cursors, object types, nested tables and varrays utPLSQL is capable of comparing compound data-types including: + - ref cursors - object types - nested table/varray types @@ -1227,6 +1231,7 @@ utPLSQL is capable of comparing compound data-types including: See [issue #880](https://github.com/utPLSQL/utPLSQL/issues/880) for details. *Note: This behavior might be fixed in future releases, when utPLSQL is no longer depending on XMLType for compound data comparison.* utPLSQL offers advanced data-comparison options, for comparing compound data-types. The options allow you to: + - define columns/attributes to exclude from comparison - define columns/attributes to include in comparison - and more ... @@ -1237,6 +1242,7 @@ For details on available options and how to use them, read the [advanced data co When comparing compound data, utPLSQL will determine the difference between the expected and the actual data. The diff includes: + - differences in column names, column positions and column data-type for cursor data - only data in columns/rows that differ @@ -1246,9 +1252,9 @@ Consider the following expected cursor data | ID (NUMBER)| FIRST_NAME (VARCHAR2) | LAST_NAME (VARCHAR2) | SALARY (NUMBER) | |:----------:|:----------------------:|:----------------------:|:---------------:| -| 1 | JACK | SPARROW | 10000 | -| 2 | LUKE | SKYWALKER | 1000 | -| 3 | TONY | STARK | 1000000 | +| 1 | JACK | SPARROW | 10000 | +| 2 | LUKE | SKYWALKER | 1000 | +| 3 | TONY | STARK | 1000000 | And the actual cursor data: @@ -1261,6 +1267,7 @@ And the actual cursor data: The two data-sets above have the following differences: + - column ID is misplaced (should be first column but is last) - column SALARY has data-type VARCHAR2 but should be NUMBER - column GENDER exists in actual but not in the expected (it is an Extra column) @@ -1272,7 +1279,7 @@ The two data-sets above have the following differences: utPLSQL will report all of the above differences in a readable format to help you identify what is not correct in the compared dataset. Below example illustrates, how utPLSQL will report such differences. -```sql +```sql linenums="1" declare l_actual sys_refcursor; l_expected sys_refcursor; @@ -1320,11 +1327,13 @@ FAILURE ``` utPLSQL identifies and reports on columns: + - column misplacement - column data-type mismatch - extra/missing columns When comparing rows utPLSQL: + - reports only mismatched columns when rows match - reports columns existing in both data-sets when whole row is not matching - reports whole extra (not expected) row from actual when actual has extra rows @@ -1334,6 +1343,7 @@ When comparing rows utPLSQL: ### Object and nested table data-type comparison examples When comparing object type / nested table / varray, utPLSQL will check: + - if data-types match - if data in the compared elements is the same. @@ -1343,7 +1353,7 @@ When diffing, utPLSQL will not check name and data-type of individual attribute Below examples demonstrate how to compare object and nested table data-types. Object type comparison. -```sql +```sql linenums="1" create type department as object(name varchar2(30)) / @@ -1371,7 +1381,7 @@ FAILURE ``` Table type comparison. -```sql +```sql linenums="1" create type department as object(name varchar2(30)) / create type departments as table of department @@ -1409,7 +1419,7 @@ FAILURE ``` Some of the possible combinations of anydata and their results: -```sql +```sql linenums="1" clear screen set serverout on set feedback off @@ -1593,18 +1603,18 @@ FAILURE ### Comparing cursor data containing DATE fields -**Important note** +!!! warning "Important note" -utPLSQL uses XMLType internally to represent rows of the cursor data. This is by far the most flexible method and allows comparison of cursors containing LONG, CLOB, BLOB, user defined types and even nested cursors. -Due to the way Oracle handles DATE data type when converting from cursor data to XML, utPLSQL has no control over the DATE formatting. -The NLS_DATE_FORMAT setting from the moment the cursor was opened determines the formatting of dates used for cursor data comparison. -By default, Oracle NLS_DATE_FORMAT is timeless, so data of DATE datatype, will be compared ignoring the time component. + utPLSQL uses XMLType internally to represent rows of the cursor data. This is by far the most flexible method and allows comparison of cursors containing LONG, CLOB, BLOB, user defined types and even nested cursors.
    + Due to the way Oracle handles DATE data type when converting from cursor data to XML, utPLSQL has no control over the DATE formatting.
    + The NLS_DATE_FORMAT setting from the moment the cursor was opened determines the formatting of dates used for cursor data comparison.
    + By default, Oracle NLS_DATE_FORMAT is timeless, so data of DATE datatype, will be compared ignoring the time component.
    You should surround cursors and expectations with procedures `ut.set_nls`, `ut.reset_nls`. This way, the DATE data in cursors will be properly formatted for comparison using date-time format. The example below makes use of `ut.set_nls`, `ut.reset_nls`, so that the date in `l_expected` and `l_actual` is compared using date-time formatting. -```sql +```sql linenums="1" clear screen alter session set nls_date_format='yyyy-mm-dd'; set serverout on @@ -1649,6 +1659,7 @@ drop table events; ``` In the above example: + - The first expectation is successful, as the `l_expected` cursor contains different date-time then the cursor returned by `get_events` function call - The second expectation fails, as the column `event_date` will get compared as DATE without TIME (using default current session NLS date format) @@ -1687,7 +1698,7 @@ This applies to `timestamp`,`timestamp with timezone`, `timestamp with local tim Example below illustrates usage of `cast` operator to assure appropriate precision is applied on timestamp bind-variables in cursor result-set -```sql +```sql linenums="1" clear screen set serverout on set feedback off @@ -1754,8 +1765,8 @@ FAILURE utPLSQL is capable of comparing json data-types of `json_element_t` **on Oracle 12.2 and above**, and also `json` **on Oracle 21 and above** -**Note:** -> Whenever a database is upgraded to compatible version the utPLSQL needs to be reinstalled to pick up json changes. E.g. upgrade from 18c to 21c to enable `json` type compare. +!!! note + Whenever a database is upgraded to compatible version the utPLSQL needs to be reinstalled to pick up json changes. E.g. upgrade from 18c to 21c to enable `json` type compare. ### Notes on comparison of json data @@ -1769,7 +1780,7 @@ utPLSQL is capable of comparing json data-types of `json_element_t` **on Oracle Compare JSON example using `json_element_t`: -```sql +```sql linenums="1" declare l_expected json_element_t; l_actual json_element_t; @@ -1851,7 +1862,7 @@ FAILURE ``` Comparing parts of JSON example using `json_element_t` subtypes: -```sql +```sql linenums="1" declare l_actual json_object_t; l_actual_extract json_array_t; diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index e9681bb7b..c199d7095 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -24,7 +24,7 @@ This way, we assure we don't jump ahead too much and produce code that is untest ### Create test package -```sql +```sql linenums="1" create or replace package test_betwnstr as --%suite(Between string function) @@ -45,7 +45,7 @@ Finished in .451423 seconds ### Define specification for the test -```sql +```sql linenums="1" create or replace package test_betwnstr as --%suite(Between string function) @@ -78,7 +78,7 @@ Well our test is failing as the package specification requires a body. ### Define body of first test -```sql +```sql linenums="1" create or replace package body test_betwnstr as procedure basic_usage is @@ -114,7 +114,7 @@ Looks like we need to define the function we want to test. ### Define tested function -```sql +```sql linenums="1" create or replace function betwnstr( a_string varchar2, a_start_pos integer, a_end_pos integer ) return varchar2 is begin @@ -147,7 +147,7 @@ Let us fix this and continue from here. The function returned a string one character short, so we need to add 1 to the substr parameter. -```sql +```sql linenums="1" create or replace function betwnstr( a_string varchar2, a_start_pos integer, a_end_pos integer ) return varchar2 is begin @@ -200,7 +200,7 @@ Once defined we can start implementing tests for those behaviors and adjust the A new requirement was added: Start position zero - should be treated as start position one -```sql +```sql linenums="1" create or replace package test_betwnstr as --%suite(Between string function) @@ -254,7 +254,7 @@ Looks like our function does not work as expected for zero start position. Let's fix our function so that the new requirement is met -```sql +```sql linenums="1" create or replace function betwnstr( a_string varchar2, a_start_pos integer, a_end_pos integer ) return varchar2 is begin @@ -288,7 +288,7 @@ When all tests are passing we can proceed with a safe cleanup of our code. The function works well, but we use the `return` twice, which is not the best coding practice. An alternative implementation could be cleaner. -```sql +```sql linenums="1" create or replace function betwnstr( a_string varchar2, a_start_pos integer, a_end_pos integer ) return varchar2 is begin diff --git a/docs/userguide/install.md b/docs/userguide/install.md index fca38c92e..6dfa66140 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -116,26 +116,18 @@ This process can be time-consuming if DB schema is large. The headless scripts accept three optional parameters that define: - username to create as owner of utPLSQL (default `ut3`) - password for owner of utPLSQL (default `XNtxj8eEgA6X6b6f`) -- tablespace to use for storage of profiler data (default `users`) +- tablespace to use for storage of profiler and utPLSQL cache data (default `users`) The scripts need to be executed by `SYSDBA`, in order to grant access to `DBMS_LOCK` and `DBMS_CRYPTO` system packages. -**Note:** -> Grant on `DBMS_LOCK` is required only for installation on Oracle versions below 18c. For versions 18c and above, utPLSQL uses `DBMS_SESSION.SLEEP` so access to `DBMS_LOCK` package is no longer needed. - -**Note:** -> The user performing the installation must have the `ADMINISTER DATABASE TRIGGER` privilege. This is required for installation of trigger that is responsible for parsing annotations at at compile-time of a package. - -**Note:** -> When installing with DDL trigger, utPLSQL will not be registering unit tests for any of oracle-maintained schemas. -For Oracle 11g following users are excluded: -> ANONYMOUS, APPQOSSYS, AUDSYS, DBSFWUSER, DBSNMP, DIP, GGSYS, GSMADMIN_INTERNAL, GSMCATUSER, GSMUSER, ORACLE_OCM, OUTLN, REMOTE_SCHEDULER_AGENT, SYS, SYS$UMF, SYSBACKUP, SYSDG, SYSKM, SYSRAC, SYSTEM, WMSYS, XDB, XS$NULL -> -> For Oracle 12c and above the users returned by below query are excluded by utPLSQL: -> ->```sql -> select username from all_users where oracle_maintained='Y'; ->``` +!!! warning "Important" + - Grant on `DBMS_LOCK` is required only for installation on Oracle versions below 18c. For versions 18c and above, utPLSQL uses `DBMS_SESSION.SLEEP` so access to `DBMS_LOCK` package is no longer needed.
    + - The user performing the installation must have the `ADMINISTER DATABASE TRIGGER` privilege. This is required for installation of trigger that is responsible for parsing annotations at at compile-time of a package.
    + - When installed with DDL trigger, utPLSQL will not be registering unit tests for any of oracle-maintained schemas.
    + - For Oracle 11g following users are excluded:
    + ANONYMOUS, APPQOSSYS, AUDSYS, DBSFWUSER, DBSNMP, DIP, GGSYS, GSMADMIN_INTERNAL, GSMCATUSER, GSMUSER, ORACLE_OCM, OUTLN, REMOTE_SCHEDULER_AGENT, SYS, SYS$UMF, SYSBACKUP, SYSDG, SYSKM, SYSRAC, SYSTEM, WMSYS, XDB, XS$NULL
    + - For Oracle 12c and above the users returned by below query are excluded by utPLSQL:
    + `select username from all_users where oracle_maintained='Y';`
    ### Installation without DDL trigger @@ -232,8 +224,8 @@ cd source sqlplus admin/admins_password@database @install_ddl_trigger.sql ut3 ``` -**Note:** ->Trigger can be installed ant any point in time. +!!! note + Trigger can be installed ant any point in time after the utPLSQL installation. The framework will detect the presence of DDL trigger and act accordingly. ### Allowing other users to access the utPLSQL framework @@ -268,12 +260,12 @@ The following tools that support the SQL*Plus commands can be used to run the in ## Checking environment and utPLSQL version To check the framework version execute the following query: -```sql +```sql linenums="1" select substr(ut.version(),1,60) as ut_version from dual; ``` Additionally you may retrieve more information about your environment by executing the following query: -```sql +```sql linenums="1" select xmlserialize( content xmltype(ut_run_info()) as clob indent size = 2 ) from dual; diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index e7496320c..6ee0b546f 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -22,27 +22,27 @@ Querying the data from function provides the follwing details: - `tags` - tags associated with suites To get list of all test suites in current schema -```sql +```sql linenums="1" select * from table(ut_runner.get_suites_info()) where item_type = 'UT_SUITE'; ``` To get list of all tests for test suite `TEST_STUFF` in current user schema -```sql +```sql linenums="1" select * from table(ut_runner.get_suites_info(USER, 'TEST_STUFF')) where item_type = 'UT_TEST'; ``` To get a full information about suite `TEST_STUFF` including suite description, all contexts and tests in a suite -```sql +```sql linenums="1" select * from table(ut_runner.get_suites_info(USER, 'TEST_STUFF')) where item_type = 'UT_TEST'; ``` To get a full information about suites that have a path like `ut3:tests.test_package_*` including suite description, all contexts and tests in a suite -```sql +```sql linenums="1" select * from table(ut_runner.get_suites_info('ut3:tests.test_package_*') where item_type = 'UT_TEST'; ``` To get a full information about suites that have object name like `test_package_*` including suite description, all contexts and tests in a suite -```sql +```sql linenums="1" select * from table(ut_runner.get_suites_info('test_package_*')); ``` @@ -51,7 +51,7 @@ select * from table(ut_runner.get_suites_info('test_package_*')); Function `ut_runner.has_suites(a_owner)` returns boolean value indicating if given schema contains test suites. Example: -```sql +```sql linenums="1" begin if ut_runner.has_suites(USER) then dbms_output.put_line( 'User '||USER||' owns test suites' ); @@ -66,7 +66,7 @@ end; Function `ut_runner.is_suite(a_owner, a_package_name) ` returns boolean value indicating if given package is a test suites. Example: -```sql +```sql linenums="1" begin if ut_runner.is_suite(USER,'TEST_STUFF') then dbms_output.put_line( 'Package '||USER||'.TEST_STUFF is a test suite' ); @@ -81,7 +81,7 @@ end; Function `ut_runner.is_test(a_owner, a_package_name, a_procedure_name) ` returns boolean value indicating if given package is a test suites. Example: -```sql +```sql linenums="1" begin if ut_runner.is_test(USER,'TEST_STUFF','A_TEST_TO_CHECK_STUFF') then dbms_output.put_line( 'Procedure '||USER||'.TEST_STUFF.A_TEST_TO_CHECK_STUFF is a test' ); diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 1f5ead1c5..467116479 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,6 +1,6 @@ ![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) -utPLSQL provides the following reporting formats. +utPLSQL provides several reporting formats. The sections below describe most of them. ## Documentation reporter @@ -17,7 +17,8 @@ Example outputs from documentation reporter. ![doc_reporter_outputs](../images/documentation_reporter.png) -The documentation report provides the following information. +Documentation reporter provides the following information. + - Test suite name or test package name (nested with suitepath if suitepath is used) - Test description name or test procedure name - Information about test failing `(FAILED - n)` @@ -84,8 +85,11 @@ Example of failure report details ## Sonar test reporter -If you are using [SonarQube](https://www.sonarqube.org/) or [SonarCloud](https://about.sonarcloud.io/) to do static code analysis for you PLSQL projects, your code analysis can benefit from code coverage and test results. + +If you are using [SonarQube](https://www.sonarqube.org/) or [SonarCloud](https://about.sonarcloud.io/) to do static code analysis for you PLSQL projects, +your code analysis can benefit from code coverage and test results. utPLSQL provides two reporters to for SonarQube: + - `ut_sonar_test_reporter` - provides an XML output of each test executed per each project test file (package) - `ut_coverage_sonar_reporter` - provides XML output of code coverage per each project source file @@ -97,15 +101,15 @@ The paths to files can be relative to the project root directory (recommended) o Providing invalid paths or paths to non-existing files will result in failure when publishing test results/coverage results to sonar server. -For details on how to invoke reporter with paths, see the **Coverage reporters** section. +For details on how to invoke reporter with paths, see the [Code coverage](coverage.md) section. ## TFS / VSTS Reporter -If you are using [TFS](https://www.visualstudio.com/tfs/) or [VSTS](https://www.visualstudio.com/team-services/) to do static code analysis for you PLSQL projects and run builds, your code analysis can benefit from code coverage and test results. TFS reporter is designed specifically to [work with Microsoft Team Fundation Server](https://docs.microsoft.com/en-us/vsts/build-release/tasks/test/publish-test-results?view=vsts) report format which is very old version of [JUnit](https://github.com/windyroad/JUnit-Schema/blob/master/JUnit.xsd). -Main diffrence between standard JUnit is that elements cannot be nested and attribute skipped is not present. -utPLSQL provides test reporter to for TFS / VSTS server: -- `ut_tfs_junit_reporter` - provides an XML output of each test executed per each project test file (package) +If you are using [TFS](https://www.visualstudio.com/tfs/) or [VSTS](https://www.visualstudio.com/team-services/) to do static code analysis for you PLSQL projects and run builds, +your code analysis can benefit from code coverage and test results. TFS reporter is designed specifically to [work with Microsoft Team Fundation Server](https://docs.microsoft.com/en-us/vsts/build-release/tasks/test/publish-test-results?view=vsts) report format which is very old version of [JUnit](https://github.com/windyroad/JUnit-Schema/blob/master/JUnit.xsd). +Main difference between standard JUnit is that elements cannot be nested and attribute skipped is not present. +utPLSQL provides a dedicated `ut_tfs_junit_reporter` reporter to for TFS / VSTS servers. The reporter provides an XML output of each test executed per each project test file (package). Example of test report from TFS CI server. Summary: @@ -119,8 +123,8 @@ Details: ## Coverage reporters -utPLSQL comes with a set of build-in coverage reporters. Have a look into the [coverage documentation](coverage.md) to learn more about them. - +utPLSQL comes with a set of build-in coverage reporters. +[Code coverage](coverage.md) section describes in details how to use configure and use code coverage. ## Debug reporter @@ -131,6 +135,7 @@ Use this reporter only when you need to investigate framework issues or raise a Usage of this reporter might have impact on performance of test-suite execution. Amongst others, reporter provides the following information: + - framework version - database version - database OS @@ -152,25 +157,26 @@ Amongst others, reporter provides the following information: - every test - every expectation and it's result -Some of the information in debug log might be redundant. +Some information in debug log might be redundant. -**Note:** ->Some of the information in debug log may be sensitive. In particular: -> - expectation results and messages (logged even for successful runs) -> - test structure -> - db object names -> - etc. +!!! note + Some information in debug log may be sensitive. In particular:
    + - expectation results and messages (logged even for successful runs)
    + - test structure
    + - db object names
    + - etc. ## Custom reporters -It is possible to add your own reporters by creating an appropriate object type. In principle, it has to be a subtype of `ut_reporter_base`. However, if the reporter is expected to produce output consumable by a client oustside of the database (e.g. the data has to be reported to the screen or to a file), then you should base it on `ut_output_reporter_base` (which is a subtype of `ut_reporter_base`). In contrast, if you would like to create a reporter that, for example, saves the data to a database table, then it should be based directly on `ut_reporter_base`. (Currently, all reporters in the utPLSQL framework are based on `ut_output_reporter_base`.) Coverage reporters are based on `ut_coverage_reporter_base` (a subtype of `ut_output_reporter_base`). +It is possible to add your own reporters by creating an appropriate object type. +In principle, it has to be a subtype of `ut_reporter_base`. However, if the reporter is expected to produce output consumable by a client oustside of the database (e.g. the data has to be reported to the screen or to a file), then you should base it on `ut_output_reporter_base` (which is a subtype of `ut_reporter_base`). In contrast, if you would like to create a reporter that, for example, saves the data to a database table, then it should be based directly on `ut_reporter_base`. (Currently, all reporters in the utPLSQL framework are based on `ut_output_reporter_base`.) Coverage reporters are based on `ut_coverage_reporter_base` (a subtype of `ut_output_reporter_base`). If you need to produce a colored text output from the custom reporter, then you can build it basing on `ut_console_reporter_base` (a subtype of `ut_output_reporter_base`). In many cases it may also be more convenient to create the custom reporter type under a more specialized type, like `ut_documentation_reporter` or `ut_junit_reporter`, and override just some of the functionality. It is recommended to create the reporter type in the schema where utPLSQL is installed (by default it is the `UT3` schema). Note that before running the utPLSQL uninstall scripts, all custom reporters should be dropped (cf. [the installation documentation](install.md)). In particular, when upgrading to a newer version of utPLSQL, one has to drop the custom reporters and recreate them after the upgrade. -**Note:** -> It is possible, but cumbersome, to use another schema for storing the custom reporters. This requires to create a synonym for the base reporter type in the schema that is going to own the custom reporter, and to provide appropriate grants both to the owner of the custom reporter and to the user running the reporter. After upgrading or reinstalling utPLSQL, the extra privileges need to be recreated. This approach is not recommended. +!!! note + It is possible, but cumbersome, to use another schema for storing the custom reporters. This requires to create a synonym for the base reporter type in the schema that is going to own the custom reporter, and to provide appropriate grants both to the owner of the custom reporter and to the user running the reporter. After upgrading or reinstalling utPLSQL, the extra privileges need to be recreated. This approach is not recommended. Assuming that the custom reporter type is created in the `UT3` schema, to run the tests using a custom reporter just call: `exec ut.run(ut3.custom_reporter_name());`, optionally providing parameter values to the `custom_reporter_name` constructor. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index a87fe9836..18270e707 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -47,7 +47,7 @@ You can use a wildcard character `*` to call tests by part of their name or to c Wildcard character can be placed anywhere on the path and can occur mutliple times. Schema name cannot contain a wildcard character whether is in a suitepath call or call by object name. -```sql +```sql linenums="1" alter session set current_schema=hr; set serveroutput on begin @@ -57,7 +57,7 @@ end; Executes all tests in current schema (_HR_). -```sql +```sql linenums="1" set serveroutput on begin ut.run('HR'); @@ -66,7 +66,7 @@ end; Executes all tests in specified schema (_HR_). -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr:com.my_org.my_project'); @@ -76,7 +76,7 @@ end; Executes all tests from all packages that are on the _com.my_org.my_project_ suitepath. Check the [annotations documentation](annotations.md) to find out about suitepaths and how they can be used to organize test packages for your project. -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr:com*'); @@ -85,7 +85,7 @@ end; Executes all tests in schema `hr` from all packages that are on suitepath starting with `com`. -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr:co*.my_*.my_*'); @@ -94,7 +94,7 @@ end; Executes all tests in schema `hr` from all packages that starting with `my_` and all tests starting with `my_*` that are on suitepath starting with `co` . -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test_apply_bonus'); @@ -103,7 +103,7 @@ end; Executes all tests from package _hr.test_apply_bonus_. -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test_apply_bonus.bonus_cannot_be_negative'); @@ -112,7 +112,7 @@ end; Executes single test procedure _hr.test_apply_bonus.bonus_cannot_be_negative_. -```sql +```sql linenums="1" set serveroutput on begin ut.run(ut_varchar2_list('hr.test_apply_bonus','cust')); @@ -120,7 +120,7 @@ end; ``` Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_. -```sql +```sql linenums="1" set serveroutput on begin ut.run(ut_varchar2_list('hr.test_apply_bonus,cust)'); @@ -129,7 +129,7 @@ end; Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_. -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test_apply_bonus,cust'); @@ -142,7 +142,7 @@ Using a list of items to execute allows you to execute a fine-grained set of tes List can be passed as a comma separated list or a list of *ut_varchar2_list objects* or as a list within ut_varchar2_list. -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test*'); @@ -150,7 +150,7 @@ end; ``` Executes all tests in schema `hr` located in packages starting with name `test`. -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test_apply_bonus.bonus_*'); @@ -166,7 +166,7 @@ Executes test procedures with names starting with `bonus` in package `hr.test_ap The `ut.run` procedures and functions accept `a_reporter` attribute that defines the reporter to be used in the run. You can execute any set of tests with any of the predefined reporters. -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test_apply_bonus', ut_junit_reporter()); @@ -189,7 +189,7 @@ Functions provide output as a pipelined stream and therefore need to be executed At the end of the run, the transaction is automatically rolled-back and all uncommitted changes are reverted. Example. -```sql +```sql linenums="1" select * from table(ut.run('hr.test_apply_bonus', ut_junit_reporter())); ``` @@ -222,7 +222,7 @@ Running with multiple reporters. - each reporter for each test-run must have a unique `reporter_id`. The `reporter_id` is used between two sessions to identify the data stream Example: -```sql +```sql linenums="1" --main test run ( session 1 ) declare l_reporter ut_realtime_reporter := ut_realtime_reporter(); @@ -234,7 +234,7 @@ end; / ``` -```sql +```sql linenums="1" --report consumer ( session 2 ) set arraysize 1 set pagesize 0 @@ -247,7 +247,7 @@ select * ); ``` -```sql +```sql linenums="1" --alternative version of report consumer ( session 2 ) set arraysize 1 set pagesize 0 @@ -279,14 +279,14 @@ When tests are executed with random order, randomization is applied to single le This is needed to maintain visibility and accessibility of common setup/cleanup `beforeall`/`afterall` in tests. Example: -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test_apply_bonus', a_random_test_order => true); end; ``` -```sql +```sql linenums="1" select * from table(ut.run('hr.test_apply_bonus', a_random_test_order => 1)); ``` @@ -301,14 +301,14 @@ Tests were executed with random order seed '302980531'. If you want to re-run tests using previously generated seed, you may do so by running them with parameter `a_random_test_order_seed` Example: -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test_apply_bonus', a_random_test_order_seed => 302980531); end; ``` -```sql +```sql linenums="1" select * from table(ut.run('hr.test_apply_bonus', a_random_test_order_seed => 302980531)); ``` @@ -321,18 +321,18 @@ In addition to the path, you can filter the tests to be run by specifying tags. Multiple tags are separated by comma. The framework applies `OR` logic to all specified tags so any test / suite that matches at least one tag will be included in the test run. -```sql +```sql linenums="1" begin ut.run('hr.test_apply_bonus', a_tags => 'test1,test2'); end; ``` -```sql +```sql linenums="1" select * from table(ut.run('hr.test_apply_bonus', a_tags => 'suite1')) ``` You can also exclude specific tags by adding a `-` (dash) in front of the tag -```sql +```sql linenums="1" select * from table(ut.run('hr.test_apply_bonus', a_tags => '-suite1')) ``` @@ -347,7 +347,7 @@ Setting this flag to true has following side-effects: - automatic rollback is forced to be disabled in test-run even if it was explicitly enabled by using annotation `--%rollback(manual) Example invocation: -```sql +```sql linenums="1" set serveroutput on begin ut.run('hr.test_apply_bonus', a_force_manual_rollback => true); @@ -366,7 +366,7 @@ If you run your tests using `utPLSQL-cli`, this is done automatically and no act To make sure that the reports will display your national characters properly when running from IDE like SQLDeveloper/TOAD/SQLPlus or sqlcl you need to provide the charaterset manualy to `ut.run`. Example call with characterset provided: -```sql +```sql linenums="1" begin ut.run('hr.test_apply_bonus', ut_junit_reporter(), a_client_character_set => 'Windows-1251'); end; diff --git a/mkdocs.yml b/mkdocs.yml index 487505097..713722620 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -60,11 +60,13 @@ extra: version: # disable for offline docs provider: mike # disable for offline docs markdown_extensions: + - admonition + - pymdownx.details + - pymdownx.superfences - pymdownx.highlight: anchor_linenums: true - pymdownx.inlinehilite - pymdownx.snippets - - pymdownx.superfences - pymdownx.caret - pymdownx.mark - pymdownx.tilde diff --git a/mkdocs_offline.yml b/mkdocs_offline.yml index fe2255e59..31c90615e 100644 --- a/mkdocs_offline.yml +++ b/mkdocs_offline.yml @@ -60,11 +60,13 @@ extra: # version: # disable for offline docs # provider: mike # disable for offline docs markdown_extensions: + - admonition + - pymdownx.details + - pymdownx.superfences - pymdownx.highlight: anchor_linenums: true - pymdownx.inlinehilite - pymdownx.snippets - - pymdownx.superfences - pymdownx.caret - pymdownx.mark - pymdownx.tilde From 535f682336801e450c22ae7bc8c7281e15164197 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 26 Oct 2022 22:28:55 +0100 Subject: [PATCH 105/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 961ba3060..0a3d8196f 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 2b625c7d0..928066c17 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index a915f2a52..bae8cc5f9 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 5d4ed97cf..a0752effd 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index bc7e1e63b..6829b6ff6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 2e2d4af9f..da3ee4b59 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 2c13fb649..112e66dd5 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index b39ab803b..dedd8fe14 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 20707e917..d3c0f1881 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index c795c5421..932c34f94 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index a972fa2e3..e3378f69b 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index c199d7095..ac684258c 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 6dfa66140..4bf1a7ef6 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 6ee0b546f..4376106c8 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 467116479..a7a8a3540 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 18270e707..482aec796 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index a219012fd..32f8b53f6 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4063--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 06b17ccbf..3c80498cb 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4063-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4064-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 05753e533c90b4f82af449728f27b5e5541e4aad Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 21 Nov 2022 23:37:15 +0200 Subject: [PATCH 106/187] Improving expectations documentation --- docs/userguide/expectations.md | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index e3378f69b..242922d69 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -388,7 +388,7 @@ Finished in .009229 seconds 1 tests, 0 failed, 0 errored, 0 disabled, 0 warning(s) ``` -For more details see documentation of the [`--%throws` annotation.](annotations.md#throws-annotation) +For more details see documentation of the [`--%throws` annotation.](annotations.md#throws) ## Matchers @@ -396,7 +396,7 @@ For more details see documentation of the [`--%throws` annotation.](annotations. You can choose different matchers to validate that your PL/SQL code is working as expected. -## be_between +### be_between Validates that the actual value is between the lower and upper bound. Example: @@ -452,7 +452,7 @@ SUCCESS Actual: 'Abb' (varchar2) was expected to be between: 'Aba' and 'Abc' ``` -## be_empty +### be_empty Unary matcher that validates if the provided dataset is empty. Can be used with `BLOB`,`CLOB`, `refcursor` or `nested table`/`varray` passed as `ANYDATA` @@ -501,7 +501,7 @@ FAILURE at "anonymous block", line 9 ``` -## be_false +### be_false Unary matcher that validates if the provided value is false. Usage: @@ -529,7 +529,7 @@ SUCCESS Actual: TRUE (boolean) was expected not to be false ``` -## be_greater_or_equal +### be_greater_or_equal Checks if the actual value is greater or equal than the expected. Usage: @@ -557,7 +557,7 @@ SUCCESS Actual: 2019-07-07T22:43:29 (date) was expected not to be greater or equal: 2019-07-08T22:43:29 (date) ``` -## be_greater_than +### be_greater_than Checks if the actual value is greater than the expected. Usage: @@ -585,7 +585,7 @@ SUCCESS Actual: 0 (number) was expected not to be greater than: 1 (number) ``` -## be_less_or_equal +### be_less_or_equal Checks if the actual value is less or equal than the expected. Usage: @@ -613,7 +613,7 @@ SUCCESS Actual: 4 (number) was expected not to be less or equal: 3 (number) ``` -## be_less_than +### be_less_than Checks if the actual value is less than the expected. Usage: @@ -641,7 +641,7 @@ FAILURE at "anonymous block", line 5 ``` -## be_like +### be_like Validates that the actual value is like the expected expression. Syntax: @@ -679,7 +679,7 @@ SUCCESS Actual: 'Lorem_impsum' (varchar2) was expected not to be like: '%reM%' ``` -## be_not_null +### be_not_null Unary matcher that validates if the actual value is not null. Usage: @@ -707,7 +707,7 @@ SUCCESS Actual: NULL (varchar2) was expected not to be not null ``` -## be_null +### be_null Unary matcher that validates if the actual value is null. Usage: @@ -735,7 +735,7 @@ SUCCESS Actual: 0 (number) was expected not to be null ``` -## be_true +### be_true Unary matcher that validates if the provided value is true. Usage: @@ -763,7 +763,7 @@ FAILURE at "anonymous block", line 5 ``` -## have_count +### have_count Unary matcher that validates if the provided dataset count is equal to expected value. Can be used with `refcursor`, `json` or `table type` @@ -799,7 +799,7 @@ FAILURE at "anonymous block", line 11 ``` -## match +### match Validates that the actual value is matching the expected regular expression. Syntax: @@ -833,7 +833,7 @@ FAILURE at "anonymous block", line 5 ``` -## equal +### equal The `equal` matcher is very restrictive. Test using this matcher succeeds only when the compared data-types are exactly the same. If you are comparing a `varchar2` to a `number`, it will fail even if the text contains the same numeric value as the number. The matcher will also fail when comparing a `timestamp` to a `timestamp with timezone` data-type etc. @@ -919,7 +919,7 @@ FAILURE The `a_nulls_are_equal` parameter controls the behavior of a `null = null` comparison.
    To change the behavior of `NULL = NULL` comparison pass the `a_nulls_are_equal => false` to the `equal` matcher. -## contain +### contain This matcher supports only compound data-types comparison. It check if the actual set contains all values of expected subset. @@ -1100,7 +1100,7 @@ SUCCESS DEF ``` -## to_be_within of +### to_be_within of Determines whether expected value is within range (tolerance) from another value. @@ -1181,7 +1181,7 @@ Failures: ``` -## to_be_within_pct of +### to_be_within_pct of Determines whether actual value is within percentage range of expected value. The matcher only works with `number` data-type. @@ -1603,7 +1603,7 @@ FAILURE ### Comparing cursor data containing DATE fields -!!! warning "Important note" +!!! warning "Important" utPLSQL uses XMLType internally to represent rows of the cursor data. This is by far the most flexible method and allows comparison of cursors containing LONG, CLOB, BLOB, user defined types and even nested cursors.
    Due to the way Oracle handles DATE data type when converting from cursor data to XML, utPLSQL has no control over the DATE formatting.
    From ce1a289959ddf284cbf0c03a3ed7ae13fcc07f99 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 21 Nov 2022 23:52:52 +0200 Subject: [PATCH 107/187] Changed to develop version of `mike` for mkdocs - see https://github.com/jimporter/mike/issues/123 --- .github/workflows/build.yml | 4 +++- .github/workflows/release.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 92bf0752e..904c9772a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -255,7 +255,9 @@ jobs: pip install mkdocs pip install mkdocs-git-revision-date-localized-plugin pip install mkdocs-material - pip install mike +# pip install mike +# using develop version of mike - see https://github.com/jimporter/mike/issues/123 + pip install git+https://github.com/jimporter/mike.git mike deploy -p develop dispatch: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index acac5f1aa..8a4423758 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,7 +40,9 @@ jobs: pip install mkdocs pip install mkdocs-git-revision-date-localized-plugin pip install mkdocs-material - pip install mike +# pip install mike +# using develop version of mike - see https://github.com/jimporter/mike/issues/123 + pip install git+https://github.com/jimporter/mike.git mike deploy -p -u ${UTPLSQL_VERSION} latest mkdocs build --clean -f mkdocs_offline.yml rm -rf docs/* From a216a3cb0e409db7a4bec13e2ec9616c8dd1c431 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 21 Nov 2022 23:52:52 +0200 Subject: [PATCH 108/187] Changed to develop version of `mike` for mkdocs - see https://github.com/jimporter/mike/issues/123 --- .github/workflows/build.yml | 2 -- .github/workflows/release.yml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 904c9772a..441a29d0d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -255,8 +255,6 @@ jobs: pip install mkdocs pip install mkdocs-git-revision-date-localized-plugin pip install mkdocs-material -# pip install mike -# using develop version of mike - see https://github.com/jimporter/mike/issues/123 pip install git+https://github.com/jimporter/mike.git mike deploy -p develop diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a4423758..6ec82435f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,8 +40,6 @@ jobs: pip install mkdocs pip install mkdocs-git-revision-date-localized-plugin pip install mkdocs-material -# pip install mike -# using develop version of mike - see https://github.com/jimporter/mike/issues/123 pip install git+https://github.com/jimporter/mike.git mike deploy -p -u ${UTPLSQL_VERSION} latest mkdocs build --clean -f mkdocs_offline.yml From 7eaffbde89af288e04cb5ab6384341cd72d8f3f6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 21 Nov 2022 22:06:17 +0000 Subject: [PATCH 109/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 0a3d8196f..83ccdcdf8 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 928066c17..c7336985b 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index bae8cc5f9..2a32da1e1 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index a0752effd..49c005679 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 6829b6ff6..3ce91e6b3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index da3ee4b59..e90367224 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 112e66dd5..441b2cae4 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index dedd8fe14..bda84931c 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index d3c0f1881..028044c29 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 932c34f94..d39e11abc 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 242922d69..dc38a1dbf 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index ac684258c..8608d1375 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 4bf1a7ef6..6883a123e 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 4376106c8..056459fc7 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index a7a8a3540..ebecc840c 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 482aec796..87e8fdc5a 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 32f8b53f6..07861ae3e 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4064--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 3c80498cb..825683207 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4064-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4067-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 5508dff49c92a8691cc5cffa2ff0afc909cb6fb8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 11 Dec 2022 18:30:51 +0000 Subject: [PATCH 110/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 83ccdcdf8..9428fddd5 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index c7336985b..d4dbf52cb 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 2a32da1e1..181f9ebe0 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 49c005679..beff5f9cd 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 3ce91e6b3..4b1219689 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index e90367224..7f99edbdb 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 441b2cae4..2272eb321 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index bda84931c..2eac7a733 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 028044c29..2e54cfba5 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index d39e11abc..43b362e35 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index dc38a1dbf..bf5d53809 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 8608d1375..83f80b145 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 6883a123e..9fd89ea83 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 056459fc7..faef86500 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index ebecc840c..3df400c98 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 87e8fdc5a..363ef20b3 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 07861ae3e..633346370 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4067--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 825683207..9dba896a9 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4067-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4068-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 45d20eb5fd6885456b35e9ff2856213671bf9757 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 11 Dec 2022 19:13:58 +0000 Subject: [PATCH 111/187] Updated project version after build [skip ci] --- VERSION | 2 +- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- sonar-project.properties | 2 +- source/core/ut_utils.pks | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/VERSION b/VERSION index d0237db61..ecbc73caf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.1.13-develop +v3.1.13 diff --git a/docs/about/authors.md b/docs/about/authors.md index 9428fddd5..bb8b46bb2 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index d4dbf52cb..1381a7d43 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 181f9ebe0..b241fedd7 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index beff5f9cd..06d113450 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 4b1219689..26e95ff2f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 7f99edbdb..629ef4237 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 2272eb321..a21fa7292 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 2eac7a733..a5a9c40b6 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 2e54cfba5..2220807ae 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 43b362e35..f585ad14d 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index bf5d53809..128b05b7b 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 83f80b145..60b3f54b7 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 9fd89ea83..3ac993327 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index faef86500..913abf783 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 3df400c98..b7a516a87 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 363ef20b3..84a71c0f1 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 633346370..a081a0a1b 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4069-blue.svg) # Upgrading from version 2 diff --git a/sonar-project.properties b/sonar-project.properties index 5d6cefe12..77cc387a8 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.organization=utplsql sonar.projectKey=utPLSQL # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=utPLSQL -sonar.projectVersion=v3.1.13-develop +sonar.projectVersion=v3.1.13 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # Since SonarQube 4.2, this property is optional if sonar.modules is set. diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 9dba896a9..86f25f8fa 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4068-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4069'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From b84535d4532f928f6312777a7b402b36be3fb625 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 11 Dec 2022 21:17:50 +0200 Subject: [PATCH 112/187] Fixed documentation build process for release branch, --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 441a29d0d..0ec37efe2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -213,8 +213,7 @@ jobs: API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} if: | github.repository == 'utPLSQL/utPLSQL' && - github.base_ref == null && - ( startsWith( github.ref, 'refs/heads/release/v' ) || github.ref == 'refs/heads/develop' ) + github.base_ref == null && github.ref == 'refs/heads/develop' steps: - name: 🔍 API_TOKEN_GITHUB if: env.API_TOKEN_GITHUB == '' From ebb59383d90e64a1b265fe85a7a0034f18ac9d29 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 11 Dec 2022 19:27:38 +0000 Subject: [PATCH 113/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 9428fddd5..e8d37d574 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index d4dbf52cb..5b94283db 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 181f9ebe0..26c838e8a 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index beff5f9cd..d2580f63b 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 4b1219689..0f87193a4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 7f99edbdb..6bb8163e6 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 2272eb321..9913f9a90 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 2eac7a733..94db22808 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 2e54cfba5..689732e0b 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 43b362e35..81024551e 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index bf5d53809..b6854a8cd 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 83f80b145..aca1963a7 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 9fd89ea83..64d59877d 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index faef86500..7957d106e 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 3df400c98..ab3a5b56c 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 363ef20b3..dbcfc2b59 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 633346370..f76e86f23 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4068--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 9dba896a9..f965536cb 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4068-develop'; + gc_version constant varchar2(50) := 'v3.1.13.4070-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 1846c4fc638508f5cf7a86546e8d6dd572624a73 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 11 Dec 2022 22:18:30 +0200 Subject: [PATCH 114/187] Updated releasing.md --- development/releasing.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/development/releasing.md b/development/releasing.md index bcc89067a..4b9e2f7f9 100644 --- a/development/releasing.md +++ b/development/releasing.md @@ -3,7 +3,7 @@ To create a release follow the below steps ## Release preparation - - Create a **draft** of Release from the `main` branch using [github releases page](https://github.com/utPLSQL/utPLSQL/releases) and populate release description using information found on the issues and pull requests **since previous release**. + - Create a **draft** of a Release with version number `vX.Y.X` sourced from the `main` branch using [github releases page](https://github.com/utPLSQL/utPLSQL/releases) and populate release description using information found on the issues and pull requests **since previous release**. To find issues closed after certain date use [advanced filters](https://help.github.com/articles/searching-issues-and-pull-requests/#search-by-open-or-closed-state). Example: [`is:issue closed:>2018-07-22`](https://github.com/utPLSQL/utPLSQL/issues?utf8=%E2%9C%93&q=is%3Aissue+closed%3A%3E2018-07-22+) @@ -11,11 +11,9 @@ To create a release follow the below steps - create the release branch from `develop` branch and make sure to name the release branch: `release/vX.Y.Z` - update, commit and push at least one file change in the release branch, to kick off a build on [GithubActions](https://github.com/utPLSQL/utPLSQL/actions) or kick-off a build manually for that branch after it was created on github. - wait for the build to complete successfully as it will update the version to be release number (without develop) - - merge the release branch to `main` branch and wait for build on `main` branch to complete successfully (do not use Squash/rebase for merge operation) - - Publish the release on the `main` branch and tag it with version number `vX.Y.Z` - - Wait for the release build to finish successfully on Github Actions as this will upload release artifacts (`zip` and `tar.gz` files along with `md5`) - - After A Release build was completed successfully, merge main branch back into develop branch. - - At this point, main branch and release tag should be at the same commit version and artifacts should be uploaded into Github release. + - merge the release branch to `main` branch and publish [the previously prepared](#release-preparation) release draft. + - Wait for the [Github Actions `Release`](https://github.com/utPLSQL/utPLSQL/actions/workflows/release.yml) process to complete successfully. The process will upload release artifacts (`zip` and `tar.gz` files along with `md5`) + - After Release build was completed successfully, merge the `main` branch back into `develop` branch. At this point, main branch and release tag should be at the same commit version and artifacts should be uploaded into Github release. - After develop branch was built, increase the version number in `VERSION` file to represent next planned release version. - Clone `utplsql.githug.io` project and add a new announcement about next version being released in `_posts`. Use previous announcements as a template. Make sure to set date, time and post title properly. From 90d0e5d53e9673e270053be995885868535d81cd Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 11 Dec 2022 22:22:10 +0200 Subject: [PATCH 115/187] Fixed release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6ec82435f..a748d1cbd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -67,7 +67,7 @@ jobs: slack-workflow-status: if: always() name: Post Workflow Status To Slack - needs: [ publish, upload_artifacts ] + needs: [ upload_artifacts ] runs-on: ubuntu-latest steps: - name: Slack Workflow Notification From 86cd04dcf436eb1545105f70c4c207d5a78b7bbb Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 11 Dec 2022 22:58:00 +0200 Subject: [PATCH 116/187] Updated releasing.md --- development/releasing.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/development/releasing.md b/development/releasing.md index 4b9e2f7f9..2b9be317a 100644 --- a/development/releasing.md +++ b/development/releasing.md @@ -15,7 +15,10 @@ To create a release follow the below steps - Wait for the [Github Actions `Release`](https://github.com/utPLSQL/utPLSQL/actions/workflows/release.yml) process to complete successfully. The process will upload release artifacts (`zip` and `tar.gz` files along with `md5`) - After Release build was completed successfully, merge the `main` branch back into `develop` branch. At this point, main branch and release tag should be at the same commit version and artifacts should be uploaded into Github release. - After develop branch was built, increase the version number in `VERSION` file to represent next planned release version. - - Clone `utplsql.githug.io` project and add a new announcement about next version being released in `_posts`. Use previous announcements as a template. Make sure to set date, time and post title properly. + - Clone `utplsql.githug.io` project and: + - Add a new announcement about next version being released in `docs/_posts`. Use previous announcements as a template. Make sure to set date, time and post title properly. + - Add the post to list in `mkdocs.yml` file in root directory of that repository. + - Add the link to the post at the beginning of the `docs/index.md` file. The following will happen: - build executed on branch `release/vX.Y.Z-[something]` updates files `sonar-project.properties`, `VERSION` with project version derived from the release branch name From 315e5c6f07e1b3d299bebea722a022ffb60bbab6 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 21 Jan 2023 00:29:49 +0200 Subject: [PATCH 117/187] Updated version to 3.1.14 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ecbc73caf..3b63c19c9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.1.13 +v3.1.14 From f72db1e7dacd09ee273e9df3c65d908db7b3e197 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Jan 2023 22:38:37 +0000 Subject: [PATCH 118/187] Updated project version after build [skip ci] --- VERSION | 2 +- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- sonar-project.properties | 2 +- source/core/ut_utils.pks | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/VERSION b/VERSION index 3b63c19c9..5fcdcb942 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v3.1.14 +v3.1.14-develop diff --git a/docs/about/authors.md b/docs/about/authors.md index e8d37d574..cd50c02bf 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 5b94283db..52b771abc 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 26c838e8a..c869cfa4f 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index d2580f63b..ec7316027 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 0f87193a4..4a9108f8a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 6bb8163e6..dc7d2f0ad 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 9913f9a90..87ede5b5f 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 94db22808..905a27acb 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 689732e0b..5e9331e6b 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 81024551e..0da0f5178 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index b6854a8cd..0655700af 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index aca1963a7..a6948f9d7 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 64d59877d..ad3bfe97e 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 7957d106e..8cb47b973 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index ab3a5b56c..3d0bf7d84 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index dbcfc2b59..0ab199c08 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index f76e86f23..1a554dfc9 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.13.4070--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) # Upgrading from version 2 diff --git a/sonar-project.properties b/sonar-project.properties index 77cc387a8..d088e9ccb 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.organization=utplsql sonar.projectKey=utPLSQL # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=utPLSQL -sonar.projectVersion=v3.1.13 +sonar.projectVersion=v3.1.14-develop # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. # Since SonarQube 4.2, this property is optional if sonar.modules is set. diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index f965536cb..438abddd2 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.13.4070-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4072-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From da6ee7089b4dcdab01b7782562f113b3f34ddab0 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 8 Feb 2023 21:50:46 +0200 Subject: [PATCH 119/187] Refactored output buffers to have better segregation of responsibilities. Changed behavior of output buffer `get_lines` procedure to stop immediately after consuming all produced data if producer has stopped. Changed behavior of output buffer `get_lines` procedure not to timeout after 4 hours, if producer is still running. --- docs/userguide/install.md | 2 +- .../coverage/ut_coverage_reporter_base.tpb | 2 - .../output_buffers/ut_output_buffer_base.tpb | 133 ++++++++++++++++- .../output_buffers/ut_output_buffer_base.tps | 21 ++- .../ut_output_clob_table_buffer.tpb | 134 +++++------------- .../ut_output_clob_table_buffer.tps | 10 +- .../output_buffers/ut_output_table_buffer.tpb | 133 +++++------------ .../output_buffers/ut_output_table_buffer.tps | 10 +- source/core/types/ut_output_reporter_base.tpb | 8 +- source/core/types/ut_output_reporter_base.tps | 3 +- source/create_utplsql_owner.sql | 10 +- test/ut3_tester/core/test_output_buffer.pkb | 25 +++- test/ut3_tester/core/test_output_buffer.pks | 25 +++- test/ut3_tester_helper/coverage_helper.pkb | 19 +-- 14 files changed, 277 insertions(+), 258 deletions(-) diff --git a/docs/userguide/install.md b/docs/userguide/install.md index ad3bfe97e..278bad788 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -121,7 +121,7 @@ The headless scripts accept three optional parameters that define: The scripts need to be executed by `SYSDBA`, in order to grant access to `DBMS_LOCK` and `DBMS_CRYPTO` system packages. !!! warning "Important" - - Grant on `DBMS_LOCK` is required only for installation on Oracle versions below 18c. For versions 18c and above, utPLSQL uses `DBMS_SESSION.SLEEP` so access to `DBMS_LOCK` package is no longer needed.
    + - `DBMS_LOCK` is required for session synchronization between main session and session consuming realtime reports.
    - The user performing the installation must have the `ADMINISTER DATABASE TRIGGER` privilege. This is required for installation of trigger that is responsible for parsing annotations at at compile-time of a package.
    - When installed with DDL trigger, utPLSQL will not be registering unit tests for any of oracle-maintained schemas.
    - For Oracle 11g following users are excluded:
    diff --git a/source/core/coverage/ut_coverage_reporter_base.tpb b/source/core/coverage/ut_coverage_reporter_base.tpb index aff4e6560..da2bd27ad 100644 --- a/source/core/coverage/ut_coverage_reporter_base.tpb +++ b/source/core/coverage/ut_coverage_reporter_base.tpb @@ -92,7 +92,6 @@ create or replace type body ut_coverage_reporter_base is ut_coverage_helper.cleanup_tmp_table(); (l_reporter as ut_output_reporter_base).before_calling_run(null); l_reporter.after_calling_run( ut_run( a_coverage_options => a_coverage_options, a_client_character_set => a_client_character_set ) ); - l_reporter.on_finalize(null); for i in (select /*+ no_parallel */ x.text from table(l_reporter.get_lines(1, 1)) x ) loop pipe row (i.text); end loop; @@ -106,7 +105,6 @@ create or replace type body ut_coverage_reporter_base is ut_coverage_helper.cleanup_tmp_table(); (l_reporter as ut_output_reporter_base).before_calling_run(null); l_reporter.after_calling_run( ut_run( a_coverage_options => a_coverage_options, a_client_character_set => a_client_character_set ) ); - l_reporter.on_finalize(null); open l_result for select /*+ no_parallel */ x.text from table(l_reporter.get_lines(1, 1)) x; return l_result; end; diff --git a/source/core/output_buffers/ut_output_buffer_base.tpb b/source/core/output_buffers/ut_output_buffer_base.tpb index 6d7964150..c3a137b42 100644 --- a/source/core/output_buffers/ut_output_buffer_base.tpb +++ b/source/core/output_buffers/ut_output_buffer_base.tpb @@ -24,7 +24,7 @@ create or replace type body ut_output_buffer_base is self.self_type := coalesce(a_self_type,self.self_type); self.output_id := coalesce(a_output_id, self.output_id, sys_guid()); self.start_date := coalesce(self.start_date, sysdate); - self.last_message_id := 0; + self.last_write_message_id := 0; select /*+ no_parallel */ count(*) into l_exists from ut_output_buffer_info_tmp where output_id = self.output_id; if ( l_exists > 0 ) then update /*+ no_parallel */ ut_output_buffer_info_tmp set start_date = self.start_date where output_id = self.output_id; @@ -32,10 +32,135 @@ create or replace type body ut_output_buffer_base is insert /*+ no_parallel */ into ut_output_buffer_info_tmp(output_id, start_date) values (self.output_id, self.start_date); end if; commit; + dbms_lock.allocate_unique( self.output_id, self.lock_handle); self.is_closed := 0; end; - member function get_lines_cursor(a_initial_timeout natural := null, a_timeout_sec natural := null) return sys_refcursor is + member procedure lock_buffer(a_timeout_sec number := null) is + l_status integer; + begin + l_status := dbms_lock.request( self.lock_handle, dbms_lock.x_mode, 5, false ); + if l_status != 0 then + raise_application_error(-20000, 'Cannot allocate lock for output buffer of reporter. lock request status = '||l_status||', lock handle = '||self.lock_handle||', self.output_id ='||self.output_id); + end if; + end; + + member procedure close(self in out nocopy ut_output_buffer_base) is + l_status integer; + begin + l_status := dbms_lock.release( self.lock_handle ); + if l_status != 0 then + raise_application_error(-20000, 'Cannot release lock for output buffer of reporter. Lock_handle = '||self.lock_handle||' status = '||l_status); + end if; + self.is_closed := 1; + end; + + + member procedure remove_buffer_info(self in ut_output_buffer_base) is + pragma autonomous_transaction; + begin + delete from ut_output_buffer_info_tmp a + where a.output_id = self.output_id; + commit; + end; + + member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined is + lc_init_wait_sec constant number := coalesce(a_initial_timeout, 10 ); + lc_100_milisec constant number(1,1) := 0.1; --sleep for 100 ms between checks + lc_500_milisec constant number(3,1) := 0.5; --sleep for 1 s when waiting long + lc_1_second constant number(3,1) := 1; + l_buffer_rowids ut_varchar2_rows; + l_buffer_data ut_output_data_rows; + l_finished_flags ut_integer_list; + l_last_read_message_id integer; + l_already_waited_sec number(10,2) := 0; + l_data_finished boolean := false; + l_finished boolean := false; + l_sleep_time number(2,1) := lc_100_milisec; + l_lock_status integer; + l_producer_started boolean := false; + l_producer_finished boolean := false; + function get_lock_status return integer is + l_result integer; + l_release_status integer; + begin + l_result := dbms_lock.request( self.lock_handle, dbms_lock.s_mode, 0, false ); + if l_result = 0 then + l_release_status := dbms_lock.release( self.lock_handle ); + end if; + return l_result; + end; + begin + while not l_finished loop + + --check if the lock is still there on output - if yes, the main session is still running and so don't stop + l_lock_status := get_lock_status(); + get_data_from_buffer_table( l_last_read_message_id, l_buffer_data, l_buffer_rowids, l_finished_flags ); + + --nothing fetched from output, wait and try again + if l_buffer_data.count = 0 then + + dbms_lock.sleep(l_sleep_time); + l_already_waited_sec := l_already_waited_sec + l_sleep_time; + + -- if waited more than lc_1_second seconds then increase wait period to minimize the CPU usage. + if l_already_waited_sec >= lc_1_second then + l_sleep_time := lc_500_milisec; + end if; + + else + + l_already_waited_sec := 0; + l_sleep_time := lc_100_milisec; + + for i in 1 .. l_buffer_data.count loop + if l_buffer_data(i).text is not null then + pipe row( l_buffer_data(i) ); + elsif l_finished_flags(i) = 1 then + l_data_finished := true; + exit; + end if; + end loop; + + remove_read_data(l_buffer_rowids); + + end if; + l_producer_started := (l_lock_status <> 0 or l_buffer_data.count > 0) or l_producer_started; + l_producer_finished := (l_producer_started and l_lock_status = 0 and l_buffer_data.count = 0) or l_producer_finished; + + if not l_producer_started and l_already_waited_sec >= lc_init_wait_sec then + + if lc_init_wait_sec > 0 then + self.remove_buffer_info(); + raise_application_error( + ut_utils.gc_out_buffer_timeout, + 'Timeout occurred while waiting for report data producer to start. Waited for: '||ut_utils.to_string( l_already_waited_sec )||' seconds.' + ); + else + l_finished := true; + end if; + + elsif not l_producer_finished and a_timeout_sec is not null and l_already_waited_sec >= a_timeout_sec then + + if a_timeout_sec > 0 then + self.remove_buffer_info(); + raise_application_error( + ut_utils.gc_out_buffer_timeout, + 'Timeout occurred while waiting for more data from producer. Waited for: '||ut_utils.to_string( l_already_waited_sec )||' seconds.' + ); + else + l_finished := true; + end if; + + elsif (l_data_finished or l_producer_finished) then + l_finished := true; + end if; + end loop; + self.remove_buffer_info(); + return; + end; + + member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor is l_lines sys_refcursor; begin open l_lines for @@ -44,7 +169,7 @@ create or replace type body ut_output_buffer_base is return l_lines; end; - member procedure lines_to_dbms_output(self in ut_output_buffer_base, a_initial_timeout natural := null, a_timeout_sec natural := null) is + member procedure lines_to_dbms_output(self in ut_output_buffer_base, a_initial_timeout number := null, a_timeout_sec number := null) is l_data sys_refcursor; l_clob clob; l_item_type varchar2(32767); @@ -63,7 +188,7 @@ create or replace type body ut_output_buffer_base is end; member procedure cleanup_buffer(self in ut_output_buffer_base, a_retention_time_sec natural := null) is - gc_buffer_retention_sec constant naturaln := coalesce(a_retention_time_sec, 60 * 60 * 24); -- 24 hours + gc_buffer_retention_sec constant naturaln := coalesce(a_retention_time_sec, 60 * 60 * 24 * 5); -- 5 days l_retention_days number := gc_buffer_retention_sec / (60 * 60 * 24); l_max_retention_date date := sysdate - l_retention_days; pragma autonomous_transaction; diff --git a/source/core/output_buffers/ut_output_buffer_base.tps b/source/core/output_buffers/ut_output_buffer_base.tps index 98a6847cd..8000ea2e7 100644 --- a/source/core/output_buffers/ut_output_buffer_base.tps +++ b/source/core/output_buffers/ut_output_buffer_base.tps @@ -19,16 +19,27 @@ create or replace type ut_output_buffer_base force authid definer as object( output_id raw(32), is_closed number(1,0), start_date date, - last_message_id number(38,0), + last_write_message_id number(38,0), + lock_handle varchar2(30 byte), self_type varchar2(250 byte), member procedure init(self in out nocopy ut_output_buffer_base, a_output_id raw := null, a_self_type varchar2 := null), - member function get_lines_cursor(a_initial_timeout natural := null, a_timeout_sec natural := null) return sys_refcursor, - member procedure lines_to_dbms_output(self in ut_output_buffer_base, a_initial_timeout natural := null, a_timeout_sec natural := null), + member procedure lock_buffer(a_timeout_sec number := null), + member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor, + member procedure lines_to_dbms_output(self in ut_output_buffer_base, a_initial_timeout number := null, a_timeout_sec number := null), member procedure cleanup_buffer(self in ut_output_buffer_base, a_retention_time_sec natural := null), - not instantiable member procedure close(self in out nocopy ut_output_buffer_base), + member procedure remove_buffer_info(self in ut_output_buffer_base), + not instantiable member procedure get_data_from_buffer_table( + self in ut_output_buffer_base, + a_last_read_message_id in out nocopy integer, + a_buffer_data out nocopy ut_output_data_rows, + a_buffer_rowids out nocopy ut_varchar2_rows, + a_finished_flags out nocopy ut_integer_list + ), + member procedure close(self in out nocopy ut_output_buffer_base), + not instantiable member procedure remove_read_data(self in ut_output_buffer_base, a_buffer_rowids ut_varchar2_rows), not instantiable member procedure send_line(self in out nocopy ut_output_buffer_base, a_text varchar2, a_item_type varchar2 := null), not instantiable member procedure send_lines(self in out nocopy ut_output_buffer_base, a_text_list ut_varchar2_rows, a_item_type varchar2 := null), not instantiable member procedure send_clob(self in out nocopy ut_output_buffer_base, a_text clob, a_item_type varchar2 := null), - not instantiable member function get_lines(a_initial_timeout natural := null, a_timeout_sec natural := null) return ut_output_data_rows pipelined + member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined ) not final not instantiable / diff --git a/source/core/output_buffers/ut_output_clob_table_buffer.tpb b/source/core/output_buffers/ut_output_clob_table_buffer.tpb index 66ff71c62..e47f0bcb0 100644 --- a/source/core/output_buffers/ut_output_clob_table_buffer.tpb +++ b/source/core/output_buffers/ut_output_clob_table_buffer.tpb @@ -22,23 +22,13 @@ create or replace type body ut_output_clob_table_buffer is return; end; - overriding member procedure close(self in out nocopy ut_output_clob_table_buffer) is - pragma autonomous_transaction; - begin - self.last_message_id := self.last_message_id + 1; - insert /*+ no_parallel */ into ut_output_clob_buffer_tmp(output_id, message_id, is_finished) - values (self.output_id, self.last_message_id, 1); - commit; - self.is_closed := 1; - end; - overriding member procedure send_line(self in out nocopy ut_output_clob_table_buffer, a_text varchar2, a_item_type varchar2 := null) is pragma autonomous_transaction; begin if a_text is not null or a_item_type is not null then - self.last_message_id := self.last_message_id + 1; + self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_clob_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_message_id, a_text, a_item_type); + values (self.output_id, self.last_write_message_id, a_text, a_item_type); end if; commit; end; @@ -47,10 +37,10 @@ create or replace type body ut_output_clob_table_buffer is pragma autonomous_transaction; begin insert /*+ no_parallel */ into ut_output_clob_buffer_tmp(output_id, message_id, text, item_type) - select /*+ no_parallel */ self.output_id, self.last_message_id + rownum, t.column_value, a_item_type + select /*+ no_parallel */ self.output_id, self.last_write_message_id + rownum, t.column_value, a_item_type from table(a_text_list) t where t.column_value is not null or a_item_type is not null; - self.last_message_id := self.last_message_id + SQL%rowcount; + self.last_write_message_id := self.last_write_message_id + SQL%rowcount; commit; end; @@ -58,99 +48,43 @@ create or replace type body ut_output_clob_table_buffer is pragma autonomous_transaction; begin if a_text is not null and a_text != empty_clob() or a_item_type is not null then - self.last_message_id := self.last_message_id + 1; + self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_clob_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_message_id, a_text, a_item_type); + values (self.output_id, self.last_write_message_id, a_text, a_item_type); end if; commit; end; - overriding member function get_lines(a_initial_timeout natural := null, a_timeout_sec natural := null) return ut_output_data_rows pipelined is - type t_rowid_tab is table of urowid; - l_message_rowids t_rowid_tab; - l_buffer_data ut_output_data_rows; - l_finished_flags ut_integer_list; - l_already_waited_for number(10,2) := 0; - l_finished boolean := false; - lc_init_wait_sec constant naturaln := coalesce(a_initial_timeout, 60 ); -- 1 minute - lc_max_wait_sec constant naturaln := coalesce(a_timeout_sec, 60 * 60 * 4); -- 4 hours - l_wait_for integer := lc_init_wait_sec; - lc_short_sleep_time constant number(1,1) := 0.1; --sleep for 100 ms between checks - lc_long_sleep_time constant number(1) := 1; --sleep for 1 s when waiting long - lc_long_wait_time constant number(1) := 1; --waiting more than 1 sec - l_sleep_time number(2,1) := lc_short_sleep_time; - lc_bulk_limit constant integer := 5000; - l_max_message_id integer := lc_bulk_limit; - - procedure remove_read_data(a_message_rowids t_rowid_tab) is - pragma autonomous_transaction; - begin - forall i in 1 .. a_message_rowids.count - delete from ut_output_clob_buffer_tmp a - where rowid = a_message_rowids(i); - commit; - end; + overriding member procedure get_data_from_buffer_table( + self in ut_output_clob_table_buffer, + a_last_read_message_id in out nocopy integer, + a_buffer_data out nocopy ut_output_data_rows, + a_buffer_rowids out nocopy ut_varchar2_rows, + a_finished_flags out nocopy ut_integer_list + ) is + lc_bulk_limit constant integer := 5000; + begin + a_last_read_message_id := coalesce(a_last_read_message_id, 0); + with ordered_buffer as ( + select /*+ no_parallel index(a) */ ut_output_data_row(a.text, a.item_type), rowidtochar(a.rowid), is_finished + from ut_output_clob_buffer_tmp a + where a.output_id = self.output_id + and a.message_id <= a_last_read_message_id + lc_bulk_limit + order by a.message_id + ) + select /*+ no_parallel */ b.* + bulk collect into a_buffer_data, a_buffer_rowids, a_finished_flags + from ordered_buffer b; + a_last_read_message_id := a_last_read_message_id + a_finished_flags.count; + end; - procedure remove_buffer_info is + overriding member procedure remove_read_data(self in ut_output_clob_table_buffer, a_buffer_rowids ut_varchar2_rows) is pragma autonomous_transaction; - begin - delete from ut_output_buffer_info_tmp a - where a.output_id = self.output_id; - commit; - end; - - begin - while not l_finished loop - with ordered_buffer as ( - select /*+ no_parallel index(a) */ a.rowid, ut_output_data_row(a.text, a.item_type), is_finished - from ut_output_clob_buffer_tmp a - where a.output_id = self.output_id - and a.message_id <= l_max_message_id - order by a.message_id - ) - select /*+ no_parallel */ b.* - bulk collect into l_message_rowids, l_buffer_data, l_finished_flags - from ordered_buffer b; - - --nothing fetched from output, wait and try again - if l_buffer_data.count = 0 then - $if dbms_db_version.version >= 18 $then - dbms_session.sleep(l_sleep_time); - $else - dbms_lock.sleep(l_sleep_time); - $end - l_already_waited_for := l_already_waited_for + l_sleep_time; - if l_already_waited_for > lc_long_wait_time then - l_sleep_time := lc_long_sleep_time; - end if; - else - --reset wait time - -- we wait lc_max_wait_sec for new message - l_wait_for := lc_max_wait_sec; - l_already_waited_for := 0; - l_sleep_time := lc_short_sleep_time; - for i in 1 .. l_buffer_data.count loop - if l_buffer_data(i).text is not null then - pipe row(l_buffer_data(i)); - elsif l_finished_flags(i) = 1 then - l_finished := true; - exit; - end if; - end loop; - remove_read_data(l_message_rowids); - l_max_message_id := l_max_message_id + lc_bulk_limit; - end if; - if l_finished or l_already_waited_for >= l_wait_for then - remove_buffer_info(); - if l_already_waited_for > 0 and l_already_waited_for >= l_wait_for then - raise_application_error( - ut_utils.gc_out_buffer_timeout, - 'Timeout occurred while waiting for output data. Waited for: '||l_already_waited_for||' seconds.' - ); - end if; - end if; - end loop; - return; + begin + forall i in 1 .. a_buffer_rowids.count + delete from ut_output_clob_buffer_tmp a + where rowid = chartorowid(a_buffer_rowids(i)); + commit; end; end; diff --git a/source/core/output_buffers/ut_output_clob_table_buffer.tps b/source/core/output_buffers/ut_output_clob_table_buffer.tps index 7b98efaba..ccd710a8f 100644 --- a/source/core/output_buffers/ut_output_clob_table_buffer.tps +++ b/source/core/output_buffers/ut_output_clob_table_buffer.tps @@ -20,7 +20,13 @@ create or replace type ut_output_clob_table_buffer under ut_output_buffer_base ( overriding member procedure send_line(self in out nocopy ut_output_clob_table_buffer, a_text varchar2, a_item_type varchar2 := null), overriding member procedure send_lines(self in out nocopy ut_output_clob_table_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null), overriding member procedure send_clob(self in out nocopy ut_output_clob_table_buffer, a_text clob, a_item_type varchar2 := null), - overriding member procedure close(self in out nocopy ut_output_clob_table_buffer), - overriding member function get_lines(a_initial_timeout natural := null, a_timeout_sec natural := null) return ut_output_data_rows pipelined + overriding member procedure get_data_from_buffer_table( + self in ut_output_clob_table_buffer, + a_last_read_message_id in out nocopy integer, + a_buffer_data out nocopy ut_output_data_rows, + a_buffer_rowids out nocopy ut_varchar2_rows, + a_finished_flags out nocopy ut_integer_list + ), + overriding member procedure remove_read_data(self in ut_output_clob_table_buffer, a_buffer_rowids ut_varchar2_rows) ) not final / diff --git a/source/core/output_buffers/ut_output_table_buffer.tpb b/source/core/output_buffers/ut_output_table_buffer.tpb index 1809a49d5..189baf075 100644 --- a/source/core/output_buffers/ut_output_table_buffer.tpb +++ b/source/core/output_buffers/ut_output_table_buffer.tpb @@ -22,16 +22,6 @@ create or replace type body ut_output_table_buffer is return; end; - overriding member procedure close(self in out nocopy ut_output_table_buffer) is - pragma autonomous_transaction; - begin - self.last_message_id := self.last_message_id + 1; - insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, is_finished) - values (self.output_id, self.last_message_id, 1); - commit; - self.is_closed := 1; - end; - overriding member procedure send_line(self in out nocopy ut_output_table_buffer, a_text varchar2, a_item_type varchar2 := null) is pragma autonomous_transaction; begin @@ -44,9 +34,9 @@ create or replace type body ut_output_table_buffer is a_item_type ); else - self.last_message_id := self.last_message_id + 1; + self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_message_id, a_text, a_item_type); + values (self.output_id, self.last_write_message_id, a_text, a_item_type); end if; commit; end if; @@ -56,10 +46,10 @@ create or replace type body ut_output_table_buffer is pragma autonomous_transaction; begin insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - select /*+ no_parallel */ self.output_id, self.last_message_id + rownum, t.column_value, a_item_type + select /*+ no_parallel */ self.output_id, self.last_write_message_id + rownum, t.column_value, a_item_type from table(a_text_list) t where t.column_value is not null or a_item_type is not null; - self.last_message_id := self.last_message_id + SQL%rowcount; + self.last_write_message_id := self.last_write_message_id + SQL%rowcount; commit; end; @@ -75,100 +65,41 @@ create or replace type body ut_output_table_buffer is a_item_type ); else - self.last_message_id := self.last_message_id + 1; + self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_message_id, a_text, a_item_type); + values (self.output_id, self.last_write_message_id, a_text, a_item_type); end if; commit; end if; end; - overriding member function get_lines(a_initial_timeout natural := null, a_timeout_sec natural := null) return ut_output_data_rows pipelined is - l_buffer_data ut_varchar2_rows; - l_item_types ut_varchar2_rows; - l_finished_flags ut_integer_list; - l_already_waited_for number(10,2) := 0; - l_finished boolean := false; - lc_init_wait_sec constant naturaln := coalesce(a_initial_timeout, 60 ); -- 1 minute - lc_max_wait_sec constant naturaln := coalesce(a_timeout_sec, 60 * 60 * 4); -- 4 hours - l_wait_for integer := lc_init_wait_sec; - lc_short_sleep_time constant number(1,1) := 0.1; --sleep for 100 ms between checks - lc_long_sleep_time constant number(1) := 1; --sleep for 1 s when waiting long - lc_long_wait_time constant number(1) := 1; --waiting more than 1 sec - l_sleep_time number(2,1) := lc_short_sleep_time; - lc_bulk_limit constant integer := 5000; - l_max_message_id integer := lc_bulk_limit; - - procedure get_data_from_buffer( - a_max_message_id integer, - a_buffer_data out nocopy ut_varchar2_rows, - a_item_types out nocopy ut_varchar2_rows, - a_finished_flags out nocopy ut_integer_list - ) is - pragma autonomous_transaction; - begin - delete /*+ no_parallel */ from ( - select /*+ no_parallel */ * - from ut_output_buffer_tmp o - where o.output_id = self.output_id - and o.message_id <= a_max_message_id - order by o.message_id - ) d - returning d.text, d.item_type, d.is_finished - bulk collect into a_buffer_data, a_item_types, a_finished_flags; - commit; - - end; - - procedure remove_buffer_info is - pragma autonomous_transaction; - begin - delete from ut_output_buffer_info_tmp a - where a.output_id = self.output_id; - commit; - end; + overriding member procedure get_data_from_buffer_table( + self in ut_output_table_buffer, + a_last_read_message_id in out nocopy integer, + a_buffer_data out nocopy ut_output_data_rows, + a_buffer_rowids out nocopy ut_varchar2_rows, + a_finished_flags out nocopy ut_integer_list + ) is + lc_bulk_limit constant integer := 20000; + pragma autonomous_transaction; + begin + a_last_read_message_id := coalesce(a_last_read_message_id,0); + delete /*+ no_parallel */ from ( + select /*+ no_parallel */ * + from ut_output_buffer_tmp o + where o.output_id = self.output_id + and o.message_id <= a_last_read_message_id + lc_bulk_limit + order by o.message_id + ) d + returning ut_output_data_row(d.text, d.item_type), d.is_finished + bulk collect into a_buffer_data, a_finished_flags; + a_last_read_message_id := a_last_read_message_id + a_finished_flags.count; + commit; + end; - begin - while not l_finished loop - get_data_from_buffer( l_max_message_id, l_buffer_data, l_item_types, l_finished_flags); - --nothing fetched from output, wait and try again - if l_buffer_data.count = 0 then - $if dbms_db_version.version >= 18 $then - dbms_session.sleep(l_sleep_time); - $else - dbms_lock.sleep(l_sleep_time); - $end - l_already_waited_for := l_already_waited_for + l_sleep_time; - if l_already_waited_for > lc_long_wait_time then - l_sleep_time := lc_long_sleep_time; - end if; - else - --reset wait time - -- we wait lc_max_wait_sec for new message - l_wait_for := lc_max_wait_sec; - l_already_waited_for := 0; - l_sleep_time := lc_short_sleep_time; - for i in 1 .. l_buffer_data.count loop - if l_buffer_data(i) is not null then - pipe row(ut_output_data_row(l_buffer_data(i),l_item_types(i))); - elsif l_finished_flags(i) = 1 then - l_finished := true; - exit; - end if; - end loop; - l_max_message_id := l_max_message_id + lc_bulk_limit; - end if; - if l_finished or l_already_waited_for >= l_wait_for then - remove_buffer_info(); - if l_already_waited_for > 0 and l_already_waited_for >= l_wait_for then - raise_application_error( - ut_utils.gc_out_buffer_timeout, - 'Timeout occurred while waiting for output data. Waited for: '||l_already_waited_for||' seconds.' - ); - end if; - end if; - end loop; - return; + overriding member procedure remove_read_data(self in ut_output_table_buffer, a_buffer_rowids ut_varchar2_rows) is + begin + null; end; end; diff --git a/source/core/output_buffers/ut_output_table_buffer.tps b/source/core/output_buffers/ut_output_table_buffer.tps index 726b692f8..721e5eb8a 100644 --- a/source/core/output_buffers/ut_output_table_buffer.tps +++ b/source/core/output_buffers/ut_output_table_buffer.tps @@ -20,7 +20,13 @@ create or replace type ut_output_table_buffer under ut_output_buffer_base ( overriding member procedure send_line(self in out nocopy ut_output_table_buffer, a_text varchar2, a_item_type varchar2 := null), overriding member procedure send_lines(self in out nocopy ut_output_table_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null), overriding member procedure send_clob(self in out nocopy ut_output_table_buffer, a_text clob, a_item_type varchar2 := null), - overriding member procedure close(self in out nocopy ut_output_table_buffer), - overriding member function get_lines(a_initial_timeout natural := null, a_timeout_sec natural := null) return ut_output_data_rows pipelined + overriding member procedure get_data_from_buffer_table( + self in ut_output_table_buffer, + a_last_read_message_id in out nocopy integer, + a_buffer_data out nocopy ut_output_data_rows, + a_buffer_rowids out nocopy ut_varchar2_rows, + a_finished_flags out nocopy ut_integer_list + ), + overriding member procedure remove_read_data(self in ut_output_table_buffer, a_buffer_rowids ut_varchar2_rows) ) not final / diff --git a/source/core/types/ut_output_reporter_base.tpb b/source/core/types/ut_output_reporter_base.tpb index f6bb27b94..48970be5a 100644 --- a/source/core/types/ut_output_reporter_base.tpb +++ b/source/core/types/ut_output_reporter_base.tpb @@ -41,13 +41,6 @@ create or replace type body ut_output_reporter_base is return l_result; end; - overriding member procedure before_calling_run(self in out nocopy ut_output_reporter_base, a_run in ut_run) is - l_output_table_buffer ut_output_table_buffer; - begin - (self as ut_reporter_base).before_calling_run(a_run); - l_output_table_buffer := treat(self.output_buffer as ut_output_table_buffer); - end; - member procedure print_text(self in out nocopy ut_output_reporter_base, a_text varchar2, a_item_type varchar2 := null) is begin self.output_buffer.send_line(a_text, a_item_type); @@ -87,6 +80,7 @@ create or replace type body ut_output_reporter_base is overriding member procedure on_initialize(self in out nocopy ut_output_reporter_base, a_run in ut_run) is begin + self.output_buffer.lock_buffer(); self.output_buffer.send_line(null, 'initialize'); end; diff --git a/source/core/types/ut_output_reporter_base.tps b/source/core/types/ut_output_reporter_base.tps index 22f507f8d..21eed9957 100644 --- a/source/core/types/ut_output_reporter_base.tps +++ b/source/core/types/ut_output_reporter_base.tps @@ -20,8 +20,7 @@ create or replace type ut_output_reporter_base under ut_reporter_base( member procedure init(self in out nocopy ut_output_reporter_base, a_self_type varchar2, a_output_buffer ut_output_buffer_base := null), overriding member procedure set_reporter_id(self in out nocopy ut_output_reporter_base, a_reporter_id raw), member function set_reporter_id(self in ut_output_reporter_base, a_reporter_id raw) return ut_output_reporter_base, - overriding member procedure before_calling_run(self in out nocopy ut_output_reporter_base, a_run in ut_run), - + member procedure print_text(self in out nocopy ut_output_reporter_base, a_text varchar2, a_item_type varchar2 := null), member procedure print_text_lines(self in out nocopy ut_output_reporter_base, a_text_lines ut_varchar2_rows, a_item_type varchar2 := null), member procedure print_clob(self in out nocopy ut_output_reporter_base, a_clob clob, a_item_type varchar2 := null), diff --git a/source/create_utplsql_owner.sql b/source/create_utplsql_owner.sql index 64bcb52ce..d7e4f3040 100644 --- a/source/create_utplsql_owner.sql +++ b/source/create_utplsql_owner.sql @@ -31,15 +31,7 @@ create user &ut3_owner_schema identified by "&ut3_password" default tablespace & grant create session, create sequence, create procedure, create type, create table, create view, create synonym to &ut3_owner_schema; -begin - $if dbms_db_version.version < 18 $then - execute immediate 'grant execute on dbms_lock to &ut3_owner_schema'; - $else - null; - $end -end; -/ - +grant execute on dbms_lock to &ut3_owner_schema; grant execute on dbms_crypto to &ut3_owner_schema; grant execute on dbms_lob to &ut3_owner_schema; grant execute on dbms_xmlgen to &ut3_owner_schema; diff --git a/test/ut3_tester/core/test_output_buffer.pkb b/test/ut3_tester/core/test_output_buffer.pkb index 2e8b3337c..c5a4c07b1 100644 --- a/test/ut3_tester/core/test_output_buffer.pkb +++ b/test/ut3_tester/core/test_output_buffer.pkb @@ -16,12 +16,13 @@ create or replace package body test_output_buffer is || chr(13) || chr(10) || to_clob(lpad('a text', 31000, ',a text')) || to_clob(lpad('a text', 31000, ',a text')); l_expected_item_type := lpad('some item type',1000,'-'); --Act + l_buffer.lock_buffer(); l_buffer.send_clob(l_expected_text, l_expected_item_type); l_buffer.close(); select text, item_type into l_actual_text, l_actual_item_type - from table(l_buffer.get_lines(0,0)); + from table(l_buffer.get_lines(0.1,0.1)); --Assert ut.expect(l_actual_text).to_equal(l_expected_text); @@ -32,7 +33,14 @@ create or replace package body test_output_buffer is ut.expect(l_remaining).to_equal(0); end; - + + procedure test_wait_for_producer is + l_buffer ut3_develop.ut_output_buffer_base; + begin + l_buffer := ut3_develop.ut_output_clob_table_buffer(); + ut.expect( l_buffer.get_lines_cursor(0.1,0) ).to_be_empty(); + end; + procedure test_doesnt_send_on_null_text is l_cur sys_refcursor; l_result integer; @@ -86,11 +94,12 @@ create or replace package body test_output_buffer is begin --Arrange l_expected := 'a text'; + l_buffer.lock_buffer(); l_buffer.send_line(l_expected); l_start := localtimestamp; --Act begin - select text into l_result from table(l_buffer.get_lines(1,1)); + select text into l_result from table(l_buffer.get_lines(0,0.3)); ut.fail('Expected a timeout exception but nothing was raised'); exception when others then @@ -101,7 +110,7 @@ create or replace package body test_output_buffer is --Throws a timeout exception ut.expect(dbms_utility.format_error_stack()).to_match('ORA'||ut3_develop.ut_utils.gc_out_buffer_timeout); --Waited for one second - ut.expect(l_duration).to_be_greater_than(interval '0.99' second); + ut.expect(l_duration).to_be_greater_or_equal(interval '0.3' second); end; select count(1) into l_remaining from table(ut3_tester_helper.run_helper.ut_output_buffer_tmp) where output_id = l_buffer.output_id; @@ -116,13 +125,15 @@ create or replace package body test_output_buffer is l_buffer ut3_develop.ut_output_buffer_base; begin --Arrange - l_stale_buffer.start_date := sysdate - 2; + l_stale_buffer.start_date := sysdate - 10; --initialize with new start date l_stale_buffer.init(); + l_stale_buffer.lock_buffer(); l_stale_buffer.send_line('some text'); l_stale_buffer.close(); l_fresh_buffer := ut3_develop.ut_output_table_buffer(); + l_fresh_buffer.lock_buffer(); l_fresh_buffer.send_line('some text'); l_fresh_buffer.close(); @@ -131,9 +142,9 @@ create or replace package body test_output_buffer is --Assert -- Data in "fresh" buffer remains - ut.expect( l_fresh_buffer.get_lines_cursor(0,0), l_buffer.self_type ).to_have_count(1); + ut.expect( l_fresh_buffer.get_lines_cursor(0,0), l_fresh_buffer.self_type ).to_have_count(1); -- Data in "stale" buffer is purged and so the call to get_lines_cursor throws ORA-20218 - ut.expect( l_stale_buffer.get_lines_cursor(0,0), l_buffer.self_type ).to_be_empty(); + ut.expect( l_stale_buffer.get_lines_cursor(0,0), l_stale_buffer.self_type ).to_be_empty(); end; procedure test_purge_text_buffer is diff --git a/test/ut3_tester/core/test_output_buffer.pks b/test/ut3_tester/core/test_output_buffer.pks index 24c2c01eb..feaa337f8 100644 --- a/test/ut3_tester/core/test_output_buffer.pks +++ b/test/ut3_tester/core/test_output_buffer.pks @@ -2,10 +2,33 @@ create or replace package test_output_buffer is --%suite(output_buffer) --%suitepath(utplsql.ut3_tester.core) + + + --%context(Read and write within the same session) + + + --%endcontext + --%context(Buffer is read in a different session than buffer write) + + --reader will wait for a_initial_timeout seconds for the writer process to start and then it will finish with error + + --reader will wait forever (beyond a_initial_timeout) if the writer process is started and end of data row was not received from the buffer + + --reader stops after reading the end of data signal from the buffer + + --reader stops when writer process ends and all data was read from the buffer + + + --%endcontext + --%test(Receives a line from buffer table and deletes) procedure test_receive; + --%test(Waits specified time for producer to lock the buffer ) + --%throws(-20218) + procedure test_wait_for_producer; + --%test(Does not send line if null text given) procedure test_doesnt_send_on_null_text; @@ -19,11 +42,9 @@ create or replace package test_output_buffer is procedure test_waiting_for_data; --%test(Purges text buffer data older than one day and leaves the rest) - --%throws(-20218) procedure test_purge_text_buffer; --%test(Purges clob buffer data older than one day and leaves the rest) - --%throws(-20218) procedure test_purge_clob_buffer; end test_output_buffer; diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index 99f26e9f8..3823d9d0c 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -305,15 +305,6 @@ create or replace package body coverage_helper is return l_status; end; - procedure sleep(a_time number) is - begin - $if dbms_db_version.version >= 18 $then - dbms_session.sleep(a_time); - $else - dbms_lock.sleep(a_time ); - $end - end; - procedure run_job_and_wait_for_finish(a_job_action varchar2) is l_status varchar2(1000); l_job_name varchar2(30); @@ -323,7 +314,7 @@ create or replace package body coverage_helper is begin g_job_no := g_job_no + 1; l_job_name := 'utPLSQL_selftest_job_'||g_job_no; - sleep(0.15); + dbms_lock.sleep(0.15); dbms_scheduler.create_job( job_name => l_job_name, job_type => 'PLSQL_BLOCK', @@ -333,13 +324,13 @@ create or replace package body coverage_helper is auto_drop => TRUE, comments => 'one-time-job' ); - while (l_status is null or l_status not in ('SUCCEEDED','FAILED')) and i < 150 loop + while (l_status is null or l_status not in ('SUCCEEDED','FAILED')) and i < 300 loop l_status := get_job_status( l_job_name, l_timestamp ); - sleep(0.1); + dbms_lock.sleep(0.1); i := i + 1; end loop; commit; - if l_status = 'FAILED' then + if nvl(l_status,'null') <> 'SUCCEEDED' then raise_application_error(-20000, 'Running a scheduler job failed'); end if; end; @@ -378,7 +369,7 @@ create or replace package body coverage_helper is pragma autonomous_transaction; begin run_job_and_wait_for_finish( a_plsql_block ); - + dbms_lock.sleep(0.1); execute immediate q'[ declare l_results ut3_develop.ut_varchar2_list; From a64bd1428499ad207571cd93fcdda78d661d6d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20G=C4=99bal?= Date: Thu, 9 Feb 2023 16:34:53 +0000 Subject: [PATCH 120/187] Update RunExampleTestSuiteWithCompositeReporter.sql --- .../RunExampleTestSuiteWithCompositeReporter.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/developer_examples/RunExampleTestSuiteWithCompositeReporter.sql b/examples/developer_examples/RunExampleTestSuiteWithCompositeReporter.sql index 468d176ed..e713fa02d 100644 --- a/examples/developer_examples/RunExampleTestSuiteWithCompositeReporter.sql +++ b/examples/developer_examples/RunExampleTestSuiteWithCompositeReporter.sql @@ -20,6 +20,7 @@ begin ut_event_manager.initialize(); ut_event_manager.add_listener(l_doc_reporter); ut_event_manager.add_listener(l_tc_reporter); + ut_event_manager.trigger_event(ut_event_manager.gc_initialize, l_run); l_suite := ut_suite(user, 'ut_exampletest',a_line_no=>1); l_suite.description := 'Test Suite Name'; From c1d5ab6c24cb94af1cc22877d31c4b4c13037822 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 10 Feb 2023 01:31:44 +0200 Subject: [PATCH 121/187] Extended schediler job timeout to 10 minutes to allow for slow execution on older DB versions. We should investigate to see why execution is so slow on 11.2 and 12.1 --- test/ut3_tester_helper/coverage_helper.pkb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index 3823d9d0c..2a508ca6a 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -290,11 +290,11 @@ create or replace package body coverage_helper is ut3_develop.ut_runner.coverage_stop(); end; - function get_job_status(a_job_name varchar2, a_job_started_after timestamp with time zone) return varchar2 is - l_status varchar2(1000); + function get_job_status(a_job_name varchar2, a_job_started_after timestamp with time zone) return user_scheduler_job_run_details%rowtype is + l_result user_scheduler_job_run_details%rowtype; begin begin - select status into l_status + select * into l_result from user_scheduler_job_run_details where job_name = upper(a_job_name) and req_start_date >= a_job_started_after; @@ -302,11 +302,11 @@ create or replace package body coverage_helper is when no_data_found then null; end; - return l_status; + return l_result; end; procedure run_job_and_wait_for_finish(a_job_action varchar2) is - l_status varchar2(1000); + l_job_run_info user_scheduler_job_run_details%rowtype; l_job_name varchar2(30); l_timestamp timestamp with time zone := current_timestamp; i integer := 0; @@ -324,14 +324,14 @@ create or replace package body coverage_helper is auto_drop => TRUE, comments => 'one-time-job' ); - while (l_status is null or l_status not in ('SUCCEEDED','FAILED')) and i < 300 loop - l_status := get_job_status( l_job_name, l_timestamp ); + while (l_job_run_info.status is null or l_job_run_info.status not in ('SUCCEEDED','FAILED')) and i < 6000 loop + l_job_run_info := get_job_status( l_job_name, l_timestamp ); dbms_lock.sleep(0.1); i := i + 1; end loop; commit; - if nvl(l_status,'null') <> 'SUCCEEDED' then - raise_application_error(-20000, 'Running a scheduler job failed'); + if nvl(l_job_run_info.status,'null') <> 'SUCCEEDED' then + raise_application_error(-20000, 'Scheduler job '''||l_job_name||''', status='''||l_job_run_info.status||'''. Additional info: '||l_job_run_info.additional_info); end if; end; From 99447ed877c9deea0f21cda59ca2f326ad2914be Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 10 Feb 2023 12:35:52 +0200 Subject: [PATCH 122/187] Improving performance of output buffer processing. --- .../core/output_buffers/ut_output_buffer_base.tpb | 12 ++++++++---- .../core/output_buffers/ut_output_table_buffer.tpb | 14 ++++++++++++++ .../core/output_buffers/ut_output_table_buffer.tps | 1 + 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/source/core/output_buffers/ut_output_buffer_base.tpb b/source/core/output_buffers/ut_output_buffer_base.tpb index c3a137b42..c9cffe339 100644 --- a/source/core/output_buffers/ut_output_buffer_base.tpb +++ b/source/core/output_buffers/ut_output_buffer_base.tpb @@ -179,10 +179,14 @@ create or replace type body ut_output_buffer_base is loop fetch l_data into l_clob, l_item_type; exit when l_data%notfound; - l_lines := ut_utils.clob_to_table(l_clob); - for i in 1 .. l_lines.count loop - dbms_output.put_line(l_lines(i)); - end loop; + if dbms_lob.getlength(l_clob) > 32767 then + l_lines := ut_utils.clob_to_table(l_clob); + for i in 1 .. l_lines.count loop + dbms_output.put_line(l_lines(i)); + end loop; + else + dbms_output.put_line(l_clob); + end if; end loop; close l_data; end; diff --git a/source/core/output_buffers/ut_output_table_buffer.tpb b/source/core/output_buffers/ut_output_table_buffer.tpb index 189baf075..599b56846 100644 --- a/source/core/output_buffers/ut_output_table_buffer.tpb +++ b/source/core/output_buffers/ut_output_table_buffer.tpb @@ -73,6 +73,20 @@ create or replace type body ut_output_table_buffer is end if; end; + overriding member procedure lines_to_dbms_output(self in ut_output_table_buffer, a_initial_timeout number := null, a_timeout_sec number := null) is + l_data sys_refcursor; + l_text varchar2(32767); + l_item_type varchar2(32767); + begin + l_data := self.get_lines_cursor(a_initial_timeout, a_timeout_sec); + loop + fetch l_data into l_text, l_item_type; + exit when l_data%notfound; + dbms_output.put_line(l_text); + end loop; + close l_data; + end; + overriding member procedure get_data_from_buffer_table( self in ut_output_table_buffer, a_last_read_message_id in out nocopy integer, diff --git a/source/core/output_buffers/ut_output_table_buffer.tps b/source/core/output_buffers/ut_output_table_buffer.tps index 721e5eb8a..b7ef8a3e7 100644 --- a/source/core/output_buffers/ut_output_table_buffer.tps +++ b/source/core/output_buffers/ut_output_table_buffer.tps @@ -20,6 +20,7 @@ create or replace type ut_output_table_buffer under ut_output_buffer_base ( overriding member procedure send_line(self in out nocopy ut_output_table_buffer, a_text varchar2, a_item_type varchar2 := null), overriding member procedure send_lines(self in out nocopy ut_output_table_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null), overriding member procedure send_clob(self in out nocopy ut_output_table_buffer, a_text clob, a_item_type varchar2 := null), + overriding member procedure lines_to_dbms_output(self in ut_output_table_buffer, a_initial_timeout number := null, a_timeout_sec number := null), overriding member procedure get_data_from_buffer_table( self in ut_output_table_buffer, a_last_read_message_id in out nocopy integer, From 07f79e29e65e73e38c9219b3188c66f13acb02b4 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 10 Feb 2023 18:59:22 +0200 Subject: [PATCH 123/187] Fixed performance issues introduced with previous refactoring. --- .../output_buffers/ut_output_buffer_base.tpb | 129 ++++++------------ .../output_buffers/ut_output_buffer_base.tps | 13 +- .../ut_output_clob_table_buffer.tpb | 106 ++++++++++---- .../ut_output_clob_table_buffer.tps | 9 +- .../output_buffers/ut_output_table_buffer.tpb | 69 ++++++++-- .../output_buffers/ut_output_table_buffer.tps | 9 +- 6 files changed, 183 insertions(+), 152 deletions(-) diff --git a/source/core/output_buffers/ut_output_buffer_base.tpb b/source/core/output_buffers/ut_output_buffer_base.tpb index c9cffe339..be4c92bd8 100644 --- a/source/core/output_buffers/ut_output_buffer_base.tpb +++ b/source/core/output_buffers/ut_output_buffer_base.tpb @@ -64,100 +64,51 @@ create or replace type body ut_output_buffer_base is commit; end; - member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined is - lc_init_wait_sec constant number := coalesce(a_initial_timeout, 10 ); - lc_100_milisec constant number(1,1) := 0.1; --sleep for 100 ms between checks - lc_500_milisec constant number(3,1) := 0.5; --sleep for 1 s when waiting long - lc_1_second constant number(3,1) := 1; - l_buffer_rowids ut_varchar2_rows; - l_buffer_data ut_output_data_rows; - l_finished_flags ut_integer_list; - l_last_read_message_id integer; - l_already_waited_sec number(10,2) := 0; - l_data_finished boolean := false; - l_finished boolean := false; - l_sleep_time number(2,1) := lc_100_milisec; - l_lock_status integer; - l_producer_started boolean := false; - l_producer_finished boolean := false; - function get_lock_status return integer is - l_result integer; - l_release_status integer; - begin - l_result := dbms_lock.request( self.lock_handle, dbms_lock.s_mode, 0, false ); - if l_result = 0 then - l_release_status := dbms_lock.release( self.lock_handle ); - end if; - return l_result; - end; + member function timeout_producer_not_started( a_producer_started boolean, a_already_waited_sec number, a_init_wait_sec number ) return boolean + is + l_result boolean := false; begin - while not l_finished loop - - --check if the lock is still there on output - if yes, the main session is still running and so don't stop - l_lock_status := get_lock_status(); - get_data_from_buffer_table( l_last_read_message_id, l_buffer_data, l_buffer_rowids, l_finished_flags ); - - --nothing fetched from output, wait and try again - if l_buffer_data.count = 0 then - - dbms_lock.sleep(l_sleep_time); - l_already_waited_sec := l_already_waited_sec + l_sleep_time; - - -- if waited more than lc_1_second seconds then increase wait period to minimize the CPU usage. - if l_already_waited_sec >= lc_1_second then - l_sleep_time := lc_500_milisec; - end if; - + if not a_producer_started and a_already_waited_sec >= a_init_wait_sec then + if a_init_wait_sec > 0 then + self.remove_buffer_info(); + raise_application_error( + ut_utils.gc_out_buffer_timeout, + 'Timeout occurred while waiting for report data producer to start. Waited for: '||ut_utils.to_string( a_already_waited_sec )||' seconds.' + ); else - - l_already_waited_sec := 0; - l_sleep_time := lc_100_milisec; - - for i in 1 .. l_buffer_data.count loop - if l_buffer_data(i).text is not null then - pipe row( l_buffer_data(i) ); - elsif l_finished_flags(i) = 1 then - l_data_finished := true; - exit; - end if; - end loop; - - remove_read_data(l_buffer_rowids); - + l_result := true; end if; - l_producer_started := (l_lock_status <> 0 or l_buffer_data.count > 0) or l_producer_started; - l_producer_finished := (l_producer_started and l_lock_status = 0 and l_buffer_data.count = 0) or l_producer_finished; - - if not l_producer_started and l_already_waited_sec >= lc_init_wait_sec then - - if lc_init_wait_sec > 0 then - self.remove_buffer_info(); - raise_application_error( - ut_utils.gc_out_buffer_timeout, - 'Timeout occurred while waiting for report data producer to start. Waited for: '||ut_utils.to_string( l_already_waited_sec )||' seconds.' - ); - else - l_finished := true; - end if; - - elsif not l_producer_finished and a_timeout_sec is not null and l_already_waited_sec >= a_timeout_sec then - - if a_timeout_sec > 0 then - self.remove_buffer_info(); - raise_application_error( - ut_utils.gc_out_buffer_timeout, - 'Timeout occurred while waiting for more data from producer. Waited for: '||ut_utils.to_string( l_already_waited_sec )||' seconds.' - ); - else - l_finished := true; - end if; + end if; + return l_result; + end; - elsif (l_data_finished or l_producer_finished) then - l_finished := true; + member function timeout_producer_not_finished(a_producer_finished boolean, a_already_waited_sec number, a_timeout_sec number) return boolean + is + l_result boolean := false; + begin + if not a_producer_finished and a_timeout_sec is not null and a_already_waited_sec >= a_timeout_sec then + if a_timeout_sec > 0 then + self.remove_buffer_info(); + raise_application_error( + ut_utils.gc_out_buffer_timeout, + 'Timeout occurred while waiting for more data from producer. Waited for: '||ut_utils.to_string( a_already_waited_sec )||' seconds.' + ); + else + l_result := true; end if; - end loop; - self.remove_buffer_info(); - return; + end if; + return l_result; + end; + + member function get_lock_status return integer is + l_result integer; + l_release_status integer; + begin + l_result := dbms_lock.request( self.lock_handle, dbms_lock.s_mode, 0, false ); + if l_result = 0 then + l_release_status := dbms_lock.release( self.lock_handle ); + end if; + return l_result; end; member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor is diff --git a/source/core/output_buffers/ut_output_buffer_base.tps b/source/core/output_buffers/ut_output_buffer_base.tps index 8000ea2e7..53be365ae 100644 --- a/source/core/output_buffers/ut_output_buffer_base.tps +++ b/source/core/output_buffers/ut_output_buffer_base.tps @@ -24,22 +24,17 @@ create or replace type ut_output_buffer_base force authid definer as object( self_type varchar2(250 byte), member procedure init(self in out nocopy ut_output_buffer_base, a_output_id raw := null, a_self_type varchar2 := null), member procedure lock_buffer(a_timeout_sec number := null), + member function timeout_producer_not_started( a_producer_started boolean, a_already_waited_sec number, a_init_wait_sec number ) return boolean, + member function timeout_producer_not_finished(a_producer_finished boolean, a_already_waited_sec number, a_timeout_sec number) return boolean, + member function get_lock_status return integer, member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor, member procedure lines_to_dbms_output(self in ut_output_buffer_base, a_initial_timeout number := null, a_timeout_sec number := null), member procedure cleanup_buffer(self in ut_output_buffer_base, a_retention_time_sec natural := null), member procedure remove_buffer_info(self in ut_output_buffer_base), - not instantiable member procedure get_data_from_buffer_table( - self in ut_output_buffer_base, - a_last_read_message_id in out nocopy integer, - a_buffer_data out nocopy ut_output_data_rows, - a_buffer_rowids out nocopy ut_varchar2_rows, - a_finished_flags out nocopy ut_integer_list - ), member procedure close(self in out nocopy ut_output_buffer_base), - not instantiable member procedure remove_read_data(self in ut_output_buffer_base, a_buffer_rowids ut_varchar2_rows), not instantiable member procedure send_line(self in out nocopy ut_output_buffer_base, a_text varchar2, a_item_type varchar2 := null), not instantiable member procedure send_lines(self in out nocopy ut_output_buffer_base, a_text_list ut_varchar2_rows, a_item_type varchar2 := null), not instantiable member procedure send_clob(self in out nocopy ut_output_buffer_base, a_text clob, a_item_type varchar2 := null), - member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined + not instantiable member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined ) not final not instantiable / diff --git a/source/core/output_buffers/ut_output_clob_table_buffer.tpb b/source/core/output_buffers/ut_output_clob_table_buffer.tpb index e47f0bcb0..c4cfdb059 100644 --- a/source/core/output_buffers/ut_output_clob_table_buffer.tpb +++ b/source/core/output_buffers/ut_output_clob_table_buffer.tpb @@ -55,36 +55,86 @@ create or replace type body ut_output_clob_table_buffer is commit; end; - overriding member procedure get_data_from_buffer_table( - self in ut_output_clob_table_buffer, - a_last_read_message_id in out nocopy integer, - a_buffer_data out nocopy ut_output_data_rows, - a_buffer_rowids out nocopy ut_varchar2_rows, - a_finished_flags out nocopy ut_integer_list - ) is - lc_bulk_limit constant integer := 5000; - begin - a_last_read_message_id := coalesce(a_last_read_message_id, 0); - with ordered_buffer as ( - select /*+ no_parallel index(a) */ ut_output_data_row(a.text, a.item_type), rowidtochar(a.rowid), is_finished - from ut_output_clob_buffer_tmp a - where a.output_id = self.output_id - and a.message_id <= a_last_read_message_id + lc_bulk_limit - order by a.message_id - ) - select /*+ no_parallel */ b.* - bulk collect into a_buffer_data, a_buffer_rowids, a_finished_flags - from ordered_buffer b; - a_last_read_message_id := a_last_read_message_id + a_finished_flags.count; - end; + overriding member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined is + lc_init_wait_sec constant number := coalesce(a_initial_timeout, 10 ); + l_buffer_rowids ut_varchar2_rows; + l_buffer_data ut_output_data_rows; + l_finished_flags ut_integer_list; + l_last_read_message_id integer; + l_already_waited_sec number(10,2) := 0; + l_finished boolean := false; + l_sleep_time number(2,1); + l_lock_status integer; + l_producer_started boolean := false; + l_producer_finished boolean := false; + procedure get_data_from_buffer_table( + a_last_read_message_id in out nocopy integer, + a_buffer_data out nocopy ut_output_data_rows, + a_buffer_rowids out nocopy ut_varchar2_rows, + a_finished_flags out nocopy ut_integer_list + ) is + lc_bulk_limit constant integer := 5000; + begin + a_last_read_message_id := coalesce(a_last_read_message_id, 0); + with ordered_buffer as ( + select /*+ no_parallel index(a) */ ut_output_data_row(a.text, a.item_type), rowidtochar(a.rowid), is_finished + from ut_output_clob_buffer_tmp a + where a.output_id = self.output_id + and a.message_id <= a_last_read_message_id + lc_bulk_limit + order by a.message_id + ) + select /*+ no_parallel */ b.* + bulk collect into a_buffer_data, a_buffer_rowids, a_finished_flags + from ordered_buffer b; + a_last_read_message_id := a_last_read_message_id + a_finished_flags.count; + end; + + procedure remove_read_data(a_buffer_rowids ut_varchar2_rows) is + pragma autonomous_transaction; + begin + forall i in 1 .. a_buffer_rowids.count + delete from ut_output_clob_buffer_tmp a + where rowid = chartorowid(a_buffer_rowids(i)); + commit; + end; - overriding member procedure remove_read_data(self in ut_output_clob_table_buffer, a_buffer_rowids ut_varchar2_rows) is - pragma autonomous_transaction; begin - forall i in 1 .. a_buffer_rowids.count - delete from ut_output_clob_buffer_tmp a - where rowid = chartorowid(a_buffer_rowids(i)); - commit; + while not l_finished loop + + l_sleep_time := case when l_already_waited_sec >= 1 then 0.5 else 0.1 end; + l_lock_status := self.get_lock_status(); + get_data_from_buffer_table( l_last_read_message_id, l_buffer_data, l_buffer_rowids, l_finished_flags ); + + if l_buffer_data.count > 0 then + l_already_waited_sec := 0; + for i in 1 .. l_buffer_data.count loop + if l_buffer_data(i).text is not null then + pipe row( l_buffer_data(i) ); + elsif l_finished_flags(i) = 1 then + l_finished := true; + exit; + end if; + end loop; + remove_read_data(l_buffer_rowids); + else + --nothing fetched from output, wait. + dbms_lock.sleep(l_sleep_time); + l_already_waited_sec := l_already_waited_sec + l_sleep_time; + end if; + + l_producer_started := (l_lock_status <> 0 or l_buffer_data.count > 0) or l_producer_started; + l_producer_finished := (l_producer_started and l_lock_status = 0 and l_buffer_data.count = 0) or l_producer_finished; + + l_finished := + self.timeout_producer_not_finished(l_producer_finished, l_already_waited_sec, a_timeout_sec) + or self.timeout_producer_not_started(l_producer_started, l_already_waited_sec, lc_init_wait_sec) + or l_producer_finished + or l_finished; + + end loop; + + self.remove_buffer_info(); + return; end; end; diff --git a/source/core/output_buffers/ut_output_clob_table_buffer.tps b/source/core/output_buffers/ut_output_clob_table_buffer.tps index ccd710a8f..191e64c01 100644 --- a/source/core/output_buffers/ut_output_clob_table_buffer.tps +++ b/source/core/output_buffers/ut_output_clob_table_buffer.tps @@ -20,13 +20,6 @@ create or replace type ut_output_clob_table_buffer under ut_output_buffer_base ( overriding member procedure send_line(self in out nocopy ut_output_clob_table_buffer, a_text varchar2, a_item_type varchar2 := null), overriding member procedure send_lines(self in out nocopy ut_output_clob_table_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null), overriding member procedure send_clob(self in out nocopy ut_output_clob_table_buffer, a_text clob, a_item_type varchar2 := null), - overriding member procedure get_data_from_buffer_table( - self in ut_output_clob_table_buffer, - a_last_read_message_id in out nocopy integer, - a_buffer_data out nocopy ut_output_data_rows, - a_buffer_rowids out nocopy ut_varchar2_rows, - a_finished_flags out nocopy ut_integer_list - ), - overriding member procedure remove_read_data(self in ut_output_clob_table_buffer, a_buffer_rowids ut_varchar2_rows) + overriding member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined ) not final / diff --git a/source/core/output_buffers/ut_output_table_buffer.tpb b/source/core/output_buffers/ut_output_table_buffer.tpb index 599b56846..f38363e49 100644 --- a/source/core/output_buffers/ut_output_table_buffer.tpb +++ b/source/core/output_buffers/ut_output_table_buffer.tpb @@ -87,12 +87,29 @@ create or replace type body ut_output_table_buffer is close l_data; end; - overriding member procedure get_data_from_buffer_table( - self in ut_output_table_buffer, + /* Important note. + This function code is almost duplicated between two types for performance reasons. + The pipe row clause is much faster on VARCHAR2 then it is on clob. + That is the key reason for two implementations. + */ + overriding member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined is + lc_init_wait_sec constant number := coalesce(a_initial_timeout, 10 ); + l_buffer_texts ut_varchar2_rows; + l_buffer_item_types ut_varchar2_rows; + l_finished_flags ut_integer_list; + l_last_read_message_id integer; + l_already_waited_sec number(10,2) := 0; + l_finished boolean := false; + l_sleep_time number(2,1); + l_lock_status integer; + l_producer_started boolean := false; + l_producer_finished boolean := false; + + procedure get_data_from_buffer_table( a_last_read_message_id in out nocopy integer, - a_buffer_data out nocopy ut_output_data_rows, - a_buffer_rowids out nocopy ut_varchar2_rows, - a_finished_flags out nocopy ut_integer_list + a_buffer_texts out nocopy ut_varchar2_rows, + a_buffer_item_types out nocopy ut_varchar2_rows, + a_finished_flags out nocopy ut_integer_list ) is lc_bulk_limit constant integer := 20000; pragma autonomous_transaction; @@ -105,15 +122,47 @@ create or replace type body ut_output_table_buffer is and o.message_id <= a_last_read_message_id + lc_bulk_limit order by o.message_id ) d - returning ut_output_data_row(d.text, d.item_type), d.is_finished - bulk collect into a_buffer_data, a_finished_flags; + returning d.text, d.item_type, d.is_finished + bulk collect into a_buffer_texts, a_buffer_item_types, a_finished_flags; a_last_read_message_id := a_last_read_message_id + a_finished_flags.count; commit; end; - - overriding member procedure remove_read_data(self in ut_output_table_buffer, a_buffer_rowids ut_varchar2_rows) is begin - null; + while not l_finished loop + + l_sleep_time := case when l_already_waited_sec >= 1 then 0.5 else 0.1 end; + l_lock_status := self.get_lock_status(); + get_data_from_buffer_table( l_last_read_message_id, l_buffer_texts, l_buffer_item_types, l_finished_flags ); + + if l_buffer_texts.count > 0 then + l_already_waited_sec := 0; + for i in 1 .. l_buffer_texts.count loop + if l_buffer_texts(i) is not null then + pipe row( ut_output_data_row(l_buffer_texts(i), l_buffer_item_types(i)) ); + elsif l_finished_flags(i) = 1 then + l_finished := true; + exit; + end if; + end loop; + else + --nothing fetched from output, wait. + dbms_lock.sleep(l_sleep_time); + l_already_waited_sec := l_already_waited_sec + l_sleep_time; + end if; + + l_producer_started := (l_lock_status <> 0 or l_buffer_texts.count > 0) or l_producer_started; + l_producer_finished := (l_producer_started and l_lock_status = 0 and l_buffer_texts.count = 0) or l_producer_finished; + + l_finished := + self.timeout_producer_not_finished(l_producer_finished, l_already_waited_sec, a_timeout_sec) + or self.timeout_producer_not_started(l_producer_started, l_already_waited_sec, lc_init_wait_sec) + or l_producer_finished + or l_finished; + + end loop; + + self.remove_buffer_info(); + return; end; end; diff --git a/source/core/output_buffers/ut_output_table_buffer.tps b/source/core/output_buffers/ut_output_table_buffer.tps index b7ef8a3e7..154ce4de6 100644 --- a/source/core/output_buffers/ut_output_table_buffer.tps +++ b/source/core/output_buffers/ut_output_table_buffer.tps @@ -21,13 +21,6 @@ create or replace type ut_output_table_buffer under ut_output_buffer_base ( overriding member procedure send_lines(self in out nocopy ut_output_table_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null), overriding member procedure send_clob(self in out nocopy ut_output_table_buffer, a_text clob, a_item_type varchar2 := null), overriding member procedure lines_to_dbms_output(self in ut_output_table_buffer, a_initial_timeout number := null, a_timeout_sec number := null), - overriding member procedure get_data_from_buffer_table( - self in ut_output_table_buffer, - a_last_read_message_id in out nocopy integer, - a_buffer_data out nocopy ut_output_data_rows, - a_buffer_rowids out nocopy ut_varchar2_rows, - a_finished_flags out nocopy ut_integer_list - ), - overriding member procedure remove_read_data(self in ut_output_table_buffer, a_buffer_rowids ut_varchar2_rows) + overriding member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined ) not final / From 865785aa49c0258f9b1c1ad8291d07867300daf6 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Fri, 10 Feb 2023 19:18:31 +0200 Subject: [PATCH 124/187] Fixed failing test. --- development/refresh_sources.sh | 2 +- test/ut3_tester/core/test_output_buffer.pkb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/development/refresh_sources.sh b/development/refresh_sources.sh index b6ef51ef9..83518d7cc 100755 --- a/development/refresh_sources.sh +++ b/development/refresh_sources.sh @@ -12,7 +12,7 @@ git clone --depth=1 --branch=${SELFTESTING_BRANCH:-main} https://github.com/utPL rm -rf utPLSQL-cli/* # download latest release version of utPLSQL-cli -curl -Lk -o utPLSQL-cli.zip https://github.com/utPLSQL/utPLSQL-cli/releases/download/v${UTPLSQL_CLI_VERSION}/utPLSQL-cli.zip +curl -Lk -o utPLSQL-cli.zip https://github.com/utPLSQL/utPLSQL-cli/releases/download/${UTPLSQL_CLI_VERSION}/utPLSQL-cli.zip # unzip utPLSQL-cli and remove the zip file unzip utPLSQL-cli.zip && chmod u+x utPLSQL-cli/bin/utplsql && rm utPLSQL-cli.zip diff --git a/test/ut3_tester/core/test_output_buffer.pkb b/test/ut3_tester/core/test_output_buffer.pkb index c5a4c07b1..edb10e3e6 100644 --- a/test/ut3_tester/core/test_output_buffer.pkb +++ b/test/ut3_tester/core/test_output_buffer.pkb @@ -38,7 +38,7 @@ create or replace package body test_output_buffer is l_buffer ut3_develop.ut_output_buffer_base; begin l_buffer := ut3_develop.ut_output_clob_table_buffer(); - ut.expect( l_buffer.get_lines_cursor(0.1,0) ).to_be_empty(); + ut.expect( l_buffer.get_lines_cursor(0.1) ).to_be_empty(); end; procedure test_doesnt_send_on_null_text is From 33f5485645d074f6993402a4f11c8f350534dd43 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 11 Feb 2023 10:57:45 +0000 Subject: [PATCH 125/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index cd50c02bf..9bd1a10c6 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 52b771abc..727b513eb 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index c869cfa4f..5f4b1d57c 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index ec7316027..cd2f76d49 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 4a9108f8a..b029f6206 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index dc7d2f0ad..7a2f511aa 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 87ede5b5f..0e3b6446e 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 905a27acb..d41641303 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 5e9331e6b..5e1c4cbdb 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 0da0f5178..8c986cb87 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 0655700af..c116464de 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index a6948f9d7..4427f2f10 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 278bad788..7af30194d 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 8cb47b973..68c689828 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 3d0bf7d84..75bd4df3d 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 0ab199c08..07b192ce1 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 1a554dfc9..bb66e6e0e 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4072--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 438abddd2..18a3d5952 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4072-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4085-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 28b6eaa53ec15e0fc11c8ff2531388d7e857c645 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sat, 11 Feb 2023 12:54:42 +0200 Subject: [PATCH 126/187] Small performance improvements to output buffer handling and some tests. --- source/api/ut.pkb | 12 +++++++++--- .../core/output_buffers/ut_output_table_buffer.tpb | 10 ++++++---- test/ut3_tester_helper/coverage_helper.pkb | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/source/api/ut.pkb b/source/api/ut.pkb index 5c91e54d4..5e612efb4 100644 --- a/source/api/ut.pkb +++ b/source/api/ut.pkb @@ -222,10 +222,15 @@ create or replace package body ut is raise_if_packages_invalidated(); raise no_data_found; end if; - g_result_lines := ut_utils.clob_to_table(l_clob, ut_utils.gc_max_storage_varchar2_len); - g_result_line_no := g_result_lines.first; + if l_clob is not null and l_clob != empty_clob() then + if length(l_clob) > ut_utils.gc_max_storage_varchar2_len then + g_result_lines := ut_utils.clob_to_table(l_clob, ut_utils.gc_max_storage_varchar2_len); + else + g_result_lines := ut_varchar2_list(l_clob); + end if; + g_result_line_no := g_result_lines.first; + end if; end if; - if g_result_line_no is not null then l_result := g_result_lines(g_result_line_no); g_result_line_no := g_result_lines.next(g_result_line_no); @@ -274,6 +279,7 @@ create or replace package body ut is if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); loop + g_result_lines := ut_varchar2_list(); pipe row( get_report_outputs( l_results ) ); end loop; end if; diff --git a/source/core/output_buffers/ut_output_table_buffer.tpb b/source/core/output_buffers/ut_output_table_buffer.tpb index f38363e49..480ae9144 100644 --- a/source/core/output_buffers/ut_output_table_buffer.tpb +++ b/source/core/output_buffers/ut_output_table_buffer.tpb @@ -75,14 +75,16 @@ create or replace type body ut_output_table_buffer is overriding member procedure lines_to_dbms_output(self in ut_output_table_buffer, a_initial_timeout number := null, a_timeout_sec number := null) is l_data sys_refcursor; - l_text varchar2(32767); - l_item_type varchar2(32767); + l_text ut_varchar2_rows; + l_item_type ut_varchar2_rows; begin l_data := self.get_lines_cursor(a_initial_timeout, a_timeout_sec); loop - fetch l_data into l_text, l_item_type; + fetch l_data bulk collect into l_text, l_item_type limit 10000; + for idx in 1 .. l_text.count loop + dbms_output.put_line(l_text(idx)); + end loop; exit when l_data%notfound; - dbms_output.put_line(l_text); end loop; close l_data; end; diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index 2a508ca6a..d234967e4 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -489,16 +489,30 @@ create or replace package body coverage_helper is l_coverage_id raw(32) := sys_guid(); begin l_plsql_block := q'[ + declare + x dbms_output.chararr; + i integer := 100000; begin + execute immediate 'alter session set statistics_level=all'; +/* + dbms_hprof.start_profiling( + location => 'PLSHPROF_DIR' + , filename => 'profiler_utPLSQL_run_]'||rawtohex(l_coverage_id)||q'[.txt' + ); +*/ ut3_develop.ut_runner.coverage_start(']'||rawtohex(l_coverage_id)||q'['); ut3_develop.ut_coverage.set_develop_mode(a_develop_mode => true); --gather coverage on the command executed begin {a_run_command}; end; + dbms_output.get_lines(x,i); ut3_develop.ut_coverage.set_develop_mode(a_develop_mode => false); ut3_develop.ut_runner.coverage_stop(); --get the actual results of the command gathering the coverage insert into test_results select rownum as id, x.* from table( {a_run_command} ) x; commit; +/* + dbms_hprof.stop_profiling; +*/ end;]'; l_plsql_block := replace(l_plsql_block,'{a_run_command}',a_run_command); l_result_clob := run_code_as_job( l_plsql_block ); From 3a837f4ccf5021fbbb8d2a269653226601ca535d Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 14 Mar 2023 23:10:15 -0700 Subject: [PATCH 127/187] Address issue where the not_to(contain) executes a negated matcher without negated flag set causing refcursor compare sql generated inclusion comparision. --- source/expectations/matchers/ut_contain.tpb | 1 + source/expectations/ut_expectation.tpb | 4 +- .../expectations/test_expectations_cursor.pkb | 100 +++++++++++++++++- .../expectations/test_expectations_cursor.pks | 22 +++- 4 files changed, 122 insertions(+), 5 deletions(-) diff --git a/source/expectations/matchers/ut_contain.tpb b/source/expectations/matchers/ut_contain.tpb index 7591925f5..c9691f731 100644 --- a/source/expectations/matchers/ut_contain.tpb +++ b/source/expectations/matchers/ut_contain.tpb @@ -47,6 +47,7 @@ create or replace type body ut_contain as overriding member function run_matcher_negated(self in out nocopy ut_contain, a_actual ut_data_value) return boolean is begin + self.negated(); return run_matcher(a_actual); end; diff --git a/source/expectations/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index a78c57eb7..309759d48 100644 --- a/source/expectations/ut_expectation.tpb +++ b/source/expectations/ut_expectation.tpb @@ -686,7 +686,7 @@ create or replace type body ut_expectation as member procedure not_to_contain(self in ut_expectation, a_expected sys_refcursor) is begin - self.not_to( ut_contain(a_expected).negated() ); + self.not_to( ut_contain(a_expected)); end; member procedure to_contain(self in ut_expectation, a_expected anydata) is @@ -696,7 +696,7 @@ create or replace type body ut_expectation as member procedure not_to_contain(self in ut_expectation, a_expected anydata) is begin - self.not_to( ut_contain(a_expected).negated() ); + self.not_to( ut_contain(a_expected)); end; member function to_be_within(a_dist number) return ut_be_within is diff --git a/test/ut3_user/expectations/test_expectations_cursor.pkb b/test/ut3_user/expectations/test_expectations_cursor.pkb index 952084fd3..7d0f308a8 100644 --- a/test/ut3_user/expectations/test_expectations_cursor.pkb +++ b/test/ut3_user/expectations/test_expectations_cursor.pkb @@ -2329,6 +2329,23 @@ Diff:% ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; + procedure cursor_not_to_contain2 + as + l_actual sys_refcursor; + l_expected sys_refcursor; + begin + open l_expected for select 'TEST' username, -600 user_id from dual; + + open l_actual for select username, user_id from all_users + union all + select 'TEST1' username, -601 user_id from dual; + + --Act + ut3_develop.ut.expect(l_actual).not_to(ut3_develop.contain(l_expected)); + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + procedure cursor_not_to_contain_fail is l_actual sys_refcursor; l_expected sys_refcursor; @@ -2359,6 +2376,37 @@ Diff:% ut.expect(l_actual_message).to_be_like(l_expected_message); end; + + procedure cursor_not_to_contain_fail2 is + l_actual sys_refcursor; + l_expected sys_refcursor; + l_expected_message varchar2(32767); + l_actual_message varchar2(32767); + begin + --Arrange + open l_expected for select 'TEST' username, -600 user_id from dual; + + open l_actual for select username, user_id from all_users + union all + select 'TEST' username, -600 user_id from dual; + + --Act + ut3_develop.ut.expect(l_actual).not_to(ut3_develop.contain(l_expected)); + --Assert + l_expected_message := q'[%Actual: (refcursor [ count = % ])% +%Data-types:% +%VARCHAR2NUMBER% +%Data:% +%was expected not to contain:(refcursor [ count = 1 ])% +%Data-types:% +%CHARNUMBER% +%Data:% +%TEST-600%]'; + l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1); + --Assert + ut.expect(l_actual_message).to_be_like(l_expected_message); + end; + procedure cursor_not_to_contain_joinby is l_actual sys_refcursor; l_expected sys_refcursor; @@ -2372,7 +2420,21 @@ Diff:% --Assert ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; - + + procedure cursor_not_to_contain_joinby2 is + l_actual sys_refcursor; + l_expected sys_refcursor; + begin + --Arrange + open l_actual for select username,rownum * 10 user_id from all_users where rownum < 5; + open l_expected for select username||to_char(rownum) username ,rownum user_id from all_users where rownum < 5; + + --Act + ut3_develop.ut.expect(l_actual).not_to(ut3_develop.contain(l_expected).join_by('USER_ID')); + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + procedure not_cont_join_incl_cols_as_lst is l_actual sys_refcursor; l_expected sys_refcursor; @@ -2386,6 +2448,19 @@ Diff:% ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; + procedure not_cont_join_incl_cols_as_lst2 is + l_actual sys_refcursor; + l_expected sys_refcursor; + begin + --Arrange + open l_actual for select rownum as rn, 'b' as "A_Column", 'c' as A_COLUMN, 'x' SOME_COL, 'd' "Some_Col" from dual a connect by level < 10; + open l_expected for select rownum * 20 rn, 'a' as "A_Column", 'd' as A_COLUMN, 'x' SOME_COL, 'c' "Some_Col" from dual a connect by level < 4; + --Act + ut3_develop.ut.expect(l_actual).not_to(ut3_develop.contain(l_expected).include(ut3_develop.ut_varchar2_list('RN','//A_Column','SOME_COL')).join_by('RN')); + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + procedure not_cont_join_excl_cols_as_lst is l_actual sys_refcursor; l_expected sys_refcursor; @@ -2399,6 +2474,19 @@ Diff:% ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; + procedure not_cont_join_excl_cols_as_lst2 is + l_actual sys_refcursor; + l_expected sys_refcursor; + begin + --Arrange + open l_actual for select rownum as rn, 'a' as "A_Column", 'c' as A_COLUMN, 'y' SOME_COL, 'd' "Some_Col" from dual a connect by level < 10; + open l_expected for select rownum * 20 as rn, 'a' as "A_Column", 'd' as A_COLUMN, 'x' SOME_COL, 'c' "Some_Col" from dual a connect by level < 4; + --Act + ut3_develop.ut.expect(l_actual).not_to(ut3_develop.contain(l_expected).exclude(ut3_develop.ut_varchar2_list('//Some_Col','A_COLUMN')).join_by('RN')); + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + procedure to_contain_duplicates is l_actual sys_refcursor; l_expected sys_refcursor; @@ -2440,6 +2528,16 @@ Diff:% ut.expect(l_actual_message).to_be_like(l_expected_message); end; + procedure to_not_contain_fails_1245 is + c1 sys_refcursor; + c2 sys_refcursor; + begin + open c1 for select 'a' as letter from dual union all select 'b' from dual; + open c2 for select 'c' as letter from dual; + ut3_develop.ut.expect(c1).not_to(ut3_develop.contain(c2)); + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + procedure udt_messg_format_eq is l_actual sys_refcursor; l_expected sys_refcursor; diff --git a/test/ut3_user/expectations/test_expectations_cursor.pks b/test/ut3_user/expectations/test_expectations_cursor.pks index 0ed249a49..e7a289247 100644 --- a/test/ut3_user/expectations/test_expectations_cursor.pks +++ b/test/ut3_user/expectations/test_expectations_cursor.pks @@ -376,24 +376,42 @@ create or replace package test_expectations_cursor is --%test( Cursor not to contains data from another cursor) procedure cursor_not_to_contain; + --%test( Cursor not_to[contain] data from another cursor) + procedure cursor_not_to_contain2; + --%test( Cursor fail not to contains data from another cursor) procedure cursor_not_to_contain_fail; - + + --%test( Cursor fail not_to[contain] data from another cursor) + procedure cursor_not_to_contain_fail2; + --%test( Cursor not contains data from another cursor with joinby clause) procedure cursor_not_to_contain_joinby; + --%test( Cursor not_to[contain] data from another cursor with joinby clause) + procedure cursor_not_to_contain_joinby2; + --%test(Cursor not contains data with of columns to include and join by value) procedure not_cont_join_incl_cols_as_lst; + --%test(Cursor not_to[contain] data with of columns to include and join by value) + procedure not_cont_join_incl_cols_as_lst2; + --%test(Cursor not contains data with of columns to exclude and join by value) procedure not_cont_join_excl_cols_as_lst; + --%test(Cursor not_to[contain] data with of columns to exclude and join by value) + procedure not_cont_join_excl_cols_as_lst2; + --%test(Cursor to contain duplicates) procedure to_contain_duplicates; --%test(Cursor to contain duplicates fail) procedure to_contain_duplicates_fail; - + + --%test(Cursor using not_to[contain] fails #1245) + procedure to_not_contain_fails_1245; + --%test(Display a message with a uer defined type with only type name not structure on equal) procedure udt_messg_format_eq; From 0707b2d8a8cb44b77abe327c46b596c7899bbb9a Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 14 Mar 2023 23:19:56 -0700 Subject: [PATCH 128/187] Fixing when test name is longer than 30 char --- test/ut3_user/expectations/test_expectations_cursor.pkb | 4 ++-- test/ut3_user/expectations/test_expectations_cursor.pks | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/ut3_user/expectations/test_expectations_cursor.pkb b/test/ut3_user/expectations/test_expectations_cursor.pkb index 7d0f308a8..847cce9a0 100644 --- a/test/ut3_user/expectations/test_expectations_cursor.pkb +++ b/test/ut3_user/expectations/test_expectations_cursor.pkb @@ -2448,7 +2448,7 @@ Diff:% ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; - procedure not_cont_join_incl_cols_as_lst2 is + procedure not_con_join_incl_cols_as_lst2 is l_actual sys_refcursor; l_expected sys_refcursor; begin @@ -2474,7 +2474,7 @@ Diff:% ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; - procedure not_cont_join_excl_cols_as_lst2 is + procedure not_con_join_excl_cols_as_lst2 is l_actual sys_refcursor; l_expected sys_refcursor; begin diff --git a/test/ut3_user/expectations/test_expectations_cursor.pks b/test/ut3_user/expectations/test_expectations_cursor.pks index e7a289247..0f34486a9 100644 --- a/test/ut3_user/expectations/test_expectations_cursor.pks +++ b/test/ut3_user/expectations/test_expectations_cursor.pks @@ -395,13 +395,13 @@ create or replace package test_expectations_cursor is procedure not_cont_join_incl_cols_as_lst; --%test(Cursor not_to[contain] data with of columns to include and join by value) - procedure not_cont_join_incl_cols_as_lst2; + procedure not_con_join_incl_cols_as_lst2; --%test(Cursor not contains data with of columns to exclude and join by value) procedure not_cont_join_excl_cols_as_lst; --%test(Cursor not_to[contain] data with of columns to exclude and join by value) - procedure not_cont_join_excl_cols_as_lst2; + procedure not_con_join_excl_cols_as_lst2; --%test(Cursor to contain duplicates) procedure to_contain_duplicates; From 8460a3092ac4f6781bf8f07f5a0d26d31ab6fa71 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 15 Mar 2023 00:24:05 -0700 Subject: [PATCH 129/187] Update test --- .../expectations/test_expectation_anydata.pkb | 19 ++++++++++++++++++- .../expectations/test_expectation_anydata.pks | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/test/ut3_user/expectations/test_expectation_anydata.pkb b/test/ut3_user/expectations/test_expectation_anydata.pkb index c56c31930..c70d41f9e 100644 --- a/test/ut3_user/expectations/test_expectation_anydata.pkb +++ b/test/ut3_user/expectations/test_expectation_anydata.pkb @@ -957,6 +957,23 @@ Rows: [ 60 differences, showing first 20 ] ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; + procedure collection_not_to_contain is + l_actual ut3_tester_helper.test_dummy_object_list; + l_expected ut3_tester_helper.test_dummy_object_list; + begin + --Arrange + select ut3_tester_helper.test_dummy_object( rownum, 'Something2 '||rownum, rownum+100) + bulk collect into l_actual + from dual connect by level <=4; + select ut3_tester_helper.test_dummy_object( rownum, 'Something '||rownum, rownum) + bulk collect into l_expected + from dual connect by level <=2 + order by rownum desc; + --Act + ut3_develop.ut.expect(anydata.convertCollection(l_actual)).not_to_contain(anydata.convertCollection(l_expected)); + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + procedure object_to_contain is begin --Arrange @@ -967,7 +984,7 @@ Rows: [ 60 differences, showing first 20 ] ut3_develop.ut.expect(g_test_actual).to_contain(g_test_expected); ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; - + procedure arr_empty_eq_arr_empty_unord is begin --Arrange diff --git a/test/ut3_user/expectations/test_expectation_anydata.pks b/test/ut3_user/expectations/test_expectation_anydata.pks index 81dea74eb..54c246bd3 100644 --- a/test/ut3_user/expectations/test_expectation_anydata.pks +++ b/test/ut3_user/expectations/test_expectation_anydata.pks @@ -195,6 +195,9 @@ create or replace package test_expectation_anydata is --%test( Success when anydata collection contains data from another anydata collection) procedure collection_to_contain; + --%test( Success when anydata collection not contains data from another anydata collection) + procedure collection_not_to_contain; + --%test( Success when anydata object contains data from another anydata) procedure object_to_contain; From 7597905bfe41bc1b3580919e670d00e76bd62f3d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 19 Mar 2023 17:05:14 +0000 Subject: [PATCH 130/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 9bd1a10c6..d132d2085 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 727b513eb..21b82ee41 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 5f4b1d57c..9b423d5a8 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index cd2f76d49..d534857fa 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index b029f6206..d6884ba2d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 7a2f511aa..2c31a9a89 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 0e3b6446e..d193e2c20 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index d41641303..63c0e36e9 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 5e1c4cbdb..f77717798 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 8c986cb87..e237bf4ef 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index c116464de..8fa525a69 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 4427f2f10..d97d49464 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 7af30194d..934d07d72 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 68c689828..9e16fd3e8 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 75bd4df3d..b3b0e338a 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 07b192ce1..e8e431980 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index bb66e6e0e..47772937e 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4085--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 18a3d5952..f92fbc2b0 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4085-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4094-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 521fe472bb634095a3a3081f5175933eec61d2aa Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 20 Mar 2023 00:20:15 +0200 Subject: [PATCH 131/187] Performance improvements in output buffer for reporters that only produce data after the whole run is finished. --- source/api/ut.pkb | 7 +- .../output_buffers/ut_output_bulk_buffer.tpb | 160 ++++++++++++++++++ .../output_buffers/ut_output_bulk_buffer.tps | 27 +++ source/core/ut_utils.pkb | 1 + source/install.sql | 2 + .../ut_coverage_cobertura_reporter.tpb | 2 +- .../reporters/ut_coverage_html_reporter.tpb | 2 +- .../reporters/ut_coverage_sonar_reporter.tpb | 9 +- source/reporters/ut_coveralls_reporter.tpb | 2 +- source/reporters/ut_junit_reporter.tpb | 2 +- source/reporters/ut_sonar_test_reporter.tpb | 2 +- source/reporters/ut_tfs_junit_reporter.tpb | 2 +- source/reporters/ut_xunit_reporter.tpb | 2 +- source/uninstall_objects.sql | 2 + test/ut3_tester_helper/coverage_helper.pkb | 2 +- 15 files changed, 214 insertions(+), 10 deletions(-) create mode 100644 source/core/output_buffers/ut_output_bulk_buffer.tpb create mode 100644 source/core/output_buffers/ut_output_bulk_buffer.tps diff --git a/source/api/ut.pkb b/source/api/ut.pkb index 5e612efb4..cff35b771 100644 --- a/source/api/ut.pkb +++ b/source/api/ut.pkb @@ -278,8 +278,8 @@ create or replace package body ut is ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); + g_result_lines := ut_varchar2_list(); loop - g_result_lines := ut_varchar2_list(); pipe row( get_report_outputs( l_results ) ); end loop; end if; @@ -326,6 +326,7 @@ create or replace package body ut is ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); + g_result_lines := ut_varchar2_list(); loop pipe row( get_report_outputs( l_results ) ); end loop; @@ -374,6 +375,7 @@ create or replace package body ut is ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); + g_result_lines := ut_varchar2_list(); loop pipe row( get_report_outputs( l_results ) ); end loop; @@ -422,6 +424,7 @@ create or replace package body ut is ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); + g_result_lines := ut_varchar2_list(); loop pipe row( get_report_outputs( l_results ) ); end loop; @@ -470,6 +473,7 @@ create or replace package body ut is ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); + g_result_lines := ut_varchar2_list(); loop pipe row( get_report_outputs( l_results ) ); end loop; @@ -518,6 +522,7 @@ create or replace package body ut is ); if l_reporter is of (ut_output_reporter_base) then l_results := treat(l_reporter as ut_output_reporter_base).get_lines_cursor(); + g_result_lines := ut_varchar2_list(); loop pipe row( get_report_outputs( l_results ) ); end loop; diff --git a/source/core/output_buffers/ut_output_bulk_buffer.tpb b/source/core/output_buffers/ut_output_bulk_buffer.tpb new file mode 100644 index 000000000..49aa1e913 --- /dev/null +++ b/source/core/output_buffers/ut_output_bulk_buffer.tpb @@ -0,0 +1,160 @@ +create or replace type body ut_output_bulk_buffer is + /* + utPLSQL - Version 3 + Copyright 2016 - 2023 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + constructor function ut_output_bulk_buffer(self in out nocopy ut_output_bulk_buffer, a_output_id raw := null) return self as result is + begin + self.init(a_output_id, $$plsql_unit); + return; + end; + + overriding member procedure send_line(self in out nocopy ut_output_bulk_buffer, a_text varchar2, a_item_type varchar2 := null) is + pragma autonomous_transaction; + begin + if a_text is not null or a_item_type is not null then + if length(a_text) > ut_utils.gc_max_storage_varchar2_len then + self.send_lines( + ut_utils.convert_collection( + ut_utils.clob_to_table(a_text, ut_utils.gc_max_storage_varchar2_len) + ), + a_item_type + ); + else + self.last_write_message_id := self.last_write_message_id + 1; + insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) + values (self.output_id, self.last_write_message_id, a_text, a_item_type); + end if; + commit; + end if; + end; + + overriding member procedure send_lines(self in out nocopy ut_output_bulk_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null) is + pragma autonomous_transaction; + begin + insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) + select /*+ no_parallel */ self.output_id, self.last_write_message_id + rownum, t.column_value, a_item_type + from table(a_text_list) t + where t.column_value is not null or a_item_type is not null; + self.last_write_message_id := self.last_write_message_id + SQL%rowcount; + commit; + end; + + overriding member procedure send_clob(self in out nocopy ut_output_bulk_buffer, a_text clob, a_item_type varchar2 := null) is + pragma autonomous_transaction; + begin + if a_text is not null and a_text != empty_clob() or a_item_type is not null then + if length(a_text) > ut_utils.gc_max_storage_varchar2_len then + self.send_lines( + ut_utils.convert_collection( + ut_utils.clob_to_table(a_text, ut_utils.gc_max_storage_varchar2_len) + ), + a_item_type + ); + else + self.last_write_message_id := self.last_write_message_id + 1; + insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) + values (self.output_id, self.last_write_message_id, a_text, a_item_type); + end if; + commit; + end if; + end; + + overriding member procedure lines_to_dbms_output(self in ut_output_bulk_buffer, a_initial_timeout number := null, a_timeout_sec number := null) is + l_data sys_refcursor; + l_text ut_varchar2_rows; + l_item_type ut_varchar2_rows; + begin + l_data := self.get_lines_cursor(a_initial_timeout, a_timeout_sec); + loop + fetch l_data bulk collect into l_text, l_item_type limit 10000; + for idx in 1 .. l_text.count loop + dbms_output.put_line(l_text(idx)); + end loop; + exit when l_data%notfound; + end loop; + close l_data; + end; + + overriding member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor is + lc_init_wait_sec constant number := coalesce(a_initial_timeout, 30 ); + l_already_waited_sec number(10,2) := 0; + l_sleep_time number(2,1); + l_exists integer; + l_finished boolean := false; + l_data_produced boolean; + l_producer_active boolean := false; + l_producer_started boolean := false; + l_producer_finished boolean := false; + l_results sys_refcursor; + begin + + while not l_finished loop + + if not l_data_produced then + select /*+ no_parallel */ count(1) into l_exists + from ut_output_buffer_tmp o + where o.output_id = self.output_id and rownum = 1; + l_data_produced := (l_exists = 1); + end if; + + l_sleep_time := case when l_already_waited_sec >= 1 then 0.5 else 0.1 end; + l_producer_active := (self.get_lock_status() <> 0); + l_producer_started := (l_producer_active or l_data_produced ) or l_producer_started; + l_producer_finished := (l_producer_started and not l_producer_active) or l_producer_finished; + + l_finished := + self.timeout_producer_not_finished(l_producer_finished, l_already_waited_sec, a_timeout_sec) + or self.timeout_producer_not_started(l_producer_started, l_already_waited_sec, lc_init_wait_sec) + or l_producer_finished; + end loop; + + open l_results for + select /*+ no_parallel */ o.text, o.item_type + from ut_output_buffer_tmp o + where o.output_id = self.output_id + and o.text is not null + order by o.output_id, o.message_id; + + return l_results; + + end; + + /* Important note. + This function code is almost duplicated between two types for performance reasons. + The pipe row clause is much faster on VARCHAR2 then it is on clob. + That is the key reason for two implementations. + */ + overriding member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined is + l_data sys_refcursor; + l_text ut_varchar2_rows; + l_item_type ut_varchar2_rows; + begin + l_data := self.get_lines_cursor(a_initial_timeout, a_timeout_sec); + loop + fetch l_data bulk collect into l_text, l_item_type limit 10000; + for idx in 1 .. l_text.count loop + pipe row( ut_output_data_row(l_text(idx), l_item_type(idx)) ); + end loop; + exit when l_data%notfound; + end loop; + close l_data; + return; + self.remove_buffer_info(); + end; + +end; +/ diff --git a/source/core/output_buffers/ut_output_bulk_buffer.tps b/source/core/output_buffers/ut_output_bulk_buffer.tps new file mode 100644 index 000000000..d74d4ee14 --- /dev/null +++ b/source/core/output_buffers/ut_output_bulk_buffer.tps @@ -0,0 +1,27 @@ +create or replace type ut_output_bulk_buffer under ut_output_buffer_base ( + /* + utPLSQL - Version 3 + Copyright 2016 - 2023 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + constructor function ut_output_bulk_buffer(self in out nocopy ut_output_bulk_buffer, a_output_id raw := null) return self as result, + overriding member procedure send_line(self in out nocopy ut_output_bulk_buffer, a_text varchar2, a_item_type varchar2 := null), + overriding member procedure send_lines(self in out nocopy ut_output_bulk_buffer, a_text_list ut_varchar2_rows, a_item_type varchar2 := null), + overriding member procedure send_clob(self in out nocopy ut_output_bulk_buffer, a_text clob, a_item_type varchar2 := null), + overriding member procedure lines_to_dbms_output(self in ut_output_bulk_buffer, a_initial_timeout number := null, a_timeout_sec number := null), + overriding member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor, + overriding member function get_lines(a_initial_timeout number := null, a_timeout_sec number := null) return ut_output_data_rows pipelined +) not final +/ diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 162e50f8f..5114cecad 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -570,6 +570,7 @@ create or replace package body ut_utils is end loop; exit when l_lines_data%notfound; end loop; + close l_lines_data; execute immediate 'truncate table ut_dbms_output_cache'; commit; end; diff --git a/source/install.sql b/source/install.sql index 6f3c16801..0873d6a1e 100644 --- a/source/install.sql +++ b/source/install.sql @@ -120,6 +120,8 @@ create or replace context &&ut3_owner._info using &&ut3_owner..ut_session_contex @@install_component.sql 'core/output_buffers/ut_output_table_buffer.tpb' @@install_component.sql 'core/output_buffers/ut_output_clob_table_buffer.tps' @@install_component.sql 'core/output_buffers/ut_output_clob_table_buffer.tpb' +@@install_component.sql 'core/output_buffers/ut_output_bulk_buffer.tps' +@@install_component.sql 'core/output_buffers/ut_output_bulk_buffer.tpb' @@install_component.sql 'core/types/ut_output_reporter_base.tps' diff --git a/source/reporters/ut_coverage_cobertura_reporter.tpb b/source/reporters/ut_coverage_cobertura_reporter.tpb index 48082a6d4..50eb34631 100644 --- a/source/reporters/ut_coverage_cobertura_reporter.tpb +++ b/source/reporters/ut_coverage_cobertura_reporter.tpb @@ -20,7 +20,7 @@ create or replace type body ut_coverage_cobertura_reporter is self in out nocopy ut_coverage_cobertura_reporter ) return self as result is begin - self.init($$plsql_unit); + self.init($$plsql_unit,ut_output_bulk_buffer()); return; end; diff --git a/source/reporters/ut_coverage_html_reporter.tpb b/source/reporters/ut_coverage_html_reporter.tpb index c88c91a80..b1f9f6651 100644 --- a/source/reporters/ut_coverage_html_reporter.tpb +++ b/source/reporters/ut_coverage_html_reporter.tpb @@ -22,7 +22,7 @@ create or replace type body ut_coverage_html_reporter is a_html_report_assets_path varchar2 := null ) return self as result is begin - self.init($$plsql_unit); + self.init($$plsql_unit,ut_output_bulk_buffer()); self.project_name := a_project_name; assets_path := nvl(a_html_report_assets_path, ut_coverage_report_html_helper.get_default_html_assets_path()); return; diff --git a/source/reporters/ut_coverage_sonar_reporter.tpb b/source/reporters/ut_coverage_sonar_reporter.tpb index 8ee78dc24..1861a9be3 100644 --- a/source/reporters/ut_coverage_sonar_reporter.tpb +++ b/source/reporters/ut_coverage_sonar_reporter.tpb @@ -20,7 +20,7 @@ create or replace type body ut_coverage_sonar_reporter is self in out nocopy ut_coverage_sonar_reporter ) return self as result is begin - self.init($$plsql_unit); + self.init($$plsql_unit,ut_output_bulk_buffer()); return; end; @@ -84,6 +84,12 @@ create or replace type body ut_coverage_sonar_reporter is end; begin +-- execute immediate 'alter session set statistics_level=all'; +-- dbms_hprof.start_profiling( +-- location => 'PLSHPROF_DIR' +-- , filename => 'profiler_utPLSQL_run_on_'||$$plsql_unit||'_'||rawtohex(self.id)||'.txt' +-- ); +-- ut_coverage.coverage_stop(); self.print_text_lines( @@ -92,6 +98,7 @@ create or replace type body ut_coverage_sonar_reporter is a_run ) ); +-- dbms_hprof.stop_profiling; end; overriding member function get_description return varchar2 as diff --git a/source/reporters/ut_coveralls_reporter.tpb b/source/reporters/ut_coveralls_reporter.tpb index 3a54aa7f7..14672303e 100644 --- a/source/reporters/ut_coveralls_reporter.tpb +++ b/source/reporters/ut_coveralls_reporter.tpb @@ -20,7 +20,7 @@ create or replace type body ut_coveralls_reporter is self in out nocopy ut_coveralls_reporter ) return self as result is begin - self.init($$plsql_unit); + self.init($$plsql_unit,ut_output_bulk_buffer()); return; end; diff --git a/source/reporters/ut_junit_reporter.tpb b/source/reporters/ut_junit_reporter.tpb index 44affa030..3bceb52a4 100644 --- a/source/reporters/ut_junit_reporter.tpb +++ b/source/reporters/ut_junit_reporter.tpb @@ -18,7 +18,7 @@ create or replace type body ut_junit_reporter is constructor function ut_junit_reporter(self in out nocopy ut_junit_reporter) return self as result is begin - self.init($$plsql_unit); + self.init($$plsql_unit,ut_output_bulk_buffer()); return; end; diff --git a/source/reporters/ut_sonar_test_reporter.tpb b/source/reporters/ut_sonar_test_reporter.tpb index a3ec72241..7c46879d2 100644 --- a/source/reporters/ut_sonar_test_reporter.tpb +++ b/source/reporters/ut_sonar_test_reporter.tpb @@ -20,7 +20,7 @@ create or replace type body ut_sonar_test_reporter is self in out nocopy ut_sonar_test_reporter ) return self as result is begin - self.init($$plsql_unit); + self.init($$plsql_unit,ut_output_bulk_buffer()); return; end; diff --git a/source/reporters/ut_tfs_junit_reporter.tpb b/source/reporters/ut_tfs_junit_reporter.tpb index 710c3bc7f..e2d45a369 100644 --- a/source/reporters/ut_tfs_junit_reporter.tpb +++ b/source/reporters/ut_tfs_junit_reporter.tpb @@ -18,7 +18,7 @@ create or replace type body ut_tfs_junit_reporter is constructor function ut_tfs_junit_reporter(self in out nocopy ut_tfs_junit_reporter) return self as result is begin - self.init($$plsql_unit); + self.init($$plsql_unit,ut_output_bulk_buffer()); return; end; diff --git a/source/reporters/ut_xunit_reporter.tpb b/source/reporters/ut_xunit_reporter.tpb index eab0c8a3c..4612fb640 100644 --- a/source/reporters/ut_xunit_reporter.tpb +++ b/source/reporters/ut_xunit_reporter.tpb @@ -18,7 +18,7 @@ create or replace type body ut_xunit_reporter is constructor function ut_xunit_reporter(self in out nocopy ut_xunit_reporter) return self as result is begin - self.init($$plsql_unit); + self.init($$plsql_unit,ut_output_bulk_buffer()); return; end; diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index 571d187a2..9531736b9 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -323,6 +323,8 @@ drop type ut_output_table_buffer force; drop type ut_output_clob_table_buffer force; +drop type ut_output_bulk_buffer force; + drop type ut_output_buffer_base force; drop table ut_output_buffer_tmp purge; diff --git a/test/ut3_tester_helper/coverage_helper.pkb b/test/ut3_tester_helper/coverage_helper.pkb index d234967e4..ef14c586f 100644 --- a/test/ut3_tester_helper/coverage_helper.pkb +++ b/test/ut3_tester_helper/coverage_helper.pkb @@ -493,8 +493,8 @@ create or replace package body coverage_helper is x dbms_output.chararr; i integer := 100000; begin - execute immediate 'alter session set statistics_level=all'; /* + execute immediate 'alter session set statistics_level=all'; dbms_hprof.start_profiling( location => 'PLSHPROF_DIR' , filename => 'profiler_utPLSQL_run_]'||rawtohex(l_coverage_id)||q'[.txt' From 6c0b6e681954c389ca2763edcc6c56a7d142b586 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Mon, 20 Mar 2023 12:35:05 +0200 Subject: [PATCH 132/187] Fixes to new data-buffer implementation. --- .../core/output_buffers/ut_output_bulk_buffer.tpb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/source/core/output_buffers/ut_output_bulk_buffer.tpb b/source/core/output_buffers/ut_output_bulk_buffer.tpb index 49aa1e913..ceae07862 100644 --- a/source/core/output_buffers/ut_output_bulk_buffer.tpb +++ b/source/core/output_buffers/ut_output_bulk_buffer.tpb @@ -49,7 +49,7 @@ create or replace type body ut_output_bulk_buffer is select /*+ no_parallel */ self.output_id, self.last_write_message_id + rownum, t.column_value, a_item_type from table(a_text_list) t where t.column_value is not null or a_item_type is not null; - self.last_write_message_id := self.last_write_message_id + SQL%rowcount; + self.last_write_message_id := self.last_write_message_id + sql%rowcount; commit; end; @@ -87,15 +87,16 @@ create or replace type body ut_output_bulk_buffer is exit when l_data%notfound; end loop; close l_data; + self.remove_buffer_info(); end; overriding member function get_lines_cursor(a_initial_timeout number := null, a_timeout_sec number := null) return sys_refcursor is - lc_init_wait_sec constant number := coalesce(a_initial_timeout, 30 ); + lc_init_wait_sec constant number := coalesce(a_initial_timeout, 10 ); l_already_waited_sec number(10,2) := 0; l_sleep_time number(2,1); l_exists integer; l_finished boolean := false; - l_data_produced boolean; + l_data_produced boolean := false; l_producer_active boolean := false; l_producer_started boolean := false; l_producer_finished boolean := false; @@ -115,11 +116,13 @@ create or replace type body ut_output_bulk_buffer is l_producer_active := (self.get_lock_status() <> 0); l_producer_started := (l_producer_active or l_data_produced ) or l_producer_started; l_producer_finished := (l_producer_started and not l_producer_active) or l_producer_finished; - l_finished := self.timeout_producer_not_finished(l_producer_finished, l_already_waited_sec, a_timeout_sec) or self.timeout_producer_not_started(l_producer_started, l_already_waited_sec, lc_init_wait_sec) or l_producer_finished; + + dbms_lock.sleep(l_sleep_time); + l_already_waited_sec := l_already_waited_sec + l_sleep_time; end loop; open l_results for @@ -152,8 +155,8 @@ create or replace type body ut_output_bulk_buffer is exit when l_data%notfound; end loop; close l_data; - return; self.remove_buffer_info(); + return; end; end; From 0daab3389dbf3fd0a0ec28e800479cfff486d45c Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 27 Mar 2023 20:37:09 -0700 Subject: [PATCH 133/187] Checkpoint --- docs/userguide/annotations.md | 71 ++++++++++-- source/api/ut_runner.pkb | 14 +-- source/core/types/ut_run.tpb | 2 +- source/core/types/ut_run.tps | 6 +- source/core/ut_suite_builder.pkb | 2 +- source/core/ut_suite_cache_manager.pkb | 150 ++++++++++++++++++------- source/core/ut_suite_cache_manager.pks | 5 +- source/core/ut_suite_manager.pkb | 6 +- source/core/ut_suite_manager.pks | 2 +- source/core/ut_utils.pks | 4 + test/ut3_user/api/test_ut_run.pkb | 74 +++++++++++- test/ut3_user/api/test_ut_run.pks | 15 +++ 12 files changed, 280 insertions(+), 71 deletions(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 0e3b6446e..7fd2c09fa 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1616,11 +1616,8 @@ or Tags are defined as a comma separated list within the `--%tags` annotation. -When executing a test run with tag filter applied, the framework will find all tests associated with the given tags and execute them. -The framework applies `OR` logic to all specified tags so any test / suite that matches at least one tag will be included in the test run. - -When a suite/context is tagged, all of its children will automatically inherit the tag and get executed along with the parent. Parent suite tests are not executed, but a suitepath hierarchy is kept. - +When a suite/context is tagged, all of its children will automatically inherit the tag and get executed along with the parent, unless they are excluded by tag expression. +Parent suite tests are not executed, but a suitepath hierarchy is kept. Sample test suite package with tags. ```sql linenums="1" @@ -1661,7 +1658,37 @@ end ut_sample_test; / ``` -Execution of the test is done by using the parameter `a_tags` +#### Tag Expressions + +Tag expressions are boolean expressions with the operators !, & and |. In addition, ( and ) can be used to adjust for operator precedence. + +Two special expressions are supported, any() and none(), which select all tests with any tags at all, and all tests without any tags, respectively. These special expressions may be combined with other expressions just like normal tags. + +| Operator | Meaning | +| -------- | --------| +| ! | not | +| & | and | +| \| | or | + +If you are tagging your tests across multiple dimensions, tag expressions help you to select which tests to execute. When tagging by test type (e.g., micro, integration, end-to-end) and feature (e.g., product, catalog, shipping), the following tag expressions can be useful. + + +| Tag Expression | Selection | +| -------- | --------| +| product | all tests for product | +| catalog \| shipping | all tests for catalog plus all tests for shipping | +| catalog & shipping | all tests for the intersection between catalog and shipping | +| product & !end-to-end | all tests for product, but not the end-to-end tests | +| (micro \| integration) & (product \| shipping) | all micro or integration tests for product or shipping | + + +Execution of the test is done by using the parameter `a_tags` with tag expressions + + +```sql linenums="1" +select * from table(ut.run(a_tags => 'fast||!complex')); +``` +The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` because a suite meet expression condition. ```sql linenums="1" select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'api')); @@ -1683,8 +1710,14 @@ The above call will execute both `ut_sample_test.ut_refcursors1` and `ut_sample_ Tags must follow the below naming convention: - tag is case sensitive -- tag can contain special characters like `$#/\?-!` etc. -- tag cannot be an empty string +- tag must not contain any of the following reserved characters: + - comma (,) + - left or right parenthesis ((, )) + - ampersand (&) + - vertical bar (|) + - exclamation point (!) +- tag cannot be null or blank +- tag cannot contain whitespace - tag cannot start with a dash, e.g. `-some-stuff` is **not** a valid tag - tag cannot contain spaces, e.g. `test of batch`. To create a multi-word tag use underscores or dashes, e.g. `test_of_batch`, `test-of-batch` - leading and trailing spaces are ignored in tag name, e.g. `--%tags( tag1 , tag2 )` becomes `tag1` and `tag2` tag names @@ -1693,13 +1726,31 @@ Tags must follow the below naming convention: #### Excluding tests/suites by tags It is possible to exclude parts of test suites with tags. -In order to do so, prefix the tag name to exclude with a `-` (dash) sign when invoking the test run. - +In order to do so, prefix the tag name to exclude with a `!` (exclamation) sign when invoking the test run which is equivalent of `-` (dash) in legacy notation. Examples (based on above sample test suite) +```sql linenums="1" +select * from table(ut.run(a_tags => '(api|fast)&!complex')); +``` + +which is equivalent of legacy calling: + ```sql linenums="1" select * from table(ut.run(a_tags => 'api,fast,-complex')); ``` + +or + +```sql linenums="1" +select * from table(ut.run(a_tags => '(api|fast)&(!complex&!test1)')); +``` + +which is equivalent of legacy calling: + +```sql linenums="1" +select * from table(ut.run(a_tags => 'api,fast,-complex,-test1')); +``` + The above call will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex`. Given the above example package `ut_sample_test`, only `ut_sample_test.ut_test` will be executed. diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index b69a51a04..2760868e0 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -79,7 +79,8 @@ create or replace package body ut_runner is l_coverage_schema_names ut_varchar2_rows; l_paths ut_varchar2_list; l_random_test_order_seed positive; - l_tags ut_varchar2_rows := ut_varchar2_rows(); + l_tags varchar2(4000) := a_tags; + begin ut_event_manager.initialize(); if a_reporters is not empty then @@ -94,6 +95,11 @@ create or replace package body ut_runner is ut_event_manager.trigger_event(ut_event_manager.gc_initialize); ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_run_info()); + --Verify tag tag expression is valid + if regexp_like(l_tags,'[&|]{2,}|[!-]{2,}|[!-][&|]|[^-&|!]+[-!]|[-!|&][)]') + or (regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)')) then + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + end if; if a_random_test_order_seed is not null then l_random_test_order_seed := a_random_test_order_seed; elsif a_random_test_order then @@ -118,12 +124,6 @@ create or replace package body ut_runner is l_coverage_schema_names := ut_suite_manager.get_schema_names(l_paths); end if; - - if a_tags is not null then - l_tags := l_tags multiset union distinct ut_utils.convert_collection( - ut_utils.trim_list_elements(ut_utils.filter_list(ut_utils.string_to_table(a_tags,','),ut_utils.gc_word_no_space)) - ); - end if; l_run := ut_run( a_run_paths => l_paths, a_coverage_options => ut_coverage_options( diff --git a/source/core/types/ut_run.tpb b/source/core/types/ut_run.tpb index cdafb30fc..660c88791 100644 --- a/source/core/types/ut_run.tpb +++ b/source/core/types/ut_run.tpb @@ -24,7 +24,7 @@ create or replace type body ut_run as a_test_file_mappings ut_file_mappings := null, a_client_character_set varchar2 := null, a_random_test_order_seed positive := null, - a_run_tags ut_varchar2_rows := null + a_run_tags varchar2 := null ) return self as result is begin self.run_paths := a_run_paths; diff --git a/source/core/types/ut_run.tps b/source/core/types/ut_run.tps index debf847cd..8ce80d2a1 100644 --- a/source/core/types/ut_run.tps +++ b/source/core/types/ut_run.tps @@ -1,4 +1,4 @@ -create or replace type ut_run under ut_suite_item ( +create or replace type ut_run force under ut_suite_item ( /* utPLSQL - Version 3 Copyright 2016 - 2021 utPLSQL Project @@ -21,7 +21,7 @@ create or replace type ut_run under ut_suite_item ( project_name varchar2(4000), items ut_suite_items, run_paths ut_varchar2_list, - run_tags ut_varchar2_rows, + run_tags varchar2(4000), coverage_options ut_coverage_options, test_file_mappings ut_file_mappings, client_character_set varchar2(100), @@ -34,7 +34,7 @@ create or replace type ut_run under ut_suite_item ( a_test_file_mappings ut_file_mappings := null, a_client_character_set varchar2 := null, a_random_test_order_seed positive := null, - a_run_tags ut_varchar2_rows := null + a_run_tags varchar2 := null ) return self as result, overriding member procedure mark_as_skipped(self in out nocopy ut_run,a_skip_reason in varchar2), overriding member function do_execute(self in out nocopy ut_run) return boolean, diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index ebb113370..4aa2ff915 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -205,7 +205,7 @@ create or replace package body ut_suite_builder is l_tag_items := ut_utils.trim_list_elements(ut_utils.string_to_table(a_tags_ann_text(l_annotation_pos),',')); if l_tag_items is not empty then for i in 1 .. l_tag_items.count loop - if regexp_like(l_tag_items(i),'^[^-](\S)+$') then + if regexp_like(l_tag_items(i),'^[^-!&|](\S)+$') then l_tags_list.extend(); l_tags_list(l_tags_list.last) := l_tag_items(i); else diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index d3e832a9b..276f9427d 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -221,52 +221,118 @@ create or replace package body ut_suite_cache_manager is return l_suite_items; end; + /* + To support a legact tag notation + , = OR + - = NOT + we will perform a replace of that characters into + new notation. + || = OR + && = AND + ^ = NOT + */ + --TODO: How do we prevent when old notation reach 4k an new will be longer? + function replace_legacy_tag_notation(a_tags varchar2 + ) return varchar2 is + l_tags ut_varchar2_list := ut_utils.string_to_table(a_tags,','); + l_tags_include varchar2(2000); + l_tags_exclude varchar2(2000); + l_return_tag varchar2(4000); + begin + select listagg( t.column_value,' | ') + within group( order by column_value) + into l_tags_include + from table(l_tags) t + where t.column_value not like '-%'; + + select listagg( replace(t.column_value,'-','!'),' & ') + within group( order by column_value) + into l_tags_exclude + from table(l_tags) t + where t.column_value like '-%'; + + l_return_tag:= + case when l_tags_include is not null then + '('||l_tags_include||')' else null end || + case when l_tags_include is not null and l_tags_exclude is not null then + ' & ' else null end || + case when l_tags_exclude is not null then + '('||l_tags_exclude||')' else null end; + + return l_return_tag; + end; + + function create_where_filter(a_tags varchar2 + ) return varchar2 is + l_tags varchar2(4000):= replace(a_tags,' '); + begin + if instr(l_tags,',') > 0 or instr(l_tags,'-') > 0 then + l_tags := replace(replace_legacy_tag_notation(l_tags),' '); + end if; + l_tags := REGEXP_REPLACE(l_tags, + '(\(|\)|\||\!|\&)?([^|&!-]+)(\(|\)|\||\!|\&)?', + q'[\1q'<\2>' member of tags\3]'); + --replace operands to XPath + l_tags := REGEXP_REPLACE(l_tags, '\|',' or '); + l_tags := REGEXP_REPLACE(l_tags , '\&',' and '); + l_tags := REGEXP_REPLACE(l_tags,q'[(\!)(q'<[^|&!-]+>')( member of tags)]','\2 not \3'); + l_tags := '('||l_tags||')'; + return l_tags; + end; + /* Having a base set of suites we will do a further filter down if there are any tags defined. - */ + */ function get_tags_suites ( a_suite_items ut_suite_cache_rows, - a_tags ut_varchar2_rows + a_tags varchar2 ) return ut_suite_cache_rows is - l_suite_tags ut_suite_cache_rows := ut_suite_cache_rows(); - l_include_tags ut_varchar2_rows; - l_exclude_tags ut_varchar2_rows; + l_suite_tags ut_suite_cache_rows := ut_suite_cache_rows(); + l_sql varchar2(32000); + l_tags varchar2(4000):= create_where_filter(a_tags); begin - - select /*+ no_parallel */ column_value - bulk collect into l_include_tags - from table(a_tags) - where column_value not like '-%'; - - select /*+ no_parallel */ ltrim(column_value,'-') - bulk collect into l_exclude_tags - from table(a_tags) - where column_value like '-%'; - - with included_tags as ( - select c.path as path - from table(a_suite_items) c - where c.tags multiset intersect l_include_tags is not empty or l_include_tags is empty - ), - excluded_tags as ( - select c.path as path - from table(a_suite_items) c - where c.tags multiset intersect l_exclude_tags is not empty - ) - select value(c) as obj - bulk collect into l_suite_tags - from table(a_suite_items) c - where exists ( - select 1 from included_tags t - where t.path||'.' like c.path || '.%' /*all ancestors and self*/ - or c.path||'.' like t.path || '.%' /*all descendants and self*/ - ) - and not exists ( - select 1 from excluded_tags t - where c.path||'.' like t.path || '.%' /*all descendants and self*/ - ); - return l_suite_tags; + l_sql := + q'[ +with + suites_mv as ( + select c.id,value(c) as obj,c.path as path,c.self_type,c.object_owner,c.tags + from table(:suite_items) c + ), + suites_matching_expr as ( + select c.id,c.path as path,c.self_type,c.object_owner,c.tags + from suites_mv c + where c.self_type in ('UT_SUITE','UT_CONTEXT') + and ]'||l_tags||q'[ + ), + tests_matching_expr as ( + select c.id,c.path as path,c.self_type,c.object_owner,c.tags + from suites_mv c where c.self_type in ('UT_TEST') + and ]'||l_tags||q'[ + ), + tests_with_tags_inherited_from_suite as ( + select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner + from suites_mv c join suites_matching_expr t + on (c.path||'.' like t.path || '.%' /*all descendants and self*/ and c.object_owner = t.object_owner) + ), + tests_with_tags_promoted_to_suites as ( + select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner + from suites_mv c join tests_matching_expr t + on (t.path||'.' like c.path || '.%' /*all ancestors and self*/ and c.object_owner = t.object_owner) + ) + select obj from suites_mv c, + (select id,row_number() over (partition by id order by id) r_num from + (select id + from tests_with_tags_promoted_to_suites tst + where ]'||l_tags||q'[ + union all + select id from tests_with_tags_inherited_from_suite tst + where ]'||l_tags||q'[ + ) + ) t where c.id = t.id and r_num = 1 ]'; + + execute immediate l_sql bulk collect into l_suite_tags using a_suite_items; + return l_suite_tags; end; /* @@ -323,17 +389,17 @@ create or replace package body ut_suite_cache_manager is function get_cached_suite_rows( a_schema_paths ut_path_items, a_random_seed positive := null, - a_tags ut_varchar2_rows := null + a_tags varchar2 := null ) return ut_suite_cache_rows is l_results ut_suite_cache_rows := ut_suite_cache_rows(); l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); l_schema_paths ut_path_items; - l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows()); + l_tags varchar2(4000) := a_tags; begin l_schema_paths := a_schema_paths; l_suite_items := get_suite_items(a_schema_paths); - if l_tags.count > 0 then + if length(l_tags) > 0 then l_suite_items := get_tags_suites(l_suite_items,l_tags); end if; diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 974babca5..72dd08800 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -57,7 +57,7 @@ create or replace package ut_suite_cache_manager authid definer is function get_cached_suite_rows( a_schema_paths ut_path_items, a_random_seed positive := null, - a_tags ut_varchar2_rows := null + a_tags varchar2 := null ) return ut_suite_cache_rows; function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items; @@ -95,5 +95,8 @@ create or replace package ut_suite_cache_manager authid definer is a_procedure_name varchar2 ) return boolean; + +function create_where_filter(a_tags varchar2 + ) return varchar2; end ut_suite_cache_manager; / diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 86f68c076..0f8629ded 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -352,7 +352,7 @@ create or replace package body ut_suite_manager is function get_cached_suite_data( a_schema_paths ut_path_items, a_random_seed positive, - a_tags ut_varchar2_rows := null, + a_tags varchar2 := null, a_skip_all_objects boolean := false ) return t_cached_suites_cursor is l_unfiltered_rows ut_suite_cache_rows; @@ -451,7 +451,7 @@ create or replace package body ut_suite_manager is a_schema_paths ut_path_items, a_suites in out nocopy ut_suite_items, a_random_seed positive, - a_tags ut_varchar2_rows := null + a_tags varchar2 := null ) is begin reconstruct_from_cache( @@ -528,7 +528,7 @@ create or replace package body ut_suite_manager is a_paths ut_varchar2_list, a_suites out nocopy ut_suite_items, a_random_seed positive := null, - a_tags ut_varchar2_rows := ut_varchar2_rows() + a_tags varchar2 := null ) is l_paths ut_varchar2_list := a_paths; l_schema_names ut_varchar2_rows; diff --git a/source/core/ut_suite_manager.pks b/source/core/ut_suite_manager.pks index 65b3c0654..07539139a 100644 --- a/source/core/ut_suite_manager.pks +++ b/source/core/ut_suite_manager.pks @@ -53,7 +53,7 @@ create or replace package ut_suite_manager authid current_user is a_paths in ut_varchar2_list, a_suites out nocopy ut_suite_items, a_random_seed in positive := null, - a_tags ut_varchar2_rows := ut_varchar2_rows() + a_tags in varchar2 := null ); /** diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 18a3d5952..f7f7b4f00 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -121,6 +121,10 @@ create or replace package ut_utils authid definer is ex_failed_open_cur exception; gc_failed_open_cur constant pls_integer := -20218; pragma exception_init (ex_failed_open_cur, -20218); + + ex_invalid_tag_expression exception; + gc_invalid_tag_expression constant pls_integer := -20219; + pragma exception_init (ex_invalid_tag_expression, -20219); gc_max_storage_varchar2_len constant integer := 4000; gc_max_output_string_length constant integer := 4000; diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 41b969359..6f6e229c8 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -948,7 +948,7 @@ Failures:% procedure two_test_run_by_two_tags is l_results clob; begin - ut3_tester_helper.run_helper.run(a_tags => 'subtest1,subtest2'); + ut3_tester_helper.run_helper.run(a_tags => 'subtest1|subtest2'); l_results := ut3_tester_helper.main_helper.get_dbms_output_as_clob(); --Assert ut.expect( l_results ).to_be_like( '%test_package_1%' ); @@ -958,7 +958,21 @@ Failures:% ut.expect( l_results ).not_to_be_like( '%test_package_3%' ); ut.expect( l_results ).not_to_be_like( '%test_package_3%' ); end; - + + procedure two_test_run_by_two_tags_leg is + l_results clob; + begin + ut3_tester_helper.run_helper.run(a_tags => 'subtest1,subtest2'); + l_results := ut3_tester_helper.main_helper.get_dbms_output_as_clob(); + --Assert + ut.expect( l_results ).to_be_like( '%test_package_1%' ); + ut.expect( l_results ).to_be_like( '%test_package_2%' ); + ut.expect( l_results ).not_to_be_like( '%test_package_1.test2%' ); + ut.expect( l_results ).not_to_be_like( '%test_package_2.test2%' ); + ut.expect( l_results ).not_to_be_like( '%test_package_3%' ); + ut.expect( l_results ).not_to_be_like( '%test_package_3%' ); + end; + procedure suite_with_children_tag is l_results clob; begin @@ -1078,6 +1092,20 @@ Failures:% procedure tag_run_func_path_list is l_results ut3_develop.ut_varchar2_list; + begin + l_results := ut3_tester_helper.run_helper.run(ut3_develop.ut_varchar2_list(':tests.test_package_1',':tests'),a_tags => 'suite1test1|suite2test1'); + --Assert + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_1%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_2%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_1.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_2.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3%' ); + end; + + procedure tag_run_func_path_list_leg is + l_results ut3_develop.ut_varchar2_list; begin l_results := ut3_tester_helper.run_helper.run(ut3_develop.ut_varchar2_list(':tests.test_package_1',':tests'),a_tags => 'suite1test1,suite2test1'); --Assert @@ -1092,6 +1120,18 @@ Failures:% procedure tag_inc_exc_run_func_path_list is l_results ut3_develop.ut_varchar2_list; + begin + l_results := ut3_tester_helper.run_helper.run(ut3_develop.ut_varchar2_list(':tests.test_package_1',':tests'),a_tags => '(suite1test1|suite2test1)&!suite2'); + --Assert + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_1%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_1.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3%' ); + end; + + procedure tag_inc_exc_run_fun_pth_lst_lg is + l_results ut3_develop.ut_varchar2_list; begin l_results := ut3_tester_helper.run_helper.run(ut3_develop.ut_varchar2_list(':tests.test_package_1',':tests'),a_tags => 'suite1test1,suite2test1,-suite2'); --Assert @@ -1104,6 +1144,22 @@ Failures:% procedure tag_exclude_run_func_path_list is l_results ut3_develop.ut_varchar2_list; + begin + l_results := ut3_tester_helper.run_helper.run(ut3_develop.ut_varchar2_list(':tests,:tests2'),a_tags => '!suite1test2&!suite2test1&!test1suite3'); + --Assert + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_1%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_2%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_3%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_1.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_2.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_3.test2%executed%' ); + end; + +procedure tag_exclude_run_fun_pth_lst_lg is + l_results ut3_develop.ut_varchar2_list; begin l_results := ut3_tester_helper.run_helper.run(ut3_develop.ut_varchar2_list(':tests,:tests2'),a_tags => '-suite1test2,-suite2test1,-test1suite3'); --Assert @@ -1120,6 +1176,20 @@ Failures:% procedure tag_include_exclude_run_func is l_results ut3_develop.ut_varchar2_list; + begin + l_results := ut3_tester_helper.run_helper.run(a_tags => '(suite1)&(!suite1test2&!suite2test1&!test1suite3)'); + --Assert + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_1%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_2%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_1.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_2.test2%executed%' ); + end; + + procedure tag_include_exclude_run_fun_lg is + l_results ut3_develop.ut_varchar2_list; begin l_results := ut3_tester_helper.run_helper.run(a_tags => 'suite1,-suite1test2,-suite2test1,-test1suite3'); --Assert diff --git a/test/ut3_user/api/test_ut_run.pks b/test/ut3_user/api/test_ut_run.pks index b3be8700d..db02ee8f8 100644 --- a/test/ut3_user/api/test_ut_run.pks +++ b/test/ut3_user/api/test_ut_run.pks @@ -202,6 +202,9 @@ create or replace package test_ut_run is --%test(Execute tests by passing two tags) procedure two_test_run_by_two_tags; + --%test(Execute tests by passing two tags - Legacy notation) + procedure two_test_run_by_two_tags_leg; + --%test(Execute suite and all of its children) procedure suite_with_children_tag; @@ -235,15 +238,27 @@ create or replace package test_ut_run is --%test(Runs tests from given paths with paths list and a tag) procedure tag_run_func_path_list; + --%test(Runs tests from given paths with paths list and a tag - Legacy Notation) + procedure tag_run_func_path_list_leg; + --%test(Runs tests from given paths with paths list and include/exclude tags) procedure tag_inc_exc_run_func_path_list; + --%test(Runs tests from given paths with paths list and include/exclude tags - Legacy Notation) + procedure tag_inc_exc_run_fun_pth_lst_lg; + --%test(Runs tests from given path and excludes specific tags) procedure tag_exclude_run_func_path_list; + --%test(Runs tests from given path and excludes specific tags - Legacy Notation) + procedure tag_exclude_run_fun_pth_lst_lg; + --%test(Runs tests from given tags and exclude tags) procedure tag_include_exclude_run_func; + --%test(Runs tests from given tags and exclude tags - Legacy Notation) + procedure tag_include_exclude_run_fun_lg; + --%endcontext --%context(ut3_info context) From adbc76eb027f8425975b8277d4a10e2ec9ce7f7c Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 27 Mar 2023 23:04:34 -0700 Subject: [PATCH 134/187] Address too long identified in 11g. Address flaky expression checker to be reworked. --- source/api/ut_runner.pkb | 6 ++++-- source/core/ut_suite_cache_manager.pkb | 10 +++++----- source/core/ut_suite_cache_manager.pks | 5 +---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index 2760868e0..94538eb69 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -95,11 +95,13 @@ create or replace package body ut_runner is ut_event_manager.trigger_event(ut_event_manager.gc_initialize); ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_run_info()); - --Verify tag tag expression is valid - if regexp_like(l_tags,'[&|]{2,}|[!-]{2,}|[!-][&|]|[^-&|!]+[-!]|[-!|&][)]') + --TODO:Verify tag tag expression is valid + /* + if regexp_like(l_tags,'[&|]{2,}|[!-]{2,}|[!-][&|]|[^-&|!,]+[-!]|[-!|&][)]') or (regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)')) then raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); end if; + */ if a_random_test_order_seed is not null then l_random_test_order_seed := a_random_test_order_seed; elsif a_random_test_order then diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 276f9427d..ff18deabf 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -270,7 +270,7 @@ create or replace package body ut_suite_cache_manager is l_tags := replace(replace_legacy_tag_notation(l_tags),' '); end if; l_tags := REGEXP_REPLACE(l_tags, - '(\(|\)|\||\!|\&)?([^|&!-]+)(\(|\)|\||\!|\&)?', + '(\(|\)|\||\!|\&)?([^|&!-()]+)(\(|\)|\||\!|\&)?', q'[\1q'<\2>' member of tags\3]'); --replace operands to XPath l_tags := REGEXP_REPLACE(l_tags, '\|',' or '); @@ -310,12 +310,12 @@ with from suites_mv c where c.self_type in ('UT_TEST') and ]'||l_tags||q'[ ), - tests_with_tags_inherited_from_suite as ( + tests_with_tags_inh_from_suite as ( select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner from suites_mv c join suites_matching_expr t on (c.path||'.' like t.path || '.%' /*all descendants and self*/ and c.object_owner = t.object_owner) ), - tests_with_tags_promoted_to_suites as ( + tests_with_tags_prom_to_suite as ( select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner from suites_mv c join tests_matching_expr t on (t.path||'.' like c.path || '.%' /*all ancestors and self*/ and c.object_owner = t.object_owner) @@ -323,10 +323,10 @@ with select obj from suites_mv c, (select id,row_number() over (partition by id order by id) r_num from (select id - from tests_with_tags_promoted_to_suites tst + from tests_with_tags_prom_to_suite tst where ]'||l_tags||q'[ union all - select id from tests_with_tags_inherited_from_suite tst + select id from tests_with_tags_inh_from_suite tst where ]'||l_tags||q'[ ) ) t where c.id = t.id and r_num = 1 ]'; diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 72dd08800..7f06e95eb 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -94,9 +94,6 @@ create or replace package ut_suite_cache_manager authid definer is a_package_name varchar2, a_procedure_name varchar2 ) return boolean; - - -function create_where_filter(a_tags varchar2 - ) return varchar2; + end ut_suite_cache_manager; / From 1478b0d21035398f3b6eccf82b37fa91adeb0e6b Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 29 Mar 2023 12:41:32 -0700 Subject: [PATCH 135/187] Adding validation for tag expression --- source/api/ut_runner.pkb | 7 +-- source/core/ut_utils.pkb | 63 +++++++++++++++++++++++++- source/core/ut_utils.pks | 2 + test/ut3_tester/core/test_ut_utils.pkb | 27 +++++++++++ test/ut3_tester/core/test_ut_utils.pks | 2 + 5 files changed, 95 insertions(+), 6 deletions(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index 94538eb69..1ecaf1a42 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -95,13 +95,10 @@ create or replace package body ut_runner is ut_event_manager.trigger_event(ut_event_manager.gc_initialize); ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_run_info()); - --TODO:Verify tag tag expression is valid - /* - if regexp_like(l_tags,'[&|]{2,}|[!-]{2,}|[!-][&|]|[^-&|!,]+[-!]|[-!|&][)]') - or (regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)')) then + if ut_utils.valid_tag_expression(l_tags) = 0 then raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); end if; - */ + if a_random_test_order_seed is not null then l_random_test_order_seed := a_random_test_order_seed; elsif a_random_test_order then diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 162e50f8f..03ce1ad55 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -988,7 +988,68 @@ create or replace package body ut_utils is return l_result; end; - + + function valid_tag_expression(a_tags in varchar2) return number is + t_left_side ut_varchar2_list := ut_varchar2_list('|','&',','); + t_right_side ut_varchar2_list := ut_varchar2_list('!','-'); + l_left_side_expression varchar2(100) := '[|&,]'; + l_left_side_regex varchar(400) := '([^|&,]*)[|&,](.*)'; + l_left_side varchar2(4000); + + l_rigth_side_expression varchar2(100) := '[!-]'; + l_right_side_regex varchar(400) := '([!-])([^!-].*)'; + l_right_side varchar2(4000); + + l_tags varchar2(4000) := a_tags; + l_result number :=1; + begin + --Validate that we have closed up all brackets + if regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)') then + l_result := 0; + end if; + + --Remove brackets as we dont evaluate expression only validate. + l_tags := replace(replace(l_tags,'('),')'); + + --Check if there are any left side operators for first in order from left to right + if regexp_count(l_tags,l_left_side_expression) > 0 then + --Extract left part of operator and remaining of string to right + l_left_side := regexp_replace(l_tags,l_left_side_regex,'\1'); + l_right_side := regexp_replace(l_tags,l_left_side_regex,'\2'); + + --If left side is null that means that we used left side operator without + -- left and right e.g. &test + if l_left_side is null then + l_result := 0; + else + --Extract right side from left side expression if there is any !- + --Remove first negation tag to see if there is double negation + l_left_side := regexp_replace(l_left_side,l_right_side_regex,'\2'); + end if; + + + --check that on right side there is no extra negation + if regexp_count(l_left_side,l_rigth_side_expression) > 0 then + l_result := 0; + end if; + + --Now process right side of string + if l_right_side is not null then + l_result := least(l_result,valid_tag_expression(l_right_side)); + else + l_result := 0; + end if; + else + --We just process single tag. + l_left_side := l_tags; + l_left_side := regexp_replace(l_left_side,l_right_side_regex,'\2'); + if regexp_count(l_left_side,l_rigth_side_expression) > 0 then + l_result := 0; + end if; + end if; + + return l_result; + end; end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index f7f7b4f00..2975c3846 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -477,5 +477,7 @@ create or replace package ut_utils authid definer is */ function interval_to_text(a_interval yminterval_unconstrained) return varchar2; + function valid_tag_expression(a_tags in varchar2) return number; + end ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 4ed718777..52c9cdff8 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -489,5 +489,32 @@ end; ut.expect(l_expected).to_equal(l_actual); end; + procedure valid_tag_expressions is + begin + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1&tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|!tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1&!tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1|!tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1&!tag2')); + + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1,tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('-tag1')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1,-tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('-tag1,-tag2')); + + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('(!tag1|!tag2)|tag3')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('(!tag1&!tag2)|(tag3&tag4)')); + + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|')); + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('&!tag2')); + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('!!tag1|!tag2')); + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1&!tag2|')); + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('((!tag1|!tag2)|tag3')); + + end; + end test_ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 4d83b5042..b87d3b2c6 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -154,6 +154,8 @@ create or replace package test_ut_utils is --%test(returns text representation of interval year to month for custom interval) procedure int_conv_ym_date; + --%test(Test to validate different type of expressions passed as tags) + procedure valid_tag_expressions; --%endcontext From b5ad7475b53f5b4b14d9805f9c56b8e36dde0883 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 29 Mar 2023 14:53:24 -0700 Subject: [PATCH 136/187] Comment out to see why its failing. --- source/api/ut_runner.pkb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index 1ecaf1a42..5f4912a24 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -94,10 +94,12 @@ create or replace package body ut_runner is ut_event_manager.trigger_event(ut_event_manager.gc_initialize); ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_run_info()); - + + /* if ut_utils.valid_tag_expression(l_tags) = 0 then raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); end if; + */ if a_random_test_order_seed is not null then l_random_test_order_seed := a_random_test_order_seed; From 06cb054aa72b8aca8115f277e673485321efc0ad Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 29 Mar 2023 15:10:34 -0700 Subject: [PATCH 137/187] Revert "Comment out to see why its failing." This reverts commit b5ad7475b53f5b4b14d9805f9c56b8e36dde0883. Revert "Adding validation for tag expression" This reverts commit 1478b0d21035398f3b6eccf82b37fa91adeb0e6b. --- source/api/ut_runner.pkb | 7 +-- source/core/ut_utils.pkb | 63 +------------------------- source/core/ut_utils.pks | 2 - test/ut3_tester/core/test_ut_utils.pkb | 27 ----------- test/ut3_tester/core/test_ut_utils.pks | 2 - 5 files changed, 5 insertions(+), 96 deletions(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index 5f4912a24..94538eb69 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -94,13 +94,14 @@ create or replace package body ut_runner is ut_event_manager.trigger_event(ut_event_manager.gc_initialize); ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_run_info()); - + + --TODO:Verify tag tag expression is valid /* - if ut_utils.valid_tag_expression(l_tags) = 0 then + if regexp_like(l_tags,'[&|]{2,}|[!-]{2,}|[!-][&|]|[^-&|!,]+[-!]|[-!|&][)]') + or (regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)')) then raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); end if; */ - if a_random_test_order_seed is not null then l_random_test_order_seed := a_random_test_order_seed; elsif a_random_test_order then diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 03ce1ad55..162e50f8f 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -988,68 +988,7 @@ create or replace package body ut_utils is return l_result; end; - - function valid_tag_expression(a_tags in varchar2) return number is - t_left_side ut_varchar2_list := ut_varchar2_list('|','&',','); - t_right_side ut_varchar2_list := ut_varchar2_list('!','-'); - l_left_side_expression varchar2(100) := '[|&,]'; - l_left_side_regex varchar(400) := '([^|&,]*)[|&,](.*)'; - l_left_side varchar2(4000); - - l_rigth_side_expression varchar2(100) := '[!-]'; - l_right_side_regex varchar(400) := '([!-])([^!-].*)'; - l_right_side varchar2(4000); - - l_tags varchar2(4000) := a_tags; - l_result number :=1; - begin - --Validate that we have closed up all brackets - if regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)') then - l_result := 0; - end if; - - --Remove brackets as we dont evaluate expression only validate. - l_tags := replace(replace(l_tags,'('),')'); - - --Check if there are any left side operators for first in order from left to right - if regexp_count(l_tags,l_left_side_expression) > 0 then - --Extract left part of operator and remaining of string to right - l_left_side := regexp_replace(l_tags,l_left_side_regex,'\1'); - l_right_side := regexp_replace(l_tags,l_left_side_regex,'\2'); - - --If left side is null that means that we used left side operator without - -- left and right e.g. &test - if l_left_side is null then - l_result := 0; - else - --Extract right side from left side expression if there is any !- - --Remove first negation tag to see if there is double negation - l_left_side := regexp_replace(l_left_side,l_right_side_regex,'\2'); - end if; - - - --check that on right side there is no extra negation - if regexp_count(l_left_side,l_rigth_side_expression) > 0 then - l_result := 0; - end if; - - --Now process right side of string - if l_right_side is not null then - l_result := least(l_result,valid_tag_expression(l_right_side)); - else - l_result := 0; - end if; - else - --We just process single tag. - l_left_side := l_tags; - l_left_side := regexp_replace(l_left_side,l_right_side_regex,'\2'); - if regexp_count(l_left_side,l_rigth_side_expression) > 0 then - l_result := 0; - end if; - end if; - - return l_result; - end; + end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 2975c3846..f7f7b4f00 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -477,7 +477,5 @@ create or replace package ut_utils authid definer is */ function interval_to_text(a_interval yminterval_unconstrained) return varchar2; - function valid_tag_expression(a_tags in varchar2) return number; - end ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 52c9cdff8..4ed718777 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -489,32 +489,5 @@ end; ut.expect(l_expected).to_equal(l_actual); end; - procedure valid_tag_expressions is - begin - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1&tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|!tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1&!tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1|!tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1&!tag2')); - - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1,tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('-tag1')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1,-tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('-tag1,-tag2')); - - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('(!tag1|!tag2)|tag3')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('(!tag1&!tag2)|(tag3&tag4)')); - - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|')); - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('&!tag2')); - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('!!tag1|!tag2')); - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1&!tag2|')); - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('((!tag1|!tag2)|tag3')); - - end; - end test_ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index b87d3b2c6..4d83b5042 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -154,8 +154,6 @@ create or replace package test_ut_utils is --%test(returns text representation of interval year to month for custom interval) procedure int_conv_ym_date; - --%test(Test to validate different type of expressions passed as tags) - procedure valid_tag_expressions; --%endcontext From e87d39f992da9ff7fdb0cb2b653f6fc0380c6def Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 29 Mar 2023 15:17:46 -0700 Subject: [PATCH 138/187] Adding validate function, with no calls --- source/core/ut_utils.pkb | 61 ++++++++++++++++++++++++++++++++++++++++ source/core/ut_utils.pks | 7 ++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 162e50f8f..14d0bc148 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -989,6 +989,67 @@ create or replace package body ut_utils is return l_result; end; + function valid_tag_expression(a_tags in varchar2) return number is + t_left_side ut_varchar2_list := ut_varchar2_list('|','&',','); + t_right_side ut_varchar2_list := ut_varchar2_list('!','-'); + l_left_side_expression varchar2(100) := '[|&,]'; + l_left_side_regex varchar(400) := '([^|&,]*)[|&,](.*)'; + l_left_side varchar2(4000); + + l_rigth_side_expression varchar2(100) := '[!-]'; + l_right_side_regex varchar(400) := '([!-])([^!-].*)'; + l_right_side varchar2(4000); + + l_tags varchar2(4000) := a_tags; + l_result number :=1; + begin + --Validate that we have closed up all brackets + if regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)') then + l_result := 0; + end if; + + --Remove brackets as we dont evaluate expression only validate. + l_tags := replace(replace(l_tags,'('),')'); + + --Check if there are any left side operators for first in order from left to right + if regexp_count(l_tags,l_left_side_expression) > 0 then + --Extract left part of operator and remaining of string to right + l_left_side := regexp_replace(l_tags,l_left_side_regex,'\1'); + l_right_side := regexp_replace(l_tags,l_left_side_regex,'\2'); + + --If left side is null that means that we used left side operator without + -- left and right e.g. &test + if l_left_side is null then + l_result := 0; + else + --Extract right side from left side expression if there is any !- + --Remove first negation tag to see if there is double negation + l_left_side := regexp_replace(l_left_side,l_right_side_regex,'\2'); + end if; + + + --check that on right side there is no extra negation + if regexp_count(l_left_side,l_rigth_side_expression) > 0 then + l_result := 0; + end if; + + --Now process right side of string + if l_right_side is not null then + l_result := least(l_result,valid_tag_expression(l_right_side)); + else + l_result := 0; + end if; + else + --We just process single tag. + l_left_side := l_tags; + l_left_side := regexp_replace(l_left_side,l_right_side_regex,'\2'); + if regexp_count(l_left_side,l_rigth_side_expression) > 0 then + l_result := 0; + end if; + end if; + + return l_result; + end; end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index f7f7b4f00..06c6956b4 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -476,6 +476,11 @@ create or replace package ut_utils authid definer is * Return value of interval in plain english */ function interval_to_text(a_interval yminterval_unconstrained) return varchar2; - + + /* + * Return number 1 or 0 if the list of tags is valid expression + */ + function valid_tag_expression(a_tags in varchar2) return number; + end ut_utils; / From 97537de9629c19313ccc6157ac95f323a2de6656 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 29 Mar 2023 15:29:07 -0700 Subject: [PATCH 139/187] Remove a & from text --- source/api/ut_runner.pkb | 7 ++----- source/core/ut_utils.pkb | 2 +- test/ut3_tester/core/test_ut_utils.pkb | 27 ++++++++++++++++++++++++++ test/ut3_tester/core/test_ut_utils.pks | 3 +++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index 94538eb69..a2a69f464 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -95,13 +95,10 @@ create or replace package body ut_runner is ut_event_manager.trigger_event(ut_event_manager.gc_initialize); ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_run_info()); - --TODO:Verify tag tag expression is valid - /* - if regexp_like(l_tags,'[&|]{2,}|[!-]{2,}|[!-][&|]|[^-&|!,]+[-!]|[-!|&][)]') - or (regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)')) then + if ut_utils.valid_tag_expression(l_tags) = 0 then raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); end if; - */ + if a_random_test_order_seed is not null then l_random_test_order_seed := a_random_test_order_seed; elsif a_random_test_order then diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 14d0bc148..2a47d4d4b 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -1018,7 +1018,7 @@ create or replace package body ut_utils is l_right_side := regexp_replace(l_tags,l_left_side_regex,'\2'); --If left side is null that means that we used left side operator without - -- left and right e.g. &test + -- left and right e.g. |test if l_left_side is null then l_result := 0; else diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 4ed718777..8a497b9f1 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -488,6 +488,33 @@ end; begin ut.expect(l_expected).to_equal(l_actual); end; + + procedure valid_tag_expressions is + begin + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1&tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|!tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1&!tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1|!tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1&!tag2')); + + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1,tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('-tag1')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1,-tag2')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('-tag1,-tag2')); + + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('(!tag1|!tag2)|tag3')); + ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('(!tag1&!tag2)|(tag3&tag4)')); + + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|')); + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('&!tag2')); + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('!!tag1|!tag2')); + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1&!tag2|')); + ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('((!tag1|!tag2)|tag3')); + + end; end test_ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 4d83b5042..0f8545a45 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -157,5 +157,8 @@ create or replace package test_ut_utils is --%endcontext + --%test(Test to validate different type of expressions passed as tags) + procedure valid_tag_expressions; + end test_ut_utils; / From 69092f249427dccd39ff0df26848cbd873701ef9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 30 Mar 2023 20:07:27 +0100 Subject: [PATCH 140/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index d132d2085..a47004a3c 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 21b82ee41..8b6437299 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 9b423d5a8..02eabab07 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index d534857fa..aacb289f2 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index d6884ba2d..5e30a9fc6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 2c31a9a89..8db920ee7 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index d193e2c20..31b2fd442 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 63c0e36e9..b83fb78c3 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index f77717798..04b3db380 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index e237bf4ef..a7b0ae0a5 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 8fa525a69..2b436250e 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index d97d49464..37c22c882 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 934d07d72..00a74b288 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 9e16fd3e8..164c0cbc0 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index b3b0e338a..e92558e3d 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index e8e431980..978803b9a 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 47772937e..794e75070 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4094--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index f92fbc2b0..e79ce1fa6 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4094-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4105-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 2a0f99affc9b6b43dfa9e6f00c053c0eada27b14 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 31 Mar 2023 08:29:14 -0700 Subject: [PATCH 141/187] Extra changes and added tests --- source/core/ut_suite_cache_manager.pkb | 6 +- test/ut3_tester_helper/run_helper.pkb | 94 ++++++++++++++++++++++++++ test/ut3_user/api/test_ut_run.pkb | 33 +++++++++ test/ut3_user/api/test_ut_run.pks | 3 + 4 files changed, 133 insertions(+), 3 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index ff18deabf..ca7945c74 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -273,9 +273,9 @@ create or replace package body ut_suite_cache_manager is '(\(|\)|\||\!|\&)?([^|&!-()]+)(\(|\)|\||\!|\&)?', q'[\1q'<\2>' member of tags\3]'); --replace operands to XPath - l_tags := REGEXP_REPLACE(l_tags, '\|',' or '); - l_tags := REGEXP_REPLACE(l_tags , '\&',' and '); - l_tags := REGEXP_REPLACE(l_tags,q'[(\!)(q'<[^|&!-]+>')( member of tags)]','\2 not \3'); + l_tags := REPLACE(l_tags, '|',' or '); + l_tags := REPLACE(l_tags , '&',' and '); + l_tags := REGEXP_REPLACE(l_tags,q'[(\!)(q'<[^|&!]+?>')( member of tags)]','\2 not \3'); l_tags := '('||l_tags||')'; return l_tags; end; diff --git a/test/ut3_tester_helper/run_helper.pkb b/test/ut3_tester_helper/run_helper.pkb index a132f4943..c73564798 100644 --- a/test/ut3_tester_helper/run_helper.pkb +++ b/test/ut3_tester_helper/run_helper.pkb @@ -343,9 +343,100 @@ create or replace package body run_helper is end; end test_package_3; ]'; + + execute immediate q'[create or replace package test_tag_pkg_1 is + --%suite + --%tags(suite1,release_3_1_13,development,complex,end_to_end) + --%suitepath(suite1) + --%rollback(manual) + + --%test(Test1 from test_tag_pkg_1) + --%tags(test1,development,fast) + procedure test1; + + --%test(Test2 from test_tag_pkg_1) + --%tags(test2,production,slow,patch_3_1_13) + procedure test2; + + end test_tag_pkg_1; + ]'; + + execute immediate q'[create or replace package body test_tag_pkg_1 is + procedure test1 is + begin + dbms_output.put_line('test_tag_pkg_1.test1 executed'); + end; + procedure test2 is + begin + dbms_output.put_line('test_tag_pkg_1.test2 executed'); + end; + end test_tag_pkg_1; + ]'; + + execute immediate q'[create or replace package test_tag_pkg_2 is + --%suite + --%tags(suite2,release_3_1_12,development,simple) + --%suitepath(suite1.suite2) + --%rollback(manual) + + --%test(Test3 from test_tag_pkg_2) + --%tags(test3,development,fast) + procedure test3; + + --%test(Test4 from test_tag_pkg_1) + --%tags(test4,production,slow) + procedure test4; + + end test_tag_pkg_2; + ]'; + + execute immediate q'[create or replace package body test_tag_pkg_2 is + procedure test3 is + begin + dbms_output.put_line('test_tag_pkg_2.test3 executed'); + end; + procedure test4 is + begin + dbms_output.put_line('test_tag_pkg_2.test4 executed'); + end; + end test_tag_pkg_2; + ]'; + + execute immediate q'[create or replace package test_tag_pkg_3 is + --%suite + --%tags(suite3,release_3_1_13,production,simple,end_to_end) + --%suitepath(suite3) + --%rollback(manual) + + --%test(Test5 from test_tag_pkg_3) + --%tags(test5,release_3_1_13,production,patch_3_1_13) + procedure test5; + + --%test(Test6 from test_tag_pkg_3) + --%tags(test6,development,patch_3_1_14) + procedure test6; + + end test_tag_pkg_3; + ]'; + + execute immediate q'[create or replace package body test_tag_pkg_3 is + procedure test5 is + begin + dbms_output.put_line('test_tag_pkg_3.test5 executed'); + end; + procedure test6 is + begin + dbms_output.put_line('test_tag_pkg_3.test6 executed'); + end; + end test_tag_pkg_3; + ]'; + execute immediate q'[grant execute on test_package_1 to public]'; execute immediate q'[grant execute on test_package_2 to public]'; execute immediate q'[grant execute on test_package_3 to public]'; + execute immediate q'[grant execute on test_tag_pkg_1 to public]'; + execute immediate q'[grant execute on test_tag_pkg_2 to public]'; + execute immediate q'[grant execute on test_tag_pkg_3 to public]'; end; procedure drop_ut3_user_tests is @@ -354,6 +445,9 @@ create or replace package body run_helper is execute immediate q'[drop package test_package_1]'; execute immediate q'[drop package test_package_2]'; execute immediate q'[drop package test_package_3]'; + execute immediate q'[drop package test_tag_pkg_1]'; + execute immediate q'[drop package test_tag_pkg_2]'; + execute immediate q'[drop package test_tag_pkg_3]'; end; procedure create_test_suite is diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 6f6e229c8..ee420f310 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -1202,6 +1202,39 @@ procedure tag_exclude_run_fun_pth_lst_lg is ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_package_2.test2%executed%' ); end; + procedure tag_complex_expressions is + l_results ut3_develop.ut_varchar2_list; + begin + l_results := ut3_tester_helper.run_helper.run(a_tags => 'release_3_1_13&(fast|simple)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test5 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test6 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test3%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test4%executed%' ); + + l_results := ut3_tester_helper.run_helper.run(a_tags => 'release_3_1_13&(!patch_3_1_13&!patch_3_1_14)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_1.test1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test3%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test4%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3.test5%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3.test6%executed%' ); + + l_results := ut3_tester_helper.run_helper.run(a_tags => 'release_3_1_13&(patch_3_1_13&!slow)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test5 executed%' ); + + l_results := ut3_tester_helper.run_helper.run(a_tags => '(simple&end_to_end)|(development&fast)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_1.test1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_2.test3 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test5 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test6 executed%' ); + + l_results := ut3_tester_helper.run_helper.run(a_tags => '(!development&end_to_end)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test5 executed%' ); + + end; + procedure set_application_info is begin dbms_application_info.set_module( gc_module, gc_action ); diff --git a/test/ut3_user/api/test_ut_run.pks b/test/ut3_user/api/test_ut_run.pks index db02ee8f8..40e870fe4 100644 --- a/test/ut3_user/api/test_ut_run.pks +++ b/test/ut3_user/api/test_ut_run.pks @@ -259,6 +259,9 @@ create or replace package test_ut_run is --%test(Runs tests from given tags and exclude tags - Legacy Notation) procedure tag_include_exclude_run_fun_lg; + --%test(Runs tests suing complex expressions) + procedure tag_complex_expressions; + --%endcontext --%context(ut3_info context) From b30688cae39ea3917c92427528a5649022e76a4b Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 1 Apr 2023 08:31:13 -0700 Subject: [PATCH 142/187] Address sonar coverage issues. --- source/core/ut_suite_cache_manager.pkb | 14 ++++++++------ source/core/ut_utils.pkb | 14 ++++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index ca7945c74..2ccf20721 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -227,11 +227,10 @@ create or replace package body ut_suite_cache_manager is - = NOT we will perform a replace of that characters into new notation. - || = OR - && = AND - ^ = NOT + | = OR + & = AND + ! = NOT */ - --TODO: How do we prevent when old notation reach 4k an new will be longer? function replace_legacy_tag_notation(a_tags varchar2 ) return varchar2 is l_tags ut_varchar2_list := ut_utils.string_to_table(a_tags,','); @@ -331,8 +330,11 @@ with ) ) t where c.id = t.id and r_num = 1 ]'; - execute immediate l_sql bulk collect into l_suite_tags using a_suite_items; - return l_suite_tags; + execute immediate l_sql bulk collect into l_suite_tags using a_suite_items; + return l_suite_tags; + exception when others then + --If the dynamic SQL fails we will fall gracefully with meaningfull message + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Tag expression, causing error. If expression is correct please report error.'); end; /* diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 751971202..3747b029a 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -990,15 +990,21 @@ create or replace package body ut_utils is return l_result; end; + /* + Purpose of this function is to break down the tag expressions + We can separate operators on left and rigth side. + Left ones are AND and OR as they require an operator on left side to + be valid. Right side is NOT. + In each iteration we breakdown string into parts + + */ function valid_tag_expression(a_tags in varchar2) return number is - t_left_side ut_varchar2_list := ut_varchar2_list('|','&',','); - t_right_side ut_varchar2_list := ut_varchar2_list('!','-'); l_left_side_expression varchar2(100) := '[|&,]'; - l_left_side_regex varchar(400) := '([^|&,]*)[|&,](.*)'; + l_left_side_regex varchar2(400) := '([^|&,]*)[|&,](.*)'; l_left_side varchar2(4000); l_rigth_side_expression varchar2(100) := '[!-]'; - l_right_side_regex varchar(400) := '([!-])([^!-].*)'; + l_right_side_regex varchar2(400) := '([!-])([^!-].*)'; l_right_side varchar2(4000); l_tags varchar2(4000) := a_tags; From 0c41a0f22816b901e0b2adca5441e462feedb88a Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 1 Apr 2023 09:19:43 -0700 Subject: [PATCH 143/187] Adding tests covering exception of invalid tags --- source/core/ut_suite_cache_manager.pkb | 5 +---- test/ut3_user/api/test_ut_run.pkb | 30 +++++++++++++++++++++++++- test/ut3_user/api/test_ut_run.pks | 4 ++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 2ccf20721..152b5c0f9 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -331,10 +331,7 @@ with ) t where c.id = t.id and r_num = 1 ]'; execute immediate l_sql bulk collect into l_suite_tags using a_suite_items; - return l_suite_tags; - exception when others then - --If the dynamic SQL fails we will fall gracefully with meaningfull message - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Tag expression, causing error. If expression is correct please report error.'); + return l_suite_tags; end; /* diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index ee420f310..84dd11f9c 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -1223,16 +1223,44 @@ procedure tag_exclude_run_fun_pth_lst_lg is l_results := ut3_tester_helper.run_helper.run(a_tags => 'release_3_1_13&(patch_3_1_13&!slow)'); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test5 executed%' ); - + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test3%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test4%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3.test6%executed%' ); + l_results := ut3_tester_helper.run_helper.run(a_tags => '(simple&end_to_end)|(development&fast)'); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_1.test1 executed%' ); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_2.test3 executed%' ); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test5 executed%' ); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test6 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test4%executed%' ); l_results := ut3_tester_helper.run_helper.run(a_tags => '(!development&end_to_end)'); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%test_tag_pkg_3.test5 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test1%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_1.test2%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test3%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test4%executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3.test6%executed%' ); + + end; + + procedure invalid_tag_expression is + l_results ut3_develop.ut_varchar2_list; + begin + l_results := ut3_tester_helper.run_helper.run(a_tags => '(!!development&end_to_end)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_match('^\s*invalid_tag_expression \[[,\.0-9]+ sec\]\s*$','m'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); + + l_results := ut3_tester_helper.run_helper.run(a_tags => '(!development&&end_to_end)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_match('^\s*invalid_tag_expression \[[,\.0-9]+ sec\]\s*$','m'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); + l_results := ut3_tester_helper.run_helper.run(a_tags => '(!development&end_to_end|)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_match('^\s*invalid_tag_expression \[[,\.0-9]+ sec\]\s*$','m'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); end; procedure set_application_info is diff --git a/test/ut3_user/api/test_ut_run.pks b/test/ut3_user/api/test_ut_run.pks index 40e870fe4..c57788bff 100644 --- a/test/ut3_user/api/test_ut_run.pks +++ b/test/ut3_user/api/test_ut_run.pks @@ -262,6 +262,10 @@ create or replace package test_ut_run is --%test(Runs tests suing complex expressions) procedure tag_complex_expressions; + --%test(Testing invalid tag expression) + --%throws(-20219) + procedure invalid_tag_expression; + --%endcontext --%context(ut3_info context) From 543685dc94676110099af0b8af1a155918725cd5 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 1 Apr 2023 11:26:17 -0700 Subject: [PATCH 144/187] Removing that , we will not implement that, there is no benefit at the moment. --- docs/userguide/annotations.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index f3cf73d4d..4017521b5 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1662,8 +1662,6 @@ end ut_sample_test; Tag expressions are boolean expressions with the operators !, & and |. In addition, ( and ) can be used to adjust for operator precedence. -Two special expressions are supported, any() and none(), which select all tests with any tags at all, and all tests without any tags, respectively. These special expressions may be combined with other expressions just like normal tags. - | Operator | Meaning | | -------- | --------| | ! | not | From 0d3cfa166beccb14b19debffa99bb392f85d8bbb Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sat, 1 Apr 2023 11:30:00 -0700 Subject: [PATCH 145/187] Removing force --- source/core/types/ut_run.tps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/types/ut_run.tps b/source/core/types/ut_run.tps index 8ce80d2a1..1878a2d46 100644 --- a/source/core/types/ut_run.tps +++ b/source/core/types/ut_run.tps @@ -1,4 +1,4 @@ -create or replace type ut_run force under ut_suite_item ( +create or replace type ut_run under ut_suite_item ( /* utPLSQL - Version 3 Copyright 2016 - 2021 utPLSQL Project From 20e317742e00f5299b2abd2675160d4b2cc38b86 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 9 Apr 2023 18:47:21 -0700 Subject: [PATCH 146/187] Changing to use Dijkstra algorithm to parse infix notation into postfix ( Reverse Polish Notation). This allows us to more flexibility of using boolean expressions and not limited to flaky regex. --- source/api/ut_runner.pkb | 4 - source/core/types/ut_stack.tpb | 58 ++++++ source/core/types/ut_stack.tps | 26 +++ source/core/ut_suite_cache_manager.pkb | 21 +-- source/core/ut_utils.pkb | 245 ++++++++++++++++++++++++- source/core/ut_utils.pks | 25 +++ source/install.sql | 2 + test/ut3_user/api/test_ut_run.pkb | 2 +- 8 files changed, 363 insertions(+), 20 deletions(-) create mode 100644 source/core/types/ut_stack.tpb create mode 100644 source/core/types/ut_stack.tps diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index a2a69f464..3d4550cf9 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -95,10 +95,6 @@ create or replace package body ut_runner is ut_event_manager.trigger_event(ut_event_manager.gc_initialize); ut_event_manager.trigger_event(ut_event_manager.gc_debug, ut_run_info()); - if ut_utils.valid_tag_expression(l_tags) = 0 then - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); - end if; - if a_random_test_order_seed is not null then l_random_test_order_seed := a_random_test_order_seed; elsif a_random_test_order then diff --git a/source/core/types/ut_stack.tpb b/source/core/types/ut_stack.tpb new file mode 100644 index 000000000..a7f7ab0c2 --- /dev/null +++ b/source/core/types/ut_stack.tpb @@ -0,0 +1,58 @@ +create or replace type body ut_stack as + /* + utPLSQL - Version 3 + Copyright 2016 - 2021 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + constructor function ut_stack( self in out nocopy ut_stack) return self as result is + begin + self.tokens := ut_varchar2_list(); + self.top := 0; + return; + end ut_stack; + + member function peek(self in out nocopy ut_stack) return varchar2 is + l_token varchar2(32767); + begin + if self.tokens.count =0 or self.tokens is null then + l_token := null; + else + l_token := self.tokens(self.tokens.last); + end if; + return l_token; + end; + + member procedure push(self in out nocopy ut_stack, a_token varchar2) is + begin + self.tokens.extend; + self.tokens(self.tokens.last) := a_token; + self.top := self.tokens.count; + end push; + + member procedure pop(self in out nocopy ut_stack,a_cnt in integer default 1) is + begin + self.tokens.trim(a_cnt); + self.top := self.tokens.count; + end pop; + + member function pop(self in out nocopy ut_stack) return varchar2 is + l_token varchar2(32767) := self.tokens(self.tokens.last); + begin + self.pop(); + return l_token; + end; +end; +/ + diff --git a/source/core/types/ut_stack.tps b/source/core/types/ut_stack.tps new file mode 100644 index 000000000..9851b9cc5 --- /dev/null +++ b/source/core/types/ut_stack.tps @@ -0,0 +1,26 @@ +create or replace type ut_stack as object ( + top integer, + tokens ut_varchar2_list, + /* + utPLSQL - Version 3 + Copyright 2016 - 2021 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + constructor function ut_stack( self in out nocopy ut_stack) return self as result, + member function peek(self in out nocopy ut_stack) return varchar2, + member procedure push(self in out nocopy ut_stack, a_token varchar2), + member procedure pop(self in out nocopy ut_stack,a_cnt in integer default 1), + member function pop(self in out nocopy ut_stack) return varchar2 +) + diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 152b5c0f9..ae5460ef6 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -234,11 +234,11 @@ create or replace package body ut_suite_cache_manager is function replace_legacy_tag_notation(a_tags varchar2 ) return varchar2 is l_tags ut_varchar2_list := ut_utils.string_to_table(a_tags,','); - l_tags_include varchar2(2000); - l_tags_exclude varchar2(2000); + l_tags_include varchar2(4000); + l_tags_exclude varchar2(4000); l_return_tag varchar2(4000); begin - select listagg( t.column_value,' | ') + select listagg( t.column_value,'|') within group( order by column_value) into l_tags_include from table(l_tags) t @@ -268,15 +268,14 @@ create or replace package body ut_suite_cache_manager is if instr(l_tags,',') > 0 or instr(l_tags,'-') > 0 then l_tags := replace(replace_legacy_tag_notation(l_tags),' '); end if; - l_tags := REGEXP_REPLACE(l_tags, - '(\(|\)|\||\!|\&)?([^|&!-()]+)(\(|\)|\||\!|\&)?', - q'[\1q'<\2>' member of tags\3]'); - --replace operands to XPath + l_tags := ut_utils.convert_postfix_to_infix_where_sql(ut_utils.shunt_logical_expression(l_tags)); l_tags := REPLACE(l_tags, '|',' or '); - l_tags := REPLACE(l_tags , '&',' and '); - l_tags := REGEXP_REPLACE(l_tags,q'[(\!)(q'<[^|&!]+?>')( member of tags)]','\2 not \3'); - l_tags := '('||l_tags||')'; - return l_tags; + l_tags := REPLACE(l_tags ,'&',' and '); + l_tags := REPLACE(l_tags ,'!','not'); + return l_tags; + exception + when ut_utils.ex_invalid_tag_expression then + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); end; /* diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 3747b029a..c09c15221 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -24,6 +24,16 @@ create or replace package body ut_utils is gc_full_valid_xml_name constant varchar2(50) := '^([_a-zA-Z])([_a-zA-Z0-9\.-])*$'; gc_owner_hash constant integer(11) := dbms_utility.get_hash_value( ut_owner(), 0, power(2,31)-1); + /** + * Constants use in postfix and infix transformations + */ + gc_operators constant ut_varchar2_list := ut_varchar2_list('|','&','!'); + gc_unary_operator constant ut_varchar2_list := ut_varchar2_list('!'); -- right side associative operator + gc_binary_operator constant ut_varchar2_list := ut_varchar2_list('|','&'); -- left side associative operator + + type t_precedence_table is table of number index by varchar2(1); + g_precedence t_precedence_table; + function surround_with(a_value varchar2, a_quote_char varchar2) return varchar2 is begin return case when a_quote_char is not null then a_quote_char||a_value||a_quote_char else a_value end; @@ -999,12 +1009,12 @@ create or replace package body ut_utils is */ function valid_tag_expression(a_tags in varchar2) return number is - l_left_side_expression varchar2(100) := '[|&,]'; - l_left_side_regex varchar2(400) := '([^|&,]*)[|&,](.*)'; + l_left_side_expression varchar2(10) := '[|&,]'; + l_left_side_regex varchar2(50) := '([^|&,]*)[|&,](.*)'; l_left_side varchar2(4000); - l_rigth_side_expression varchar2(100) := '[!-]'; - l_right_side_regex varchar2(400) := '([!-])([^!-].*)'; + l_rigth_side_expression varchar2(10) := '[!-]'; + l_right_side_regex varchar2(50) := '([!-])([^!-].*)'; l_right_side varchar2(4000); l_tags varchar2(4000) := a_tags; @@ -1058,5 +1068,232 @@ create or replace package body ut_utils is return l_result; end; + procedure build_tag_expression_filter(a_tags in varchar2,a_expression_tab in out t_expression_tab,a_parent_id varchar2 default null) is + l_left_side_expression varchar2(10) := '[|&,]'; + l_left_side_regex varchar2(50) := '([^|&,]*)([|&,])(.*)'; + l_left_side varchar2(4000); + + l_rigth_side_expression varchar2(10) := '[!-]'; + l_right_side_regex varchar2(50) := '([!-])([^!-].*)'; + l_right_side varchar2(4000); + + l_tags varchar2(4000) := a_tags; + l_result number :=1; + l_expression_rec t_expression_rec; + + begin + if a_expression_tab is null then + a_expression_tab := t_expression_tab(); + end if; + + l_expression_rec.id := sys_guid(); + l_expression_rec.parent_id := a_parent_id; + + if instr(substr(l_tags,1,1),'(',1,1) + instr(substr(l_tags,-1,1),')',-1,1) = 2 then + + if regexp_count(l_tags,l_right_side_regex) = 1 then + l_expression_rec.negated :=1; + l_tags := trim (leading '!' from l_tags); + end if; + + l_expression_rec.left_bracket := 1; + l_tags := trim(leading '(' from l_tags); + l_expression_rec.right_bracket := 1; + l_tags := trim(trailing ')' from l_tags); + end if; + + + --Check if there are any left side operators for first in order from left to right + if regexp_count(l_tags,l_left_side_expression) > 0 then + --Extract left part of operator and remaining of string to right + + --if there are bracketc extract it and record it + + l_left_side := regexp_replace(l_tags,l_left_side_regex,'\1'); + l_expression_rec.log_operator := regexp_replace(l_tags,l_left_side_regex,'\2'); + l_right_side := regexp_replace(l_tags,l_left_side_regex,'\3'); + a_expression_tab.extend; + a_expression_tab(a_expression_tab.last) := l_expression_rec; + + build_tag_expression_filter(l_left_side,a_expression_tab,l_expression_rec.id); + build_tag_expression_filter(l_right_side,a_expression_tab,l_expression_rec.id); + + else + if instr(substr(l_tags,1,1),'(',1,1) + instr(substr(l_tags,-1,1),')',-1,1) = 2 then + + if regexp_count(l_tags,l_right_side_regex) = 1 then + l_expression_rec.negated :=1; + l_tags := trim (leading '!' from l_tags); + end if; + + l_expression_rec.left_bracket := 1; + l_tags := trim(leading '(' from l_tags); + l_expression_rec.right_bracket := 1; + l_tags := trim(trailing ')' from l_tags); + end if; + l_expression_rec.expression := l_tags; + a_expression_tab.extend; + a_expression_tab(a_expression_tab.last) := l_expression_rec; + end if; + + end; + + /* + https://stackoverflow.com/questions/29634992/shunting-yard-validate-expression + */ + function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list is + l_tags varchar2(32767) := a_tags; + l_operator_stack ut_stack := ut_stack(); + l_input_tokens ut_varchar2_list := ut_varchar2_list(); + l_rnp_tokens ut_varchar2_list := ut_varchar2_list(); + l_token varchar2(32767); + l_expect_operand boolean := true; + l_expect_operator boolean := false; + begin + --Tokenize a string into operators and tags + select regexp_substr(l_tags,'([^!()|&]+)|([!()|&])', 1, level) as string_parts + bulk collect into l_input_tokens + from dual connect by regexp_substr (l_tags, '([^!()|&]+)|([!()|&])', 1, level) is not null; + + --Exuecute modified shunting algorithm + for token in 1..l_input_tokens.count loop + l_token := l_input_tokens(token); + if (l_token member of gc_operators and l_token member of gc_binary_operator) then + if not(l_expect_operator) then + raise ex_invalid_tag_expression; + end if; + while l_operator_stack.top > 0 and (g_precedence(l_operator_stack.peek) > g_precedence(l_token)) loop + l_rnp_tokens.extend; + l_rnp_tokens(l_rnp_tokens.last) := l_operator_stack.pop; + end loop; + l_operator_stack.push(l_input_tokens(token)); + l_expect_operand := true; + l_expect_operator:= false; + elsif (l_token member of gc_operators and l_token member of gc_unary_operator) then + if not(l_expect_operand) then + raise ex_invalid_tag_expression; + end if; + l_operator_stack.push(l_input_tokens(token)); + l_expect_operand := true; + l_expect_operator:= false; + elsif l_token = '(' then + if not(l_expect_operand) then + raise ex_invalid_tag_expression; + end if; + l_operator_stack.push(l_input_tokens(token)); + l_expect_operand := true; + l_expect_operator:= false; + elsif l_token = ')' then + if not(l_expect_operator) then + raise ex_invalid_tag_expression; + end if; + while l_operator_stack.peek <> '(' loop + l_rnp_tokens.extend; + l_rnp_tokens(l_rnp_tokens.last) := l_operator_stack.pop; + end loop; + l_operator_stack.pop; --Pop the open bracket and discard it + l_expect_operand := false; + l_expect_operator:= true; + else + if not(l_expect_operand) then + raise ex_invalid_tag_expression; + end if; + l_rnp_tokens.extend; + l_rnp_tokens(l_rnp_tokens.last) :=l_token; + l_expect_operator := true; + l_expect_operand := false; + end if; + + end loop; + + while l_operator_stack.top > 0 loop + if l_operator_stack.peek in ('(',')') then + raise ex_invalid_tag_expression; + end if; + l_rnp_tokens.extend; + l_rnp_tokens(l_rnp_tokens.last):=l_operator_stack.pop; + end loop; + + return l_rnp_tokens; + end shunt_logical_expression; + + procedure shunt_logical_expression(a_tags in varchar2) is + a_postfix ut_varchar2_list; + begin + a_postfix := ut_utils.shunt_logical_expression(a_tags); + end shunt_logical_expression; + + function convert_postfix_to_infix(a_postfix_exp in ut_varchar2_list) + return varchar2 is + l_infix_stack ut_stack := ut_stack(); + l_right_side varchar2(32767); + l_left_side varchar2(32767); + l_infix_exp varchar2(32767); + begin + for i in 1..a_postfix_exp.count loop + --If token is operand but also single tag + if a_postfix_exp(i) not member of gc_operators then --its operand + l_infix_stack.push(a_postfix_exp(i)); + --If token is unary operator not + elsif a_postfix_exp(i) member of gc_unary_operator then + l_right_side := l_infix_stack.pop; + l_infix_exp := '('||a_postfix_exp(i)||l_right_side||')'; + l_infix_stack.push(l_infix_exp); + --If token is binary operator + elsif a_postfix_exp(i) member of gc_binary_operator then + l_right_side := l_infix_stack.pop; + l_left_side := l_infix_stack.pop; + l_infix_exp := '('||l_left_side||a_postfix_exp(i)||l_right_side||')'; + l_infix_stack.push(l_infix_exp); + else + null; + end if; + end loop; + + return l_infix_stack.pop; + end; + + function convert_postfix_to_infix_where_sql(a_postfix_exp in ut_varchar2_list) + return varchar2 is + l_infix_stack ut_stack := ut_stack(); + l_right_side varchar2(32767); + l_left_side varchar2(32767); + l_infix_exp varchar2(32767); + l_member_token varchar2(20) := ' member of tags'; + begin + for i in 1..a_postfix_exp.count loop + --If token is operand but also single tag + if regexp_count(a_postfix_exp(i),'[!()|&]') = 0 then + l_infix_stack.push(q'[']'||a_postfix_exp(i)||q'[']'||l_member_token); + --If token is operand but containing other expressions + elsif a_postfix_exp(i) not member of gc_operators then + l_infix_stack.push(a_postfix_exp(i)); + --If token is unary operator not + elsif a_postfix_exp(i) member of gc_unary_operator then + l_right_side := l_infix_stack.pop; + l_infix_exp := a_postfix_exp(i)||'('||l_right_side||')'; + l_infix_stack.push(l_infix_exp); + --If token is binary operator + elsif a_postfix_exp(i) member of gc_binary_operator then + l_right_side := l_infix_stack.pop; + l_left_side := l_infix_stack.pop; + l_infix_exp := '('||l_left_side||a_postfix_exp(i)||l_right_side||')'; + l_infix_stack.push(l_infix_exp); + else + null; + end if; + end loop; + + return l_infix_stack.pop; + end; + +begin + --Define operator precedence + g_precedence('!'):=4; + g_precedence('&'):=3; + g_precedence('|'):=2; + g_precedence(')'):=1; + g_precedence('('):=1; + end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index e84818cba..2212454f4 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -482,5 +482,30 @@ create or replace package ut_utils authid definer is */ function valid_tag_expression(a_tags in varchar2) return number; + /* + * Return number 1 or 0 if the list of tags is valid expression + */ + procedure build_tag_expression_filter(a_tags in varchar2,a_expression_tab in out t_expression_tab,a_parent_id varchar2 default null); + + /* + * Function that uses Dijkstra algorithm to parse mathematical and logical expression + * and return a list of elements in Reverse Polish Notation ( postfix ) + * As part of execution it will validate expression. + */ + function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list; + + procedure shunt_logical_expression(a_tags in varchar2); + + /* + * Function that converts postfix notation into infix + */ + function convert_postfix_to_infix(a_postfix_exp in ut_varchar2_list) return varchar2; + + /* + * Function that converts postfix notation into infix and creating a string of sql filter + * that checking a tags collections for tags according to posted logic. + */ + function convert_postfix_to_infix_where_sql(a_postfix_exp in ut_varchar2_list) return varchar2; + end ut_utils; / diff --git a/source/install.sql b/source/install.sql index 0873d6a1e..a54977f94 100644 --- a/source/install.sql +++ b/source/install.sql @@ -50,6 +50,8 @@ create or replace context &&ut3_owner._info using &&ut3_owner..ut_session_contex @@install_component.sql 'core/types/ut_key_value_pairs.tps' @@install_component.sql 'core/types/ut_reporter_info.tps' @@install_component.sql 'core/types/ut_reporters_info.tps' +@@install_component.sql 'core/types/ut_stack.tps' +@@install_component.sql 'core/types/ut_stack.tpb' @@install_component.sql 'core/ut_utils.pks' @@install_component.sql 'core/ut_metadata.pks' @@install_component.sql 'core/ut_savepoint_seq.sql' diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 84dd11f9c..7eb377f4b 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -1250,7 +1250,7 @@ procedure tag_exclude_run_fun_pth_lst_lg is procedure invalid_tag_expression is l_results ut3_develop.ut_varchar2_list; begin - l_results := ut3_tester_helper.run_helper.run(a_tags => '(!!development&end_to_end)'); + l_results := ut3_tester_helper.run_helper.run(a_tags => '(!development!&end_to_end)'); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_match('^\s*invalid_tag_expression \[[,\.0-9]+ sec\]\s*$','m'); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); From f51cc993be376e456758b73a21680591fa9130d9 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 9 Apr 2023 18:52:21 -0700 Subject: [PATCH 147/187] Missing slash at end of type --- source/core/types/ut_stack.tps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/types/ut_stack.tps b/source/core/types/ut_stack.tps index 9851b9cc5..7b8c145c2 100644 --- a/source/core/types/ut_stack.tps +++ b/source/core/types/ut_stack.tps @@ -23,4 +23,4 @@ create or replace type ut_stack as object ( member procedure pop(self in out nocopy ut_stack,a_cnt in integer default 1), member function pop(self in out nocopy ut_stack) return varchar2 ) - +/ \ No newline at end of file From 4b8e2ab124d7819b2a8a442b9fcd31d6d5d5666e Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 9 Apr 2023 21:26:13 -0700 Subject: [PATCH 148/187] Cleanup. Fix object name length. --- source/core/ut_suite_cache_manager.pkb | 2 +- source/core/ut_utils.pkb | 144 +------------------------ source/core/ut_utils.pks | 12 +-- 3 files changed, 5 insertions(+), 153 deletions(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index ae5460ef6..aea8c667e 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -268,7 +268,7 @@ create or replace package body ut_suite_cache_manager is if instr(l_tags,',') > 0 or instr(l_tags,'-') > 0 then l_tags := replace(replace_legacy_tag_notation(l_tags),' '); end if; - l_tags := ut_utils.convert_postfix_to_infix_where_sql(ut_utils.shunt_logical_expression(l_tags)); + l_tags := ut_utils.convert_postfix_to_infix(ut_utils.shunt_logical_expression(l_tags)); l_tags := REPLACE(l_tags, '|',' or '); l_tags := REPLACE(l_tags ,'&',' and '); l_tags := REPLACE(l_tags ,'!','not'); diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index c09c15221..028a0c756 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -1000,144 +1000,6 @@ create or replace package body ut_utils is return l_result; end; - /* - Purpose of this function is to break down the tag expressions - We can separate operators on left and rigth side. - Left ones are AND and OR as they require an operator on left side to - be valid. Right side is NOT. - In each iteration we breakdown string into parts - - */ - function valid_tag_expression(a_tags in varchar2) return number is - l_left_side_expression varchar2(10) := '[|&,]'; - l_left_side_regex varchar2(50) := '([^|&,]*)[|&,](.*)'; - l_left_side varchar2(4000); - - l_rigth_side_expression varchar2(10) := '[!-]'; - l_right_side_regex varchar2(50) := '([!-])([^!-].*)'; - l_right_side varchar2(4000); - - l_tags varchar2(4000) := a_tags; - l_result number :=1; - begin - --Validate that we have closed up all brackets - if regexp_count(l_tags,'\(') <> regexp_count(l_tags,'\)') then - l_result := 0; - end if; - - --Remove brackets as we dont evaluate expression only validate. - l_tags := replace(replace(l_tags,'('),')'); - - --Check if there are any left side operators for first in order from left to right - if regexp_count(l_tags,l_left_side_expression) > 0 then - --Extract left part of operator and remaining of string to right - l_left_side := regexp_replace(l_tags,l_left_side_regex,'\1'); - l_right_side := regexp_replace(l_tags,l_left_side_regex,'\2'); - - --If left side is null that means that we used left side operator without - -- left and right e.g. |test - if l_left_side is null then - l_result := 0; - else - --Extract right side from left side expression if there is any !- - --Remove first negation tag to see if there is double negation - l_left_side := regexp_replace(l_left_side,l_right_side_regex,'\2'); - end if; - - - --check that on right side there is no extra negation - if regexp_count(l_left_side,l_rigth_side_expression) > 0 then - l_result := 0; - end if; - - --Now process right side of string - if l_right_side is not null then - l_result := least(l_result,valid_tag_expression(l_right_side)); - else - l_result := 0; - end if; - else - --We just process single tag. - l_left_side := l_tags; - l_left_side := regexp_replace(l_left_side,l_right_side_regex,'\2'); - if regexp_count(l_left_side,l_rigth_side_expression) > 0 then - l_result := 0; - end if; - end if; - - return l_result; - end; - - procedure build_tag_expression_filter(a_tags in varchar2,a_expression_tab in out t_expression_tab,a_parent_id varchar2 default null) is - l_left_side_expression varchar2(10) := '[|&,]'; - l_left_side_regex varchar2(50) := '([^|&,]*)([|&,])(.*)'; - l_left_side varchar2(4000); - - l_rigth_side_expression varchar2(10) := '[!-]'; - l_right_side_regex varchar2(50) := '([!-])([^!-].*)'; - l_right_side varchar2(4000); - - l_tags varchar2(4000) := a_tags; - l_result number :=1; - l_expression_rec t_expression_rec; - - begin - if a_expression_tab is null then - a_expression_tab := t_expression_tab(); - end if; - - l_expression_rec.id := sys_guid(); - l_expression_rec.parent_id := a_parent_id; - - if instr(substr(l_tags,1,1),'(',1,1) + instr(substr(l_tags,-1,1),')',-1,1) = 2 then - - if regexp_count(l_tags,l_right_side_regex) = 1 then - l_expression_rec.negated :=1; - l_tags := trim (leading '!' from l_tags); - end if; - - l_expression_rec.left_bracket := 1; - l_tags := trim(leading '(' from l_tags); - l_expression_rec.right_bracket := 1; - l_tags := trim(trailing ')' from l_tags); - end if; - - - --Check if there are any left side operators for first in order from left to right - if regexp_count(l_tags,l_left_side_expression) > 0 then - --Extract left part of operator and remaining of string to right - - --if there are bracketc extract it and record it - - l_left_side := regexp_replace(l_tags,l_left_side_regex,'\1'); - l_expression_rec.log_operator := regexp_replace(l_tags,l_left_side_regex,'\2'); - l_right_side := regexp_replace(l_tags,l_left_side_regex,'\3'); - a_expression_tab.extend; - a_expression_tab(a_expression_tab.last) := l_expression_rec; - - build_tag_expression_filter(l_left_side,a_expression_tab,l_expression_rec.id); - build_tag_expression_filter(l_right_side,a_expression_tab,l_expression_rec.id); - - else - if instr(substr(l_tags,1,1),'(',1,1) + instr(substr(l_tags,-1,1),')',-1,1) = 2 then - - if regexp_count(l_tags,l_right_side_regex) = 1 then - l_expression_rec.negated :=1; - l_tags := trim (leading '!' from l_tags); - end if; - - l_expression_rec.left_bracket := 1; - l_tags := trim(leading '(' from l_tags); - l_expression_rec.right_bracket := 1; - l_tags := trim(trailing ')' from l_tags); - end if; - l_expression_rec.expression := l_tags; - a_expression_tab.extend; - a_expression_tab(a_expression_tab.last) := l_expression_rec; - end if; - - end; - /* https://stackoverflow.com/questions/29634992/shunting-yard-validate-expression */ @@ -1251,9 +1113,9 @@ create or replace package body ut_utils is end loop; return l_infix_stack.pop; - end; + end convert_postfix_to_infix; - function convert_postfix_to_infix_where_sql(a_postfix_exp in ut_varchar2_list) + function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) return varchar2 is l_infix_stack ut_stack := ut_stack(); l_right_side varchar2(32767); @@ -1285,7 +1147,7 @@ create or replace package body ut_utils is end loop; return l_infix_stack.pop; - end; + end conv_postfix_to_infix_sql; begin --Define operator precedence diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 2212454f4..4bc35466d 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -477,16 +477,6 @@ create or replace package ut_utils authid definer is */ function interval_to_text(a_interval yminterval_unconstrained) return varchar2; - /* - * Return number 1 or 0 if the list of tags is valid expression - */ - function valid_tag_expression(a_tags in varchar2) return number; - - /* - * Return number 1 or 0 if the list of tags is valid expression - */ - procedure build_tag_expression_filter(a_tags in varchar2,a_expression_tab in out t_expression_tab,a_parent_id varchar2 default null); - /* * Function that uses Dijkstra algorithm to parse mathematical and logical expression * and return a list of elements in Reverse Polish Notation ( postfix ) @@ -505,7 +495,7 @@ create or replace package ut_utils authid definer is * Function that converts postfix notation into infix and creating a string of sql filter * that checking a tags collections for tags according to posted logic. */ - function convert_postfix_to_infix_where_sql(a_postfix_exp in ut_varchar2_list) return varchar2; + function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) return varchar2; end ut_utils; / From 84e8684004ddbcc95318e24903fae9fd046bf12a Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 10 Apr 2023 13:29:07 -0700 Subject: [PATCH 149/187] Update tests after removed function --- test/ut3_tester/core/test_ut_utils.pkb | 27 -------------------------- test/ut3_tester/core/test_ut_utils.pks | 3 --- 2 files changed, 30 deletions(-) diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 8a497b9f1..ec7e4f403 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -489,32 +489,5 @@ end; ut.expect(l_expected).to_equal(l_actual); end; - procedure valid_tag_expressions is - begin - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1&tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|!tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1&!tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1|!tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1&!tag2')); - - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1,tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('-tag1')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1,-tag2')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('-tag1,-tag2')); - - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('(!tag1|!tag2)|tag3')); - ut.expect(1).to_equal(ut3_develop.ut_utils.valid_tag_expression('(!tag1&!tag2)|(tag3&tag4)')); - - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('tag1|')); - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('&!tag2')); - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('!!tag1|!tag2')); - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('!tag1&!tag2|')); - ut.expect(0).to_equal(ut3_develop.ut_utils.valid_tag_expression('((!tag1|!tag2)|tag3')); - - end; - end test_ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 0f8545a45..4d83b5042 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -157,8 +157,5 @@ create or replace package test_ut_utils is --%endcontext - --%test(Test to validate different type of expressions passed as tags) - procedure valid_tag_expressions; - end test_ut_utils; / From 2e7a766f6169d0ad104448166ff3d0c84280b3e3 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 10 Apr 2023 13:57:54 -0700 Subject: [PATCH 150/187] Tidy up tests --- source/core/ut_suite_cache_manager.pkb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index aea8c667e..a9153c7bd 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -268,7 +268,7 @@ create or replace package body ut_suite_cache_manager is if instr(l_tags,',') > 0 or instr(l_tags,'-') > 0 then l_tags := replace(replace_legacy_tag_notation(l_tags),' '); end if; - l_tags := ut_utils.convert_postfix_to_infix(ut_utils.shunt_logical_expression(l_tags)); + l_tags := ut_utils.conv_postfix_to_infix_sql(ut_utils.shunt_logical_expression(l_tags)); l_tags := REPLACE(l_tags, '|',' or '); l_tags := REPLACE(l_tags ,'&',' and '); l_tags := REPLACE(l_tags ,'!','not'); From cbdf83aee9491bd39e4bc06f74f72745fd5a6ef3 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 10 Apr 2023 14:02:57 -0700 Subject: [PATCH 151/187] Added ut_stack to uninstall --- source/uninstall_objects.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index 9531736b9..1e21f0f95 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -267,6 +267,8 @@ end; drop package ut_utils; +drop type ut_stack force; + drop sequence ut_savepoint_seq; drop type ut_documentation_reporter force; From 436eb5bed919df6b512688511a6d121a71c3a320 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 10 Apr 2023 18:00:07 -0700 Subject: [PATCH 152/187] Addressing test failures and sonar smells --- source/core/ut_utils.pkb | 51 +++++++++++++++----------- test/ut3_tester/core/test_ut_utils.pkb | 35 ++++++++++++++++++ test/ut3_tester/core/test_ut_utils.pks | 6 +++ 3 files changed, 71 insertions(+), 21 deletions(-) diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 028a0c756..ac5f25645 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -1011,15 +1011,17 @@ create or replace package body ut_utils is l_token varchar2(32767); l_expect_operand boolean := true; l_expect_operator boolean := false; + l_idx pls_integer; begin --Tokenize a string into operators and tags select regexp_substr(l_tags,'([^!()|&]+)|([!()|&])', 1, level) as string_parts bulk collect into l_input_tokens from dual connect by regexp_substr (l_tags, '([^!()|&]+)|([!()|&])', 1, level) is not null; + l_idx := l_input_tokens.first; --Exuecute modified shunting algorithm - for token in 1..l_input_tokens.count loop - l_token := l_input_tokens(token); + WHILE (l_idx is not null) loop + l_token := l_input_tokens(l_idx); if (l_token member of gc_operators and l_token member of gc_binary_operator) then if not(l_expect_operator) then raise ex_invalid_tag_expression; @@ -1028,21 +1030,21 @@ create or replace package body ut_utils is l_rnp_tokens.extend; l_rnp_tokens(l_rnp_tokens.last) := l_operator_stack.pop; end loop; - l_operator_stack.push(l_input_tokens(token)); + l_operator_stack.push(l_input_tokens(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif (l_token member of gc_operators and l_token member of gc_unary_operator) then if not(l_expect_operand) then raise ex_invalid_tag_expression; end if; - l_operator_stack.push(l_input_tokens(token)); + l_operator_stack.push(l_input_tokens(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif l_token = '(' then if not(l_expect_operand) then raise ex_invalid_tag_expression; end if; - l_operator_stack.push(l_input_tokens(token)); + l_operator_stack.push(l_input_tokens(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif l_token = ')' then @@ -1066,6 +1068,7 @@ create or replace package body ut_utils is l_expect_operand := false; end if; + l_idx := l_input_tokens.next(l_idx); end loop; while l_operator_stack.top > 0 loop @@ -1091,25 +1094,28 @@ create or replace package body ut_utils is l_right_side varchar2(32767); l_left_side varchar2(32767); l_infix_exp varchar2(32767); + l_idx pls_integer; begin - for i in 1..a_postfix_exp.count loop + l_idx := a_postfix_exp.first; + while (l_idx is not null) loop --If token is operand but also single tag - if a_postfix_exp(i) not member of gc_operators then --its operand - l_infix_stack.push(a_postfix_exp(i)); + if a_postfix_exp(l_idx) not member of gc_operators then --its operand + l_infix_stack.push(a_postfix_exp(l_idx)); --If token is unary operator not - elsif a_postfix_exp(i) member of gc_unary_operator then + elsif a_postfix_exp(l_idx) member of gc_unary_operator then l_right_side := l_infix_stack.pop; - l_infix_exp := '('||a_postfix_exp(i)||l_right_side||')'; + l_infix_exp := '('||a_postfix_exp(l_idx)||l_right_side||')'; l_infix_stack.push(l_infix_exp); --If token is binary operator - elsif a_postfix_exp(i) member of gc_binary_operator then + elsif a_postfix_exp(l_idx) member of gc_binary_operator then l_right_side := l_infix_stack.pop; l_left_side := l_infix_stack.pop; - l_infix_exp := '('||l_left_side||a_postfix_exp(i)||l_right_side||')'; + l_infix_exp := '('||l_left_side||a_postfix_exp(l_idx)||l_right_side||')'; l_infix_stack.push(l_infix_exp); else null; end if; + l_idx := a_postfix_exp.next(l_idx); end loop; return l_infix_stack.pop; @@ -1122,28 +1128,31 @@ create or replace package body ut_utils is l_left_side varchar2(32767); l_infix_exp varchar2(32767); l_member_token varchar2(20) := ' member of tags'; + l_idx pls_integer; begin - for i in 1..a_postfix_exp.count loop + l_idx := a_postfix_exp.first; + while ( l_idx is not null) loop --If token is operand but also single tag - if regexp_count(a_postfix_exp(i),'[!()|&]') = 0 then - l_infix_stack.push(q'[']'||a_postfix_exp(i)||q'[']'||l_member_token); + if regexp_count(a_postfix_exp(l_idx),'[!()|&]') = 0 then + l_infix_stack.push(q'[']'||a_postfix_exp(l_idx)||q'[']'||l_member_token); --If token is operand but containing other expressions - elsif a_postfix_exp(i) not member of gc_operators then - l_infix_stack.push(a_postfix_exp(i)); + elsif a_postfix_exp(l_idx) not member of gc_operators then + l_infix_stack.push(a_postfix_exp(l_idx)); --If token is unary operator not - elsif a_postfix_exp(i) member of gc_unary_operator then + elsif a_postfix_exp(l_idx) member of gc_unary_operator then l_right_side := l_infix_stack.pop; - l_infix_exp := a_postfix_exp(i)||'('||l_right_side||')'; + l_infix_exp := a_postfix_exp(l_idx)||'('||l_right_side||')'; l_infix_stack.push(l_infix_exp); --If token is binary operator - elsif a_postfix_exp(i) member of gc_binary_operator then + elsif a_postfix_exp(l_idx) member of gc_binary_operator then l_right_side := l_infix_stack.pop; l_left_side := l_infix_stack.pop; - l_infix_exp := '('||l_left_side||a_postfix_exp(i)||l_right_side||')'; + l_infix_exp := '('||l_left_side||a_postfix_exp(l_idx)||l_right_side||')'; l_infix_stack.push(l_infix_exp); else null; end if; + l_idx := a_postfix_exp.next(l_idx); end loop; return l_infix_stack.pop; diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index ec7e4f403..1f64c621e 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -489,5 +489,40 @@ end; ut.expect(l_expected).to_equal(l_actual); end; + + procedure test_conversion_to_rpn is + l_postfix ut3_develop.ut_varchar2_list; + l_postfix_string varchar2(4000); + begin + l_postfix := ut3_develop.ut_utils.shunt_logical_expression('A'); + l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); + ut.expect(l_postfix_string).to_equal('A'); + + l_postfix := ut3_develop.ut_utils.shunt_logical_expression('A|B'); + l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); + ut.expect(l_postfix_string).to_equal('AB|'); + + l_postfix := ut3_develop.ut_utils.shunt_logical_expression('(a|b)|c&d'); + l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); + ut.expect(l_postfix_string).to_equal('ab|cd&|'); + end; + + procedure test_conversion_from_rpn_to_infix is + l_postfix_rpn ut3_develop.ut_varchar2_list; + l_infix_string varchar2(4000); + begin + l_postfix_rpn := ut3_develop.ut_varchar2_list('A'); + l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); + ut.expect(l_infix_string).to_equal('A'); + + l_postfix_rpn := ut3_develop.ut_varchar2_list('A','B','|'); + l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); + ut.expect(l_infix_string).to_equal('(A|B)'); + + l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','|','c','d','&','|'); + l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); + ut.expect(l_infix_string).to_equal('((a|b)|(c&d))'); + end; + end test_ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 4d83b5042..7bfd9b36e 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -156,6 +156,12 @@ create or replace package test_ut_utils is --%endcontext + + --%test( Test conversion of expression into Reverse Polish Notation) + procedure test_conversion_to_rpn; + + --%test( Test conversion of expression from Reverse Polish Notation into infix) + procedure test_conversion_from_rpn_to_infix; end test_ut_utils; / From 3d77514448e9720ad11589343d171723ad8f1c72 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 10 Apr 2023 18:08:42 -0700 Subject: [PATCH 153/187] Update name --- test/ut3_tester/core/test_ut_utils.pkb | 2 +- test/ut3_tester/core/test_ut_utils.pks | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 1f64c621e..126ada89c 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -507,7 +507,7 @@ end; ut.expect(l_postfix_string).to_equal('ab|cd&|'); end; - procedure test_conversion_from_rpn_to_infix is + procedure test_conv_from_rpn_to_infix is l_postfix_rpn ut3_develop.ut_varchar2_list; l_infix_string varchar2(4000); begin diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 7bfd9b36e..6d11f65d1 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -161,7 +161,7 @@ create or replace package test_ut_utils is procedure test_conversion_to_rpn; --%test( Test conversion of expression from Reverse Polish Notation into infix) - procedure test_conversion_from_rpn_to_infix; + procedure test_conv_from_rpn_to_infix; end test_ut_utils; / From bf6959fc63c4c36ff24f62d28e8a5b1d6b323ce4 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 10 Apr 2023 20:39:25 -0700 Subject: [PATCH 154/187] Update tests and code --- source/core/ut_utils.pkb | 30 +++++++++++--------------- source/core/ut_utils.pks | 7 ++++-- test/ut3_tester/core/test_ut_utils.pkb | 29 +++++++++++++++++++++++-- test/ut3_tester/core/test_ut_utils.pks | 3 +++ test/ut3_user/api/test_ut_run.pkb | 15 ++++++++++++- 5 files changed, 62 insertions(+), 22 deletions(-) diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index ac5f25645..1c99a3a42 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -1000,24 +1000,30 @@ create or replace package body ut_utils is return l_result; end; + function tokenize_tags_string(a_tags in varchar2) return ut_varchar2_list is + l_tags_tokens ut_varchar2_list := ut_varchar2_list(); + begin + --Tokenize a string into operators and tags + select regexp_substr(a_tags,'([^!()|&]+)|([!()|&])', 1, level) as string_parts + bulk collect into l_tags_tokens + from dual connect by regexp_substr (a_tags, '([^!()|&]+)|([!()|&])', 1, level) is not null; + + return l_tags_tokens; + end; + /* https://stackoverflow.com/questions/29634992/shunting-yard-validate-expression */ function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list is l_tags varchar2(32767) := a_tags; l_operator_stack ut_stack := ut_stack(); - l_input_tokens ut_varchar2_list := ut_varchar2_list(); + l_input_tokens ut_varchar2_list := tokenize_tags_string(a_tags); l_rnp_tokens ut_varchar2_list := ut_varchar2_list(); l_token varchar2(32767); l_expect_operand boolean := true; l_expect_operator boolean := false; l_idx pls_integer; begin - --Tokenize a string into operators and tags - select regexp_substr(l_tags,'([^!()|&]+)|([!()|&])', 1, level) as string_parts - bulk collect into l_input_tokens - from dual connect by regexp_substr (l_tags, '([^!()|&]+)|([!()|&])', 1, level) is not null; - l_idx := l_input_tokens.first; --Exuecute modified shunting algorithm WHILE (l_idx is not null) loop @@ -1071,7 +1077,7 @@ create or replace package body ut_utils is l_idx := l_input_tokens.next(l_idx); end loop; - while l_operator_stack.top > 0 loop + while l_operator_stack.peek is not null loop if l_operator_stack.peek in ('(',')') then raise ex_invalid_tag_expression; end if; @@ -1082,12 +1088,6 @@ create or replace package body ut_utils is return l_rnp_tokens; end shunt_logical_expression; - procedure shunt_logical_expression(a_tags in varchar2) is - a_postfix ut_varchar2_list; - begin - a_postfix := ut_utils.shunt_logical_expression(a_tags); - end shunt_logical_expression; - function convert_postfix_to_infix(a_postfix_exp in ut_varchar2_list) return varchar2 is l_infix_stack ut_stack := ut_stack(); @@ -1112,8 +1112,6 @@ create or replace package body ut_utils is l_left_side := l_infix_stack.pop; l_infix_exp := '('||l_left_side||a_postfix_exp(l_idx)||l_right_side||')'; l_infix_stack.push(l_infix_exp); - else - null; end if; l_idx := a_postfix_exp.next(l_idx); end loop; @@ -1149,8 +1147,6 @@ create or replace package body ut_utils is l_left_side := l_infix_stack.pop; l_infix_exp := '('||l_left_side||a_postfix_exp(l_idx)||l_right_side||')'; l_infix_stack.push(l_infix_exp); - else - null; end if; l_idx := a_postfix_exp.next(l_idx); end loop; diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 4bc35466d..67b09b2f9 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -476,6 +476,11 @@ create or replace package ut_utils authid definer is * Return value of interval in plain english */ function interval_to_text(a_interval yminterval_unconstrained) return varchar2; + + /* + * Return table of tokens character by character + */ + function tokenize_tags_string(a_tags in varchar2) return ut_varchar2_list; /* * Function that uses Dijkstra algorithm to parse mathematical and logical expression @@ -484,8 +489,6 @@ create or replace package ut_utils authid definer is */ function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list; - procedure shunt_logical_expression(a_tags in varchar2); - /* * Function that converts postfix notation into infix */ diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 126ada89c..22733c4ce 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -504,7 +504,11 @@ end; l_postfix := ut3_develop.ut_utils.shunt_logical_expression('(a|b)|c&d'); l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); - ut.expect(l_postfix_string).to_equal('ab|cd&|'); + ut.expect(l_postfix_string).to_equal('ab|cd&|'); + + l_postfix := ut3_develop.ut_utils.shunt_logical_expression('!a|b'); + l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); + ut.expect(l_postfix_string).to_equal('a!b|'); end; procedure test_conv_from_rpn_to_infix is @@ -521,7 +525,28 @@ end; l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','|','c','d','&','|'); l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); - ut.expect(l_infix_string).to_equal('((a|b)|(c&d))'); + ut.expect(l_infix_string).to_equal('((a|b)|(c&d))'); + + l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','!','|'); + l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); + ut.expect(l_infix_string).to_equal('(a|(!b))'); + end; + + procedure conv_from_rpn_to_sql_filter is + l_postfix_rpn ut3_develop.ut_varchar2_list; + l_infix_string varchar2(4000); + begin + l_postfix_rpn := ut3_develop.ut_varchar2_list('A'); + l_infix_string := ut3_develop.ut_utils.conv_postfix_to_infix_sql(l_postfix_rpn); + ut.expect(l_infix_string).to_equal(q'['A' member of tags]'); + + l_postfix_rpn := ut3_develop.ut_varchar2_list('A','B','|'); + l_infix_string := ut3_develop.ut_utils.conv_postfix_to_infix_sql(l_postfix_rpn); + ut.expect(l_infix_string).to_equal(q'[('A' member of tags|'B' member of tags)]'); + + l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','!','|'); + l_infix_string := ut3_develop.ut_utils.conv_postfix_to_infix_sql(l_postfix_rpn); + ut.expect(l_infix_string).to_equal(q'[('a' member of tags|!('b' member of tags))]'); end; end test_ut_utils; diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 6d11f65d1..1561e1136 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -163,5 +163,8 @@ create or replace package test_ut_utils is --%test( Test conversion of expression from Reverse Polish Notation into infix) procedure test_conv_from_rpn_to_infix; + --%test( Test conversion of expression from Reverse Polish Notation into custom where filter for SQL) + procedure conv_from_rpn_to_sql_filter; + end test_ut_utils; / diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 7eb377f4b..25b50343e 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -1260,7 +1260,20 @@ procedure tag_exclude_run_fun_pth_lst_lg is l_results := ut3_tester_helper.run_helper.run(a_tags => '(!development&end_to_end|)'); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_match('^\s*invalid_tag_expression \[[,\.0-9]+ sec\]\s*$','m'); - ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); + + l_results := ut3_tester_helper.run_helper.run(a_tags => '(!development&!!end_to_end)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_match('^\s*invalid_tag_expression \[[,\.0-9]+ sec\]\s*$','m'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); + + l_results := ut3_tester_helper.run_helper.run(a_tags => '(&development&end_to_end)'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_match('^\s*invalid_tag_expression \[[,\.0-9]+ sec\]\s*$','m'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); + + l_results := ut3_tester_helper.run_helper.run(a_tags => '(development|end_to_end))'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_match('^\s*invalid_tag_expression \[[,\.0-9]+ sec\]\s*$','m'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like('%(FAILED -%'); + end; procedure set_application_info is From d8233ff6587f81c0a0a6430a4f33747bc2723983 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 11 Apr 2023 20:33:04 -0700 Subject: [PATCH 155/187] fixing typo in docs --- docs/userguide/annotations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 4017521b5..8e5a5d1ca 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1684,7 +1684,7 @@ Execution of the test is done by using the parameter `a_tags` with tag expressio ```sql linenums="1" -select * from table(ut.run(a_tags => 'fast||!complex')); +select * from table(ut.run(a_tags => 'fast|!complex')); ``` The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` because a suite meet expression condition. From bd860f602d458575d00010834e5ca28058ec09cb Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 11 Apr 2023 20:55:34 -0700 Subject: [PATCH 156/187] Removed unused variable --- source/core/ut_utils.pkb | 1 - 1 file changed, 1 deletion(-) diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 1c99a3a42..a8528fa86 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -1015,7 +1015,6 @@ create or replace package body ut_utils is https://stackoverflow.com/questions/29634992/shunting-yard-validate-expression */ function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list is - l_tags varchar2(32767) := a_tags; l_operator_stack ut_stack := ut_stack(); l_input_tokens ut_varchar2_list := tokenize_tags_string(a_tags); l_rnp_tokens ut_varchar2_list := ut_varchar2_list(); From e6a6a4cbf108b44932fb114c07e2d18f62ee687f Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 12 Apr 2023 19:54:56 +0300 Subject: [PATCH 157/187] Improvements to teamcity reporter (used by DataGrip and IntelliJ - JetBrains IDEs) The reporter will now report all errors and all failed expectations. The test description will be used instead of test name. --- source/reporters/ut_teamcity_reporter.tpb | 33 +++++++++------- .../reporters/ut_teamcity_reporter_helper.pkb | 2 - .../reporters/test_teamcity_reporter.pkb | 39 +++++++++++++++++-- .../reporters/test_teamcity_reporter.pks | 3 ++ 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/source/reporters/ut_teamcity_reporter.tpb b/source/reporters/ut_teamcity_reporter.tpb index 95bea32b8..e05dc994f 100644 --- a/source/reporters/ut_teamcity_reporter.tpb +++ b/source/reporters/ut_teamcity_reporter.tpb @@ -108,23 +108,28 @@ create or replace type body ut_teamcity_reporter is ut_teamcity_reporter_helper.test_failed( a_test_name => l_test_full_name, a_msg => 'Error occured', - a_details => - trim(l_std_err_msg) - || case when a_test.failed_expectations is not null - and a_test.failed_expectations.count>0 - then a_test.failed_expectations(1).message end + a_details => trim(l_std_err_msg) ) ); + for i in 1 .. a_test.failed_expectations.count loop + ut_utils.append_to_list( + l_results, + ut_teamcity_reporter_helper.test_failed( + a_test_name => l_test_full_name, + a_msg => a_test.failed_expectations(i).description, + a_details => a_test.failed_expectations(i).message ) + ); + end loop; elsif a_test.failed_expectations is not null and a_test.failed_expectations.count > 0 then - -- Teamcity supports only a single failure message - - ut_utils.append_to_list( - l_results, - ut_teamcity_reporter_helper.test_failed( - a_test_name => l_test_full_name, - a_msg => a_test.failed_expectations(a_test.failed_expectations.first).description, - a_details => a_test.failed_expectations(a_test.failed_expectations.first).message ) - ); + for i in 1 .. a_test.failed_expectations.count loop + ut_utils.append_to_list( + l_results, + ut_teamcity_reporter_helper.test_failed( + a_test_name => l_test_full_name, + a_msg => a_test.failed_expectations(i).description, + a_details => a_test.failed_expectations(i).message ) + ); + end loop; elsif a_test.result = ut_utils.gc_failure then ut_utils.append_to_list( l_results, diff --git a/source/reporters/ut_teamcity_reporter_helper.pkb b/source/reporters/ut_teamcity_reporter_helper.pkb index 84a9d19e8..1633d10aa 100644 --- a/source/reporters/ut_teamcity_reporter_helper.pkb +++ b/source/reporters/ut_teamcity_reporter_helper.pkb @@ -73,8 +73,6 @@ create or replace package body ut_teamcity_reporter_helper is 'true' when false then 'false' - else - null end; l_props('flowId') := a_flow_id; return message('testStarted', l_props); diff --git a/test/ut3_user/reporters/test_teamcity_reporter.pkb b/test/ut3_user/reporters/test_teamcity_reporter.pkb index ff550e488..cf7a925a1 100644 --- a/test/ut3_user/reporters/test_teamcity_reporter.pkb +++ b/test/ut3_user/reporters/test_teamcity_reporter.pkb @@ -31,12 +31,26 @@ create or replace package body test_teamcity_reporter as end; end;]'; + execute immediate q'[create or replace package check_multiple_failures is + --%suite + + --%test + procedure multi_failure; + end;]'; + execute immediate q'[create or replace package body check_multiple_failures is + procedure multi_failure is + begin + ut3_develop.ut.expect(1).to_be_null; + ut3_develop.ut.expect(2).to_equal(1); + ut3_develop.ut.expect('Bad').to_equal('Good'); + end; + end;]'; + end; procedure report_produces_expected_out is l_output_data ut3_develop.ut_varchar2_list; - l_output clob; l_expected varchar2(32767); begin l_expected := q'{%##teamcity[testSuiteStarted timestamp='%' name='org'] @@ -84,7 +98,6 @@ create or replace package body test_teamcity_reporter as procedure escape_special_chars is l_output_data ut3_develop.ut_varchar2_list; - l_output clob; l_expected varchar2(32767); begin l_expected := q'{%##teamcity[testSuiteStarted timestamp='%' name='A suite with |'quote|''] @@ -103,7 +116,6 @@ create or replace package body test_teamcity_reporter as procedure trims_long_output is l_output_data ut3_develop.ut_varchar2_list; - l_output clob; l_expected varchar2(32767); begin l_expected := q'{%##teamcity[testSuiteStarted timestamp='%' name='check_trims_long_output'] @@ -120,11 +132,32 @@ create or replace package body test_teamcity_reporter as ut.expect(ut3_tester_helper.main_helper.table_to_clob(l_output_data)).to_be_like(l_expected); end; + procedure report_mutiple_expectations is + l_output_data ut3_develop.ut_varchar2_list; + l_expected varchar2(32767); + begin + l_expected := q'{%##teamcity[testSuiteStarted timestamp='%' name='check_multiple_failures'] +%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.check_multiple_failures.multi_failure'] +%##teamcity[testFailed timestamp='%' details='Actual: 1 (number) was expected to be null' name='ut3_user.check_multiple_failures.multi_failure'] +%##teamcity[testFailed timestamp='%' details='Actual: 2 (number) was expected to equal: 1 (number)' name='ut3_user.check_multiple_failures.multi_failure'] +%##teamcity[testFailed timestamp='%' details='Actual: |'Bad|' (varchar2) was expected to equal: |'Good|' (varchar2)' name='ut3_user.check_multiple_failures.multi_failure'] +%##teamcity[testFinished timestamp='%' duration='%' name='ut3_user.check_multiple_failures.multi_failure'] +%##teamcity[testSuiteFinished timestamp='%' name='check_multiple_failures']}'; + --act + select * + bulk collect into l_output_data + from table(ut3_develop.ut.run('check_multiple_failures',ut3_develop.ut_teamcity_reporter())); + + --assert + ut.expect(ut3_tester_helper.main_helper.table_to_clob(l_output_data)).to_be_like(l_expected); + end; + procedure remove_test_package is pragma autonomous_transaction; begin execute immediate 'drop package check_escape_special_chars'; execute immediate 'drop package check_trims_long_output'; + execute immediate 'drop package check_multiple_failures'; end; end; diff --git a/test/ut3_user/reporters/test_teamcity_reporter.pks b/test/ut3_user/reporters/test_teamcity_reporter.pks index f849751f1..30ae7e26b 100644 --- a/test/ut3_user/reporters/test_teamcity_reporter.pks +++ b/test/ut3_user/reporters/test_teamcity_reporter.pks @@ -15,6 +15,9 @@ create or replace package test_teamcity_reporter as --%test(Trims output so it fits into 4000 chars) procedure trims_long_output; + --%test(Reports failures on multiple expectations) + procedure report_mutiple_expectations; + --%afterall procedure remove_test_package; From 0497dcfadcac637d186fdbc0aa36338d178f597d Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 12 Apr 2023 20:02:14 +0300 Subject: [PATCH 158/187] Adding Oracle 23-free-developer-edition --- .github/workflows/build.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ec37efe2..c2fe3971e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,6 +58,11 @@ jobs: oracle-sid: 'XE' oracle-version: "gvenzl/oracle-xe:21-slim" oracle-base: '/opt/oracle' + - id: 7 + db_version_name: '23free' + oracle-sid: 'FREEPDB1' + oracle-version: "gvenzl/oracle-free:23-slim" + oracle-base: '/opt/oracle' services: html_checker: From 55a2ecfcb73ff6389058423f41adf9e20279fc1c Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Wed, 12 Apr 2023 21:00:57 +0300 Subject: [PATCH 159/187] Adjusted tests for ORacle 23c (change of error message for ORA-06502) --- test/ut3_user/reporters/test_documentation_reporter.pkb | 2 +- test/ut3_user/reporters/test_teamcity_reporter.pkb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/ut3_user/reporters/test_documentation_reporter.pkb b/test/ut3_user/reporters/test_documentation_reporter.pkb index 6ace70c49..2a05679ff 100644 --- a/test/ut3_user/reporters/test_documentation_reporter.pkb +++ b/test/ut3_user/reporters/test_documentation_reporter.pkb @@ -37,7 +37,7 @@ Failures: % % 2) erroring_test - ORA-06502: PL/SQL: numeric or value error: character to number conversion error + ORA-06502: PL/SQL: %: character to number conversion error ORA-06512: at "UT3_USER.TEST_REPORTERS", line 44% ORA-06512: at line 6 Finished in % seconds diff --git a/test/ut3_user/reporters/test_teamcity_reporter.pkb b/test/ut3_user/reporters/test_teamcity_reporter.pkb index cf7a925a1..7c4c1e513 100644 --- a/test/ut3_user/reporters/test_teamcity_reporter.pkb +++ b/test/ut3_user/reporters/test_teamcity_reporter.pkb @@ -77,8 +77,8 @@ create or replace package body test_teamcity_reporter as -%##teamcity[testStdErr timestamp='%' name='ut3_user.test_reporters.erroring_test' out='Test exception:|nORA-06502: PL/SQL: numeric or value error: character to number conversion error|nORA-06512: at "UT3_USER.TEST_REPORTERS", line %|nORA-06512: at %|n'] -%##teamcity[testFailed timestamp='%' details='Test exception:|nORA-06502: PL/SQL: numeric or value error: character to number conversion error|nORA-06512: at "UT3_USER.TEST_REPORTERS", line %|nORA-06512: at %|n' message='Error occured' name='ut3_user.test_reporters.erroring_test'] +%##teamcity[testStdErr timestamp='%' name='ut3_user.test_reporters.erroring_test' out='Test exception:|nORA-06502: PL/SQL: %: character to number conversion error|nORA-06512: at "UT3_USER.TEST_REPORTERS", line %|nORA-06512: at %|n'] +%##teamcity[testFailed timestamp='%' details='Test exception:|nORA-06502: PL/SQL: %: character to number conversion error|nORA-06512: at "UT3_USER.TEST_REPORTERS", line %|nORA-06512: at %|n' message='Error occured' name='ut3_user.test_reporters.erroring_test'] %##teamcity[testFinished timestamp='%' duration='%' name='ut3_user.test_reporters.erroring_test'] %##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.test_reporters.disabled_test'] %##teamcity[testIgnored timestamp='%' name='ut3_user.test_reporters.disabled_test'] From 313d5e9019f1253cc222821c802a11c8cdd7ed1a Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 12 Apr 2023 18:40:28 -0700 Subject: [PATCH 160/187] Stage 1 Resolving PR comments --- source/api/ut_runner.pkb | 8 ++-- source/core/types/ut_stack.tpb | 2 +- source/core/types/ut_stack.tps | 2 +- source/core/ut_suite_builder.pkb | 2 +- source/core/ut_suite_cache_manager.pkb | 62 +++++++++++++------------- source/core/ut_utils.pkb | 55 +++++------------------ source/core/ut_utils.pks | 5 --- test/ut3_tester/core/test_ut_utils.pkb | 21 --------- test/ut3_tester/core/test_ut_utils.pks | 3 -- 9 files changed, 50 insertions(+), 110 deletions(-) diff --git a/source/api/ut_runner.pkb b/source/api/ut_runner.pkb index 3d4550cf9..3ec2a5393 100644 --- a/source/api/ut_runner.pkb +++ b/source/api/ut_runner.pkb @@ -78,9 +78,7 @@ create or replace package body ut_runner is l_run ut_run; l_coverage_schema_names ut_varchar2_rows; l_paths ut_varchar2_list; - l_random_test_order_seed positive; - l_tags varchar2(4000) := a_tags; - + l_random_test_order_seed positive; begin ut_event_manager.initialize(); if a_reporters is not empty then @@ -135,10 +133,10 @@ create or replace package body ut_runner is a_test_file_mappings => set(a_test_file_mappings), a_client_character_set => a_client_character_set, a_random_test_order_seed => l_random_test_order_seed, - a_run_tags => l_tags + a_run_tags => a_tags ); - ut_suite_manager.configure_execution_by_path(l_paths, l_run.items, l_random_test_order_seed, l_tags); + ut_suite_manager.configure_execution_by_path(l_paths, l_run.items, l_random_test_order_seed, a_tags); if a_force_manual_rollback then l_run.set_rollback_type( a_rollback_type => ut_utils.gc_rollback_manual, a_force => true ); end if; diff --git a/source/core/types/ut_stack.tpb b/source/core/types/ut_stack.tpb index a7f7ab0c2..b5f4e8747 100644 --- a/source/core/types/ut_stack.tpb +++ b/source/core/types/ut_stack.tpb @@ -1,7 +1,7 @@ create or replace type body ut_stack as /* utPLSQL - Version 3 - Copyright 2016 - 2021 utPLSQL Project + Copyright 2016 - 2023 utPLSQL Project Licensed under the Apache License, Version 2.0 (the "License"): you may not use this file except in compliance with the License. diff --git a/source/core/types/ut_stack.tps b/source/core/types/ut_stack.tps index 7b8c145c2..23112fdde 100644 --- a/source/core/types/ut_stack.tps +++ b/source/core/types/ut_stack.tps @@ -3,7 +3,7 @@ create or replace type ut_stack as object ( tokens ut_varchar2_list, /* utPLSQL - Version 3 - Copyright 2016 - 2021 utPLSQL Project + Copyright 2016 - 2023 utPLSQL Project Licensed under the Apache License, Version 2.0 (the "License"): you may not use this file except in compliance with the License. diff --git a/source/core/ut_suite_builder.pkb b/source/core/ut_suite_builder.pkb index 4aa2ff915..ebb113370 100644 --- a/source/core/ut_suite_builder.pkb +++ b/source/core/ut_suite_builder.pkb @@ -205,7 +205,7 @@ create or replace package body ut_suite_builder is l_tag_items := ut_utils.trim_list_elements(ut_utils.string_to_table(a_tags_ann_text(l_annotation_pos),',')); if l_tag_items is not empty then for i in 1 .. l_tag_items.count loop - if regexp_like(l_tag_items(i),'^[^-!&|](\S)+$') then + if regexp_like(l_tag_items(i),'^[^-](\S)+$') then l_tags_list.extend(); l_tags_list(l_tags_list.last) := l_tag_items(i); else diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index a9153c7bd..858069c8f 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -238,44 +238,46 @@ create or replace package body ut_suite_cache_manager is l_tags_exclude varchar2(4000); l_return_tag varchar2(4000); begin - select listagg( t.column_value,'|') - within group( order by column_value) - into l_tags_include - from table(l_tags) t - where t.column_value not like '-%'; - - select listagg( replace(t.column_value,'-','!'),' & ') - within group( order by column_value) - into l_tags_exclude - from table(l_tags) t - where t.column_value like '-%'; - - l_return_tag:= - case when l_tags_include is not null then - '('||l_tags_include||')' else null end || - case when l_tags_include is not null and l_tags_exclude is not null then - ' & ' else null end || - case when l_tags_exclude is not null then - '('||l_tags_exclude||')' else null end; + if instr(a_tags,',') > 0 or instr(a_tags,'-') > 0 then + + select '('||listagg( t.column_value,'|') + within group( order by column_value)||')' + into l_tags_include + from table(l_tags) t + where t.column_value not like '-%'; + select '('||listagg( replace(t.column_value,'-','!'),' & ') + within group( order by column_value)||')' + into l_tags_exclude + from table(l_tags) t + where t.column_value like '-%'; + + + l_return_tag:= + case + when l_tags_include <> '()' and l_tags_exclude <> '()' + then l_tags_include || ' & ' || l_tags_exclude + when l_tags_include <> '()' + then l_tags_include + when l_tags_exclude <> '()' + then l_tags_exclude + end; + else + l_return_tag := a_tags; + end if; return l_return_tag; end; function create_where_filter(a_tags varchar2 ) return varchar2 is - l_tags varchar2(4000):= replace(a_tags,' '); + l_tags varchar2(4000); begin - if instr(l_tags,',') > 0 or instr(l_tags,'-') > 0 then - l_tags := replace(replace_legacy_tag_notation(l_tags),' '); - end if; + l_tags := replace(replace_legacy_tag_notation(a_tags),' '); l_tags := ut_utils.conv_postfix_to_infix_sql(ut_utils.shunt_logical_expression(l_tags)); - l_tags := REPLACE(l_tags, '|',' or '); - l_tags := REPLACE(l_tags ,'&',' and '); - l_tags := REPLACE(l_tags ,'!','not'); - return l_tags; - exception - when ut_utils.ex_invalid_tag_expression then - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + l_tags := replace(l_tags, '|',' or '); + l_tags := replace(l_tags ,'&',' and '); + l_tags := replace(l_tags ,'!','not'); + return l_tags; end; /* diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index a8528fa86..6bcfbfeff 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -28,8 +28,8 @@ create or replace package body ut_utils is * Constants use in postfix and infix transformations */ gc_operators constant ut_varchar2_list := ut_varchar2_list('|','&','!'); - gc_unary_operator constant ut_varchar2_list := ut_varchar2_list('!'); -- right side associative operator - gc_binary_operator constant ut_varchar2_list := ut_varchar2_list('|','&'); -- left side associative operator + gc_unary_operators constant ut_varchar2_list := ut_varchar2_list('!'); -- right side associative operator + gc_binary_operators constant ut_varchar2_list := ut_varchar2_list('|','&'); -- left side associative operator type t_precedence_table is table of number index by varchar2(1); g_precedence t_precedence_table; @@ -1027,9 +1027,9 @@ create or replace package body ut_utils is --Exuecute modified shunting algorithm WHILE (l_idx is not null) loop l_token := l_input_tokens(l_idx); - if (l_token member of gc_operators and l_token member of gc_binary_operator) then + if (l_token member of gc_operators and l_token member of gc_binary_operators) then if not(l_expect_operator) then - raise ex_invalid_tag_expression; + raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); end if; while l_operator_stack.top > 0 and (g_precedence(l_operator_stack.peek) > g_precedence(l_token)) loop l_rnp_tokens.extend; @@ -1038,23 +1038,23 @@ create or replace package body ut_utils is l_operator_stack.push(l_input_tokens(l_idx)); l_expect_operand := true; l_expect_operator:= false; - elsif (l_token member of gc_operators and l_token member of gc_unary_operator) then + elsif (l_token member of gc_operators and l_token member of gc_unary_operators) then if not(l_expect_operand) then - raise ex_invalid_tag_expression; + raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); end if; l_operator_stack.push(l_input_tokens(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif l_token = '(' then if not(l_expect_operand) then - raise ex_invalid_tag_expression; + raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); end if; l_operator_stack.push(l_input_tokens(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif l_token = ')' then if not(l_expect_operator) then - raise ex_invalid_tag_expression; + raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); end if; while l_operator_stack.peek <> '(' loop l_rnp_tokens.extend; @@ -1065,7 +1065,7 @@ create or replace package body ut_utils is l_expect_operator:= true; else if not(l_expect_operand) then - raise ex_invalid_tag_expression; + raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); end if; l_rnp_tokens.extend; l_rnp_tokens(l_rnp_tokens.last) :=l_token; @@ -1078,7 +1078,7 @@ create or replace package body ut_utils is while l_operator_stack.peek is not null loop if l_operator_stack.peek in ('(',')') then - raise ex_invalid_tag_expression; + raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); end if; l_rnp_tokens.extend; l_rnp_tokens(l_rnp_tokens.last):=l_operator_stack.pop; @@ -1087,37 +1087,6 @@ create or replace package body ut_utils is return l_rnp_tokens; end shunt_logical_expression; - function convert_postfix_to_infix(a_postfix_exp in ut_varchar2_list) - return varchar2 is - l_infix_stack ut_stack := ut_stack(); - l_right_side varchar2(32767); - l_left_side varchar2(32767); - l_infix_exp varchar2(32767); - l_idx pls_integer; - begin - l_idx := a_postfix_exp.first; - while (l_idx is not null) loop - --If token is operand but also single tag - if a_postfix_exp(l_idx) not member of gc_operators then --its operand - l_infix_stack.push(a_postfix_exp(l_idx)); - --If token is unary operator not - elsif a_postfix_exp(l_idx) member of gc_unary_operator then - l_right_side := l_infix_stack.pop; - l_infix_exp := '('||a_postfix_exp(l_idx)||l_right_side||')'; - l_infix_stack.push(l_infix_exp); - --If token is binary operator - elsif a_postfix_exp(l_idx) member of gc_binary_operator then - l_right_side := l_infix_stack.pop; - l_left_side := l_infix_stack.pop; - l_infix_exp := '('||l_left_side||a_postfix_exp(l_idx)||l_right_side||')'; - l_infix_stack.push(l_infix_exp); - end if; - l_idx := a_postfix_exp.next(l_idx); - end loop; - - return l_infix_stack.pop; - end convert_postfix_to_infix; - function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) return varchar2 is l_infix_stack ut_stack := ut_stack(); @@ -1136,12 +1105,12 @@ create or replace package body ut_utils is elsif a_postfix_exp(l_idx) not member of gc_operators then l_infix_stack.push(a_postfix_exp(l_idx)); --If token is unary operator not - elsif a_postfix_exp(l_idx) member of gc_unary_operator then + elsif a_postfix_exp(l_idx) member of gc_unary_operators then l_right_side := l_infix_stack.pop; l_infix_exp := a_postfix_exp(l_idx)||'('||l_right_side||')'; l_infix_stack.push(l_infix_exp); --If token is binary operator - elsif a_postfix_exp(l_idx) member of gc_binary_operator then + elsif a_postfix_exp(l_idx) member of gc_binary_operators then l_right_side := l_infix_stack.pop; l_left_side := l_infix_stack.pop; l_infix_exp := '('||l_left_side||a_postfix_exp(l_idx)||l_right_side||')'; diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 67b09b2f9..a7f7752fb 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -489,11 +489,6 @@ create or replace package ut_utils authid definer is */ function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list; - /* - * Function that converts postfix notation into infix - */ - function convert_postfix_to_infix(a_postfix_exp in ut_varchar2_list) return varchar2; - /* * Function that converts postfix notation into infix and creating a string of sql filter * that checking a tags collections for tags according to posted logic. diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 22733c4ce..8f3b57fd0 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -511,27 +511,6 @@ end; ut.expect(l_postfix_string).to_equal('a!b|'); end; - procedure test_conv_from_rpn_to_infix is - l_postfix_rpn ut3_develop.ut_varchar2_list; - l_infix_string varchar2(4000); - begin - l_postfix_rpn := ut3_develop.ut_varchar2_list('A'); - l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); - ut.expect(l_infix_string).to_equal('A'); - - l_postfix_rpn := ut3_develop.ut_varchar2_list('A','B','|'); - l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); - ut.expect(l_infix_string).to_equal('(A|B)'); - - l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','|','c','d','&','|'); - l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); - ut.expect(l_infix_string).to_equal('((a|b)|(c&d))'); - - l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','!','|'); - l_infix_string := ut3_develop.ut_utils.convert_postfix_to_infix(l_postfix_rpn); - ut.expect(l_infix_string).to_equal('(a|(!b))'); - end; - procedure conv_from_rpn_to_sql_filter is l_postfix_rpn ut3_develop.ut_varchar2_list; l_infix_string varchar2(4000); diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 1561e1136..a58082be0 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -160,9 +160,6 @@ create or replace package test_ut_utils is --%test( Test conversion of expression into Reverse Polish Notation) procedure test_conversion_to_rpn; - --%test( Test conversion of expression from Reverse Polish Notation into infix) - procedure test_conv_from_rpn_to_infix; - --%test( Test conversion of expression from Reverse Polish Notation into custom where filter for SQL) procedure conv_from_rpn_to_sql_filter; From 02a071cb43799b8b68aa12cddb8cba757e6654a2 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 13 Apr 2023 16:47:00 -0700 Subject: [PATCH 161/187] Separate tag logic. --- source/core/ut_suite_cache_manager.pkb | 143 +-------- source/core/ut_suite_cache_manager.pks | 9 +- source/core/ut_suite_manager.pkb | 15 +- source/core/ut_suite_tag_filter.pkb | 288 ++++++++++++++++++ source/core/ut_suite_tag_filter.pks | 48 +++ source/core/ut_utils.pkb | 140 --------- source/core/ut_utils.pks | 18 -- source/install.sql | 2 + test/install_ut3_tester_tests.sql | 2 + .../core/test_ut_suite_tag_filter.pkb | 42 +++ .../core/test_ut_suite_tag_filter.pks | 13 + test/ut3_tester/core/test_ut_utils.pkb | 39 --- test/ut3_tester/core/test_ut_utils.pks | 6 - 13 files changed, 423 insertions(+), 342 deletions(-) create mode 100644 source/core/ut_suite_tag_filter.pkb create mode 100644 source/core/ut_suite_tag_filter.pks create mode 100644 test/ut3_tester/core/test_ut_suite_tag_filter.pkb create mode 100644 test/ut3_tester/core/test_ut_suite_tag_filter.pks diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 858069c8f..3bb679517 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -220,121 +220,7 @@ create or replace package body ut_suite_cache_manager is and c.name = nvl(upper(sp.procedure_name),c.name)))) where r_num =1; return l_suite_items; end; - - /* - To support a legact tag notation - , = OR - - = NOT - we will perform a replace of that characters into - new notation. - | = OR - & = AND - ! = NOT - */ - function replace_legacy_tag_notation(a_tags varchar2 - ) return varchar2 is - l_tags ut_varchar2_list := ut_utils.string_to_table(a_tags,','); - l_tags_include varchar2(4000); - l_tags_exclude varchar2(4000); - l_return_tag varchar2(4000); - begin - if instr(a_tags,',') > 0 or instr(a_tags,'-') > 0 then - - select '('||listagg( t.column_value,'|') - within group( order by column_value)||')' - into l_tags_include - from table(l_tags) t - where t.column_value not like '-%'; - select '('||listagg( replace(t.column_value,'-','!'),' & ') - within group( order by column_value)||')' - into l_tags_exclude - from table(l_tags) t - where t.column_value like '-%'; - - - l_return_tag:= - case - when l_tags_include <> '()' and l_tags_exclude <> '()' - then l_tags_include || ' & ' || l_tags_exclude - when l_tags_include <> '()' - then l_tags_include - when l_tags_exclude <> '()' - then l_tags_exclude - end; - else - l_return_tag := a_tags; - end if; - return l_return_tag; - end; - - function create_where_filter(a_tags varchar2 - ) return varchar2 is - l_tags varchar2(4000); - begin - l_tags := replace(replace_legacy_tag_notation(a_tags),' '); - l_tags := ut_utils.conv_postfix_to_infix_sql(ut_utils.shunt_logical_expression(l_tags)); - l_tags := replace(l_tags, '|',' or '); - l_tags := replace(l_tags ,'&',' and '); - l_tags := replace(l_tags ,'!','not'); - return l_tags; - end; - - /* - Having a base set of suites we will do a further filter down if there are - any tags defined. - */ - function get_tags_suites ( - a_suite_items ut_suite_cache_rows, - a_tags varchar2 - ) return ut_suite_cache_rows is - l_suite_tags ut_suite_cache_rows := ut_suite_cache_rows(); - l_sql varchar2(32000); - l_tags varchar2(4000):= create_where_filter(a_tags); - begin - l_sql := - q'[ -with - suites_mv as ( - select c.id,value(c) as obj,c.path as path,c.self_type,c.object_owner,c.tags - from table(:suite_items) c - ), - suites_matching_expr as ( - select c.id,c.path as path,c.self_type,c.object_owner,c.tags - from suites_mv c - where c.self_type in ('UT_SUITE','UT_CONTEXT') - and ]'||l_tags||q'[ - ), - tests_matching_expr as ( - select c.id,c.path as path,c.self_type,c.object_owner,c.tags - from suites_mv c where c.self_type in ('UT_TEST') - and ]'||l_tags||q'[ - ), - tests_with_tags_inh_from_suite as ( - select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner - from suites_mv c join suites_matching_expr t - on (c.path||'.' like t.path || '.%' /*all descendants and self*/ and c.object_owner = t.object_owner) - ), - tests_with_tags_prom_to_suite as ( - select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner - from suites_mv c join tests_matching_expr t - on (t.path||'.' like c.path || '.%' /*all ancestors and self*/ and c.object_owner = t.object_owner) - ) - select obj from suites_mv c, - (select id,row_number() over (partition by id order by id) r_num from - (select id - from tests_with_tags_prom_to_suite tst - where ]'||l_tags||q'[ - union all - select id from tests_with_tags_inh_from_suite tst - where ]'||l_tags||q'[ - ) - ) t where c.id = t.id and r_num = 1 ]'; - - execute immediate l_sql bulk collect into l_suite_tags using a_suite_items; - return l_suite_tags; - end; - /* We will sort a suites in hierarchical structure. Sorting from bottom to top so when we consolidate @@ -387,30 +273,29 @@ with end; function get_cached_suite_rows( - a_schema_paths ut_path_items, - a_random_seed positive := null, - a_tags varchar2 := null + a_suites_filtered ut_suite_cache_rows ) return ut_suite_cache_rows is l_results ut_suite_cache_rows := ut_suite_cache_rows(); - l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); - l_schema_paths ut_path_items; - l_tags varchar2(4000) := a_tags; begin - l_schema_paths := a_schema_paths; - l_suite_items := get_suite_items(a_schema_paths); - if length(l_tags) > 0 then - l_suite_items := get_tags_suites(l_suite_items,l_tags); - end if; - - open c_get_bulk_cache_suite(l_suite_items); + open c_get_bulk_cache_suite(a_suites_filtered); fetch c_get_bulk_cache_suite bulk collect into l_results; close c_get_bulk_cache_suite; return l_results; end; - + function get_cached_suites( + a_schema_paths ut_path_items, + a_random_seed positive := null + ) return ut_suite_cache_rows is + l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); + l_schema_paths ut_path_items; + begin + l_schema_paths := a_schema_paths; + l_suite_items := get_suite_items(a_schema_paths); + return l_suite_items; + end; function get_schema_parse_time(a_schema_name varchar2) return timestamp result_cache is l_cache_parse_time timestamp; @@ -558,7 +443,7 @@ with a_schema_paths ut_path_items ) return ut_suite_cache_rows is begin - return get_cached_suite_rows( a_schema_paths ); + return get_cached_suite_rows(get_cached_suites( a_schema_paths )); end; function get_suite_items_info( diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index 7f06e95eb..c217abeed 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -55,11 +55,14 @@ create or replace package ut_suite_cache_manager authid definer is * Not to be used publicly. Used internally for building suites at runtime. */ function get_cached_suite_rows( + a_suites_filtered ut_suite_cache_rows + ) return ut_suite_cache_rows; + + function get_cached_suites( a_schema_paths ut_path_items, - a_random_seed positive := null, - a_tags varchar2 := null + a_random_seed positive := null ) return ut_suite_cache_rows; - + function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items; /* diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index 0f8629ded..f8a2e002c 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -355,17 +355,18 @@ create or replace package body ut_suite_manager is a_tags varchar2 := null, a_skip_all_objects boolean := false ) return t_cached_suites_cursor is - l_unfiltered_rows ut_suite_cache_rows; - l_filtered_rows ut_suite_cache_rows; - l_result t_cached_suites_cursor; + l_unfiltered_rows ut_suite_cache_rows; + l_tag_filter_applied ut_suite_cache_rows; + l_filtered_rows ut_suite_cache_rows; + l_result t_cached_suites_cursor; begin - l_unfiltered_rows := ut_suite_cache_manager.get_cached_suite_rows( + l_unfiltered_rows := ut_suite_cache_manager.get_cached_suites( a_schema_paths, - a_random_seed, - a_tags + a_random_seed ); - l_filtered_rows := get_filtered_cursor(l_unfiltered_rows,a_skip_all_objects); + l_tag_filter_applied := ut_suite_tag_filter.apply(l_unfiltered_rows,a_tags); + l_filtered_rows := get_filtered_cursor(ut_suite_cache_manager.get_cached_suite_rows(l_tag_filter_applied),a_skip_all_objects); reconcile_paths_and_suites(a_schema_paths,l_filtered_rows); ut_suite_cache_manager.sort_and_randomize_tests(l_filtered_rows,a_random_seed); diff --git a/source/core/ut_suite_tag_filter.pkb b/source/core/ut_suite_tag_filter.pkb new file mode 100644 index 000000000..f1e055a27 --- /dev/null +++ b/source/core/ut_suite_tag_filter.pkb @@ -0,0 +1,288 @@ +create or replace package body ut_suite_tag_filter is + /* + utPLSQL - Version 3 + Copyright 2016 - 2023 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + /** + * Constants use in postfix and infix transformations + */ + gc_operators constant ut_varchar2_list := ut_varchar2_list('|','&','!'); + gc_unary_operators constant ut_varchar2_list := ut_varchar2_list('!'); -- right side associative operator + gc_binary_operators constant ut_varchar2_list := ut_varchar2_list('|','&'); -- left side associative operator + + type t_precedence_table is table of number index by varchar2(1); + g_precedence t_precedence_table; + + function tokenize_tags_string(a_tags in varchar2) return ut_varchar2_list is + l_tags_tokens ut_varchar2_list := ut_varchar2_list(); + begin + --Tokenize a string into operators and tags + select regexp_substr(a_tags,'([^!()|&]+)|([!()|&])', 1, level) as string_parts + bulk collect into l_tags_tokens + from dual connect by regexp_substr (a_tags, '([^!()|&]+)|([!()|&])', 1, level) is not null; + + return l_tags_tokens; + end; + + /* + To support a legact tag notation + , = OR + - = NOT + we will perform a replace of that characters into + new notation. + | = OR + & = AND + ! = NOT + */ + function replace_legacy_tag_notation(a_tags varchar2 + ) return varchar2 is + l_tags ut_varchar2_list := ut_utils.string_to_table(a_tags,','); + l_tags_include varchar2(4000); + l_tags_exclude varchar2(4000); + l_return_tag varchar2(4000); + begin + if instr(a_tags,',') > 0 or instr(a_tags,'-') > 0 then + + select '('||listagg( t.column_value,'|') + within group( order by column_value)||')' + into l_tags_include + from table(l_tags) t + where t.column_value not like '-%'; + + select '('||listagg( replace(t.column_value,'-','!'),' & ') + within group( order by column_value)||')' + into l_tags_exclude + from table(l_tags) t + where t.column_value like '-%'; + + + l_return_tag:= + case + when l_tags_include <> '()' and l_tags_exclude <> '()' + then l_tags_include || ' & ' || l_tags_exclude + when l_tags_include <> '()' + then l_tags_include + when l_tags_exclude <> '()' + then l_tags_exclude + end; + else + l_return_tag := a_tags; + end if; + return l_return_tag; + end; + + /* + https://stackoverflow.com/questions/29634992/shunting-yard-validate-expression + */ + function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list is + l_operator_stack ut_stack := ut_stack(); + l_input_tokens ut_varchar2_list := tokenize_tags_string(a_tags); + l_rnp_tokens ut_varchar2_list := ut_varchar2_list(); + l_token varchar2(32767); + l_expect_operand boolean := true; + l_expect_operator boolean := false; + l_idx pls_integer; + begin + l_idx := l_input_tokens.first; + --Exuecute modified shunting algorithm + WHILE (l_idx is not null) loop + l_token := l_input_tokens(l_idx); + if (l_token member of gc_operators and l_token member of gc_binary_operators) then + if not(l_expect_operator) then + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + end if; + while l_operator_stack.top > 0 and (g_precedence(l_operator_stack.peek) > g_precedence(l_token)) loop + l_rnp_tokens.extend; + l_rnp_tokens(l_rnp_tokens.last) := l_operator_stack.pop; + end loop; + l_operator_stack.push(l_input_tokens(l_idx)); + l_expect_operand := true; + l_expect_operator:= false; + elsif (l_token member of gc_operators and l_token member of gc_unary_operators) then + if not(l_expect_operand) then + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + end if; + l_operator_stack.push(l_input_tokens(l_idx)); + l_expect_operand := true; + l_expect_operator:= false; + elsif l_token = '(' then + if not(l_expect_operand) then + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + end if; + l_operator_stack.push(l_input_tokens(l_idx)); + l_expect_operand := true; + l_expect_operator:= false; + elsif l_token = ')' then + if not(l_expect_operator) then + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + end if; + while l_operator_stack.peek <> '(' loop + l_rnp_tokens.extend; + l_rnp_tokens(l_rnp_tokens.last) := l_operator_stack.pop; + end loop; + l_operator_stack.pop; --Pop the open bracket and discard it + l_expect_operand := false; + l_expect_operator:= true; + else + if not(l_expect_operand) then + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + end if; + l_rnp_tokens.extend; + l_rnp_tokens(l_rnp_tokens.last) :=l_token; + l_expect_operator := true; + l_expect_operand := false; + end if; + + l_idx := l_input_tokens.next(l_idx); + end loop; + + while l_operator_stack.peek is not null loop + if l_operator_stack.peek in ('(',')') then + raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + end if; + l_rnp_tokens.extend; + l_rnp_tokens(l_rnp_tokens.last):=l_operator_stack.pop; + end loop; + + return l_rnp_tokens; + end shunt_logical_expression; + + function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) + return varchar2 is + l_infix_stack ut_stack := ut_stack(); + l_right_side varchar2(32767); + l_left_side varchar2(32767); + l_infix_exp varchar2(32767); + l_member_token varchar2(20) := ' member of tags'; + l_idx pls_integer; + begin + l_idx := a_postfix_exp.first; + while ( l_idx is not null) loop + --If token is operand but also single tag + if regexp_count(a_postfix_exp(l_idx),'[!()|&]') = 0 then + l_infix_stack.push(q'[']'||a_postfix_exp(l_idx)||q'[']'||l_member_token); + --If token is operand but containing other expressions + elsif a_postfix_exp(l_idx) not member of gc_operators then + l_infix_stack.push(a_postfix_exp(l_idx)); + --If token is unary operator not + elsif a_postfix_exp(l_idx) member of gc_unary_operators then + l_right_side := l_infix_stack.pop; + l_infix_exp := a_postfix_exp(l_idx)||'('||l_right_side||')'; + l_infix_stack.push(l_infix_exp); + --If token is binary operator + elsif a_postfix_exp(l_idx) member of gc_binary_operators then + l_right_side := l_infix_stack.pop; + l_left_side := l_infix_stack.pop; + l_infix_exp := '('||l_left_side||a_postfix_exp(l_idx)||l_right_side||')'; + l_infix_stack.push(l_infix_exp); + end if; + l_idx := a_postfix_exp.next(l_idx); + end loop; + + return l_infix_stack.pop; + end conv_postfix_to_infix_sql; + + function create_where_filter(a_tags varchar2 + ) return varchar2 is + l_tags varchar2(4000); + begin + l_tags := replace(replace_legacy_tag_notation(a_tags),' '); + l_tags := conv_postfix_to_infix_sql(shunt_logical_expression(l_tags)); + l_tags := replace(l_tags, '|',' or '); + l_tags := replace(l_tags ,'&',' and '); + l_tags := replace(l_tags ,'!','not'); + return l_tags; + end; + + + /* + Having a base set of suites we will do a further filter down if there are + any tags defined. + */ + function get_tags_suites ( + a_suite_items ut_suite_cache_rows, + a_tags varchar2 + ) return ut_suite_cache_rows is + l_suite_tags ut_suite_cache_rows := ut_suite_cache_rows(); + l_sql varchar2(32000); + l_tags varchar2(4000):= create_where_filter(a_tags); + begin + l_sql := + q'[ +with + suites_mv as ( + select c.id,value(c) as obj,c.path as path,c.self_type,c.object_owner,c.tags + from table(:suite_items) c + ), + suites_matching_expr as ( + select c.id,c.path as path,c.self_type,c.object_owner,c.tags + from suites_mv c + where c.self_type in ('UT_SUITE','UT_CONTEXT') + and ]'||l_tags||q'[ + ), + tests_matching_expr as ( + select c.id,c.path as path,c.self_type,c.object_owner,c.tags + from suites_mv c where c.self_type in ('UT_TEST') + and ]'||l_tags||q'[ + ), + tests_with_tags_inh_from_suite as ( + select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner + from suites_mv c join suites_matching_expr t + on (c.path||'.' like t.path || '.%' /*all descendants and self*/ and c.object_owner = t.object_owner) + ), + tests_with_tags_prom_to_suite as ( + select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner + from suites_mv c join tests_matching_expr t + on (t.path||'.' like c.path || '.%' /*all ancestors and self*/ and c.object_owner = t.object_owner) + ) + select obj from suites_mv c, + (select id,row_number() over (partition by id order by id) r_num from + (select id + from tests_with_tags_prom_to_suite tst + where ]'||l_tags||q'[ + union all + select id from tests_with_tags_inh_from_suite tst + where ]'||l_tags||q'[ + ) + ) t where c.id = t.id and r_num = 1 ]'; + + execute immediate l_sql bulk collect into l_suite_tags using a_suite_items; + return l_suite_tags; + end; + + function apply( + a_unfiltered_rows ut_suite_cache_rows, + a_tags varchar2 := null + ) return ut_suite_cache_rows is + l_suite_items ut_suite_cache_rows := a_unfiltered_rows; + begin + if length(a_tags) > 0 then + l_suite_items := get_tags_suites(l_suite_items,a_tags); + end if; + + return l_suite_items; + end; + +begin + --Define operators precedence + g_precedence('!'):=4; + g_precedence('&'):=3; + g_precedence('|'):=2; + g_precedence(')'):=1; + g_precedence('('):=1; + +end ut_suite_tag_filter; +/ diff --git a/source/core/ut_suite_tag_filter.pks b/source/core/ut_suite_tag_filter.pks new file mode 100644 index 000000000..787c72603 --- /dev/null +++ b/source/core/ut_suite_tag_filter.pks @@ -0,0 +1,48 @@ +create or replace package ut_suite_tag_filter authid definer is + /* + utPLSQL - Version 3 + Copyright 2016 - 2023 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + /** + * Package that will filter suites by tags + * + */ + + /* + * Return table of tokens character by character + */ + function tokenize_tags_string(a_tags in varchar2) return ut_varchar2_list; + + /* + * Function that uses Dijkstra algorithm to parse mathematical and logical expression + * and return a list of elements in Reverse Polish Notation ( postfix ) + * As part of execution it will validate expression. + */ + function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list; + + /* + * Function that converts postfix notation into infix and creating a string of sql filter + * that checking a tags collections for tags according to posted logic. + */ + function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) return varchar2; + + function apply( + a_unfiltered_rows ut_suite_cache_rows, + a_tags varchar2 := null + ) return ut_suite_cache_rows; + +end ut_suite_tag_filter; +/ diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 6bcfbfeff..6f972e11c 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -24,15 +24,6 @@ create or replace package body ut_utils is gc_full_valid_xml_name constant varchar2(50) := '^([_a-zA-Z])([_a-zA-Z0-9\.-])*$'; gc_owner_hash constant integer(11) := dbms_utility.get_hash_value( ut_owner(), 0, power(2,31)-1); - /** - * Constants use in postfix and infix transformations - */ - gc_operators constant ut_varchar2_list := ut_varchar2_list('|','&','!'); - gc_unary_operators constant ut_varchar2_list := ut_varchar2_list('!'); -- right side associative operator - gc_binary_operators constant ut_varchar2_list := ut_varchar2_list('|','&'); -- left side associative operator - - type t_precedence_table is table of number index by varchar2(1); - g_precedence t_precedence_table; function surround_with(a_value varchar2, a_quote_char varchar2) return varchar2 is begin @@ -999,136 +990,5 @@ create or replace package body ut_utils is return l_result; end; - - function tokenize_tags_string(a_tags in varchar2) return ut_varchar2_list is - l_tags_tokens ut_varchar2_list := ut_varchar2_list(); - begin - --Tokenize a string into operators and tags - select regexp_substr(a_tags,'([^!()|&]+)|([!()|&])', 1, level) as string_parts - bulk collect into l_tags_tokens - from dual connect by regexp_substr (a_tags, '([^!()|&]+)|([!()|&])', 1, level) is not null; - - return l_tags_tokens; - end; - - /* - https://stackoverflow.com/questions/29634992/shunting-yard-validate-expression - */ - function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list is - l_operator_stack ut_stack := ut_stack(); - l_input_tokens ut_varchar2_list := tokenize_tags_string(a_tags); - l_rnp_tokens ut_varchar2_list := ut_varchar2_list(); - l_token varchar2(32767); - l_expect_operand boolean := true; - l_expect_operator boolean := false; - l_idx pls_integer; - begin - l_idx := l_input_tokens.first; - --Exuecute modified shunting algorithm - WHILE (l_idx is not null) loop - l_token := l_input_tokens(l_idx); - if (l_token member of gc_operators and l_token member of gc_binary_operators) then - if not(l_expect_operator) then - raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); - end if; - while l_operator_stack.top > 0 and (g_precedence(l_operator_stack.peek) > g_precedence(l_token)) loop - l_rnp_tokens.extend; - l_rnp_tokens(l_rnp_tokens.last) := l_operator_stack.pop; - end loop; - l_operator_stack.push(l_input_tokens(l_idx)); - l_expect_operand := true; - l_expect_operator:= false; - elsif (l_token member of gc_operators and l_token member of gc_unary_operators) then - if not(l_expect_operand) then - raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); - end if; - l_operator_stack.push(l_input_tokens(l_idx)); - l_expect_operand := true; - l_expect_operator:= false; - elsif l_token = '(' then - if not(l_expect_operand) then - raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); - end if; - l_operator_stack.push(l_input_tokens(l_idx)); - l_expect_operand := true; - l_expect_operator:= false; - elsif l_token = ')' then - if not(l_expect_operator) then - raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); - end if; - while l_operator_stack.peek <> '(' loop - l_rnp_tokens.extend; - l_rnp_tokens(l_rnp_tokens.last) := l_operator_stack.pop; - end loop; - l_operator_stack.pop; --Pop the open bracket and discard it - l_expect_operand := false; - l_expect_operator:= true; - else - if not(l_expect_operand) then - raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); - end if; - l_rnp_tokens.extend; - l_rnp_tokens(l_rnp_tokens.last) :=l_token; - l_expect_operator := true; - l_expect_operand := false; - end if; - - l_idx := l_input_tokens.next(l_idx); - end loop; - - while l_operator_stack.peek is not null loop - if l_operator_stack.peek in ('(',')') then - raise_application_error(gc_invalid_tag_expression, 'Invalid Tag expression'); - end if; - l_rnp_tokens.extend; - l_rnp_tokens(l_rnp_tokens.last):=l_operator_stack.pop; - end loop; - - return l_rnp_tokens; - end shunt_logical_expression; - - function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) - return varchar2 is - l_infix_stack ut_stack := ut_stack(); - l_right_side varchar2(32767); - l_left_side varchar2(32767); - l_infix_exp varchar2(32767); - l_member_token varchar2(20) := ' member of tags'; - l_idx pls_integer; - begin - l_idx := a_postfix_exp.first; - while ( l_idx is not null) loop - --If token is operand but also single tag - if regexp_count(a_postfix_exp(l_idx),'[!()|&]') = 0 then - l_infix_stack.push(q'[']'||a_postfix_exp(l_idx)||q'[']'||l_member_token); - --If token is operand but containing other expressions - elsif a_postfix_exp(l_idx) not member of gc_operators then - l_infix_stack.push(a_postfix_exp(l_idx)); - --If token is unary operator not - elsif a_postfix_exp(l_idx) member of gc_unary_operators then - l_right_side := l_infix_stack.pop; - l_infix_exp := a_postfix_exp(l_idx)||'('||l_right_side||')'; - l_infix_stack.push(l_infix_exp); - --If token is binary operator - elsif a_postfix_exp(l_idx) member of gc_binary_operators then - l_right_side := l_infix_stack.pop; - l_left_side := l_infix_stack.pop; - l_infix_exp := '('||l_left_side||a_postfix_exp(l_idx)||l_right_side||')'; - l_infix_stack.push(l_infix_exp); - end if; - l_idx := a_postfix_exp.next(l_idx); - end loop; - - return l_infix_stack.pop; - end conv_postfix_to_infix_sql; - -begin - --Define operator precedence - g_precedence('!'):=4; - g_precedence('&'):=3; - g_precedence('|'):=2; - g_precedence(')'):=1; - g_precedence('('):=1; - end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index a7f7752fb..b60fc4cdf 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -477,23 +477,5 @@ create or replace package ut_utils authid definer is */ function interval_to_text(a_interval yminterval_unconstrained) return varchar2; - /* - * Return table of tokens character by character - */ - function tokenize_tags_string(a_tags in varchar2) return ut_varchar2_list; - - /* - * Function that uses Dijkstra algorithm to parse mathematical and logical expression - * and return a list of elements in Reverse Polish Notation ( postfix ) - * As part of execution it will validate expression. - */ - function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list; - - /* - * Function that converts postfix notation into infix and creating a string of sql filter - * that checking a tags collections for tags according to posted logic. - */ - function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) return varchar2; - end ut_utils; / diff --git a/source/install.sql b/source/install.sql index a54977f94..827213e6c 100644 --- a/source/install.sql +++ b/source/install.sql @@ -155,6 +155,8 @@ create or replace context &&ut3_owner._info using &&ut3_owner..ut_session_contex @@install_component.sql 'core/ut_suite_cache_seq.sql' @@install_component.sql 'core/ut_suite_cache.sql' +@@install_component.sql 'core/ut_suite_tag_filter.pks' +@@install_component.sql 'core/ut_suite_tag_filter.pkb' @@install_component.sql 'core/ut_suite_cache_manager.pks' @@install_component.sql 'core/ut_suite_cache_manager.pkb' @@install_component.sql 'core/ut_suite_builder.pks' diff --git a/test/install_ut3_tester_tests.sql b/test/install_ut3_tester_tests.sql index 8163a39f2..cc96b2b64 100644 --- a/test/install_ut3_tester_tests.sql +++ b/test/install_ut3_tester_tests.sql @@ -17,6 +17,7 @@ alter session set plsql_optimize_level=0; @@ut3_tester/core/annotations/test_annot_disabled_reason.pks @@ut3_tester/core/expectations/test_expectation_processor.pks @@ut3_tester/core/test_ut_utils.pks +@@ut3_tester/core/test_ut_suite_tag_filter.pks @@ut3_tester/core/test_ut_test.pks @@ut3_tester/core/test_ut_suite.pks @@ut3_tester/core/test_ut_executable.pks @@ -35,6 +36,7 @@ alter session set plsql_optimize_level=0; @@ut3_tester/core/annotations/test_annot_disabled_reason.pkb @@ut3_tester/core/expectations/test_expectation_processor.pkb @@ut3_tester/core/test_ut_utils.pkb +@@ut3_tester/core/test_ut_suite_tag_filter.pkb @@ut3_tester/core/test_ut_test.pkb @@ut3_tester/core/test_ut_suite.pkb @@ut3_tester/core/test_ut_executable.pkb diff --git a/test/ut3_tester/core/test_ut_suite_tag_filter.pkb b/test/ut3_tester/core/test_ut_suite_tag_filter.pkb new file mode 100644 index 000000000..a1d0be1f7 --- /dev/null +++ b/test/ut3_tester/core/test_ut_suite_tag_filter.pkb @@ -0,0 +1,42 @@ +create or replace package body test_ut_suite_tag_filter is + + procedure test_conversion_to_rpn is + l_postfix ut3_develop.ut_varchar2_list; + l_postfix_string varchar2(4000); + begin + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression('A'); + l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); + ut.expect(l_postfix_string).to_equal('A'); + + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression('A|B'); + l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); + ut.expect(l_postfix_string).to_equal('AB|'); + + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression('(a|b)|c&d'); + l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); + ut.expect(l_postfix_string).to_equal('ab|cd&|'); + + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression('!a|b'); + l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); + ut.expect(l_postfix_string).to_equal('a!b|'); + end; + + procedure conv_from_rpn_to_sql_filter is + l_postfix_rpn ut3_develop.ut_varchar2_list; + l_infix_string varchar2(4000); + begin + l_postfix_rpn := ut3_develop.ut_varchar2_list('A'); + l_infix_string := ut3_develop.ut_suite_tag_filter.conv_postfix_to_infix_sql(l_postfix_rpn); + ut.expect(l_infix_string).to_equal(q'['A' member of tags]'); + + l_postfix_rpn := ut3_develop.ut_varchar2_list('A','B','|'); + l_infix_string := ut3_develop.ut_suite_tag_filter.conv_postfix_to_infix_sql(l_postfix_rpn); + ut.expect(l_infix_string).to_equal(q'[('A' member of tags|'B' member of tags)]'); + + l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','!','|'); + l_infix_string := ut3_develop.ut_suite_tag_filter.conv_postfix_to_infix_sql(l_postfix_rpn); + ut.expect(l_infix_string).to_equal(q'[('a' member of tags|!('b' member of tags))]'); + end; + +end test_ut_suite_tag_filter; +/ diff --git a/test/ut3_tester/core/test_ut_suite_tag_filter.pks b/test/ut3_tester/core/test_ut_suite_tag_filter.pks new file mode 100644 index 000000000..093fab856 --- /dev/null +++ b/test/ut3_tester/core/test_ut_suite_tag_filter.pks @@ -0,0 +1,13 @@ +create or replace package test_ut_suite_tag_filter is + + --%suite(ut_suite_tag_filter) + --%suitepath(utplsql.ut3_tester.core) + + --%test( Test conversion of expression into Reverse Polish Notation) + procedure test_conversion_to_rpn; + + --%test( Test conversion of expression from Reverse Polish Notation into custom where filter for SQL) + procedure conv_from_rpn_to_sql_filter; + +end test_ut_suite_tag_filter; +/ diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 8f3b57fd0..ec7e4f403 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -489,44 +489,5 @@ end; ut.expect(l_expected).to_equal(l_actual); end; - - procedure test_conversion_to_rpn is - l_postfix ut3_develop.ut_varchar2_list; - l_postfix_string varchar2(4000); - begin - l_postfix := ut3_develop.ut_utils.shunt_logical_expression('A'); - l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); - ut.expect(l_postfix_string).to_equal('A'); - - l_postfix := ut3_develop.ut_utils.shunt_logical_expression('A|B'); - l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); - ut.expect(l_postfix_string).to_equal('AB|'); - - l_postfix := ut3_develop.ut_utils.shunt_logical_expression('(a|b)|c&d'); - l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); - ut.expect(l_postfix_string).to_equal('ab|cd&|'); - - l_postfix := ut3_develop.ut_utils.shunt_logical_expression('!a|b'); - l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); - ut.expect(l_postfix_string).to_equal('a!b|'); - end; - - procedure conv_from_rpn_to_sql_filter is - l_postfix_rpn ut3_develop.ut_varchar2_list; - l_infix_string varchar2(4000); - begin - l_postfix_rpn := ut3_develop.ut_varchar2_list('A'); - l_infix_string := ut3_develop.ut_utils.conv_postfix_to_infix_sql(l_postfix_rpn); - ut.expect(l_infix_string).to_equal(q'['A' member of tags]'); - - l_postfix_rpn := ut3_develop.ut_varchar2_list('A','B','|'); - l_infix_string := ut3_develop.ut_utils.conv_postfix_to_infix_sql(l_postfix_rpn); - ut.expect(l_infix_string).to_equal(q'[('A' member of tags|'B' member of tags)]'); - - l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','!','|'); - l_infix_string := ut3_develop.ut_utils.conv_postfix_to_infix_sql(l_postfix_rpn); - ut.expect(l_infix_string).to_equal(q'[('a' member of tags|!('b' member of tags))]'); - end; - end test_ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index a58082be0..114b35e86 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -157,11 +157,5 @@ create or replace package test_ut_utils is --%endcontext - --%test( Test conversion of expression into Reverse Polish Notation) - procedure test_conversion_to_rpn; - - --%test( Test conversion of expression from Reverse Polish Notation into custom where filter for SQL) - procedure conv_from_rpn_to_sql_filter; - end test_ut_utils; / From b8b66ee715c6765d5fef1ad92d8c25513bf757c5 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 13 Apr 2023 17:00:41 -0700 Subject: [PATCH 162/187] Fix uninstall --- source/uninstall_objects.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index 1e21f0f95..f488b8b8d 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -95,6 +95,8 @@ drop package ut_suite_manager; drop package ut_suite_builder; +drop package ut_suite_tag_filter; + drop package ut_suite_cache_manager; drop table ut_suite_cache purge; From 077fdb11316cda8b99b9ccc909a1c9cb3de57267 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 14 Apr 2023 15:48:56 -0700 Subject: [PATCH 163/187] Various PR fixe --- docs/userguide/annotations.md | 82 +------------------ docs/userguide/running-unit-tests.md | 76 +++++++++++++++-- source/core/ut_suite_tag_filter.pkb | 18 ++-- source/core/ut_suite_tag_filter.pks | 2 +- .../core/test_ut_suite_tag_filter.pkb | 49 ++++++++++- .../core/test_ut_suite_tag_filter.pks | 20 +++++ 6 files changed, 145 insertions(+), 102 deletions(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 8e5a5d1ca..552b02b52 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1616,7 +1616,7 @@ or Tags are defined as a comma separated list within the `--%tags` annotation. -When a suite/context is tagged, all of its children will automatically inherit the tag and get executed along with the parent, unless they are excluded by tag expression. +When a suite/context is tagged, all of its children will automatically inherit the tag and get executed along with the parent, unless they are excluded explicitly at runtime with a negated tag expression. Parent suite tests are not executed, but a suitepath hierarchy is kept. Sample test suite package with tags. @@ -1657,52 +1657,6 @@ create or replace package body ut_sample_test is end ut_sample_test; / ``` - -#### Tag Expressions - -Tag expressions are boolean expressions with the operators !, & and |. In addition, ( and ) can be used to adjust for operator precedence. - -| Operator | Meaning | -| -------- | --------| -| ! | not | -| & | and | -| \| | or | - -If you are tagging your tests across multiple dimensions, tag expressions help you to select which tests to execute. When tagging by test type (e.g., micro, integration, end-to-end) and feature (e.g., product, catalog, shipping), the following tag expressions can be useful. - - -| Tag Expression | Selection | -| -------- | --------| -| product | all tests for product | -| catalog \| shipping | all tests for catalog plus all tests for shipping | -| catalog & shipping | all tests for the intersection between catalog and shipping | -| product & !end-to-end | all tests for product, but not the end-to-end tests | -| (micro \| integration) & (product \| shipping) | all micro or integration tests for product or shipping | - - -Execution of the test is done by using the parameter `a_tags` with tag expressions - - -```sql linenums="1" -select * from table(ut.run(a_tags => 'fast|!complex')); -``` -The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` because a suite meet expression condition. - -```sql linenums="1" -select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'api')); -``` -The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` - -```sql linenums="1" -select * from table(ut.run(a_tags => 'complex')); -``` -The above call will execute only the `ut_sample_test.ut_refcursors1` test, as only the test `ut_refcursors1` is tagged with `complex` - -```sql linenums="1" -select * from table(ut.run(a_tags => 'fast')); -``` -The above call will execute both `ut_sample_test.ut_refcursors1` and `ut_sample_test.ut_test` tests, as both tests are tagged with `fast` - #### Tag naming convention Tags must follow the below naming convention: @@ -1715,45 +1669,11 @@ Tags must follow the below naming convention: - vertical bar (|) - exclamation point (!) - tag cannot be null or blank -- tag cannot contain whitespace - tag cannot start with a dash, e.g. `-some-stuff` is **not** a valid tag - tag cannot contain spaces, e.g. `test of batch`. To create a multi-word tag use underscores or dashes, e.g. `test_of_batch`, `test-of-batch` - leading and trailing spaces are ignored in tag name, e.g. `--%tags( tag1 , tag2 )` becomes `tag1` and `tag2` tag names -#### Excluding tests/suites by tags - -It is possible to exclude parts of test suites with tags. -In order to do so, prefix the tag name to exclude with a `!` (exclamation) sign when invoking the test run which is equivalent of `-` (dash) in legacy notation. -Examples (based on above sample test suite) - -```sql linenums="1" -select * from table(ut.run(a_tags => '(api|fast)&!complex')); -``` - -which is equivalent of legacy calling: - -```sql linenums="1" -select * from table(ut.run(a_tags => 'api,fast,-complex')); -``` - -or - -```sql linenums="1" -select * from table(ut.run(a_tags => '(api|fast)&(!complex&!test1)')); -``` - -which is equivalent of legacy calling: - -```sql linenums="1" -select * from table(ut.run(a_tags => 'api,fast,-complex,-test1')); -``` - -The above call will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex`. -Given the above example package `ut_sample_test`, only `ut_sample_test.ut_test` will be executed. - - - ### Suitepath It is very likely that the application for which you are going to introduce tests consists of many different packages, procedures and functions. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 978803b9a..9abc7c964 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -319,23 +319,85 @@ select * from table(ut.run('hr.test_apply_bonus', a_random_test_order_seed => 30 In addition to the path, you can filter the tests to be run by specifying tags. Tags are defined in the test / context / suite with the `--%tags`-annotation ([Read more](annotations.md#tags)). Multiple tags are separated by comma. -The framework applies `OR` logic to all specified tags so any test / suite that matches at least one tag will be included in the test run. + + +### Tag Expressions + +Tag expressions are boolean expressions with the operators !, & and |. In addition, ( and ) can be used to adjust for operator precedence. + +| Operator | Meaning | +| -------- | --------| +| ! | not | +| & | and | +| \| | or | + +If you are tagging your tests across multiple dimensions, tag expressions help you to select which tests to execute. When tagging by test type (e.g., micro, integration, end-to-end) and feature (e.g., product, catalog, shipping), the following tag expressions can be useful. + + +| Tag Expression | Selection | +| -------- | --------| +| product | all tests for product | +| catalog \| shipping | all tests for catalog plus all tests for shipping | +| catalog & shipping | all tests for the intersection between catalog and shipping | +| product & !end-to-end | all tests for product, but not the end-to-end tests | +| (micro \| integration) & (product \| shipping) | all micro or integration tests for product or shipping | + + +Execution of the test is done by using the parameter `a_tags` with tag expressions + ```sql linenums="1" -begin - ut.run('hr.test_apply_bonus', a_tags => 'test1,test2'); -end; +select * from table(ut.run(a_tags => 'fast|!complex')); +``` +The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` because a suite meet expression condition. + +```sql linenums="1" +select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'api')); +``` +The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` + +```sql linenums="1" +select * from table(ut.run(a_tags => 'complex')); ``` +The above call will execute only the `ut_sample_test.ut_refcursors1` test, as only the test `ut_refcursors1` is tagged with `complex` + ```sql linenums="1" -select * from table(ut.run('hr.test_apply_bonus', a_tags => 'suite1')) +select * from table(ut.run(a_tags => 'fast')); ``` +The above call will execute both `ut_sample_test.ut_refcursors1` and `ut_sample_test.ut_test` tests, as both tests are tagged with `fast` + +### Excluding tests/suites by tags -You can also exclude specific tags by adding a `-` (dash) in front of the tag +It is possible to exclude parts of test suites with tags. +In order to do so, prefix the tag name to exclude with a `!` (exclamation) sign when invoking the test run which is equivalent of `-` (dash) in legacy notation. +Examples (based on above sample test suite) ```sql linenums="1" -select * from table(ut.run('hr.test_apply_bonus', a_tags => '-suite1')) +select * from table(ut.run(a_tags => '(api|fast)&!complex')); ``` +which is equivalent of legacy calling: + +```sql linenums="1" +select * from table(ut.run(a_tags => 'api,fast,-complex')); +``` + +or + +```sql linenums="1" +select * from table(ut.run(a_tags => '(api|fast)&(!complex&!test1)')); +``` + +which is equivalent of legacy calling: + +```sql linenums="1" +select * from table(ut.run(a_tags => 'api,fast,-complex,-test1')); +``` + +The above call will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex`. +Given the above example package `ut_sample_test`, only `ut_sample_test.ut_test` will be executed. + + ## Keeping uncommitted data after test-run utPLSQL by default runs tests in autonomous transaction and performs automatic rollback to assure that tests do not impact one-another and do not have impact on the current session in your IDE. diff --git a/source/core/ut_suite_tag_filter.pkb b/source/core/ut_suite_tag_filter.pkb index f1e055a27..d5df54212 100644 --- a/source/core/ut_suite_tag_filter.pkb +++ b/source/core/ut_suite_tag_filter.pkb @@ -87,19 +87,18 @@ create or replace package body ut_suite_tag_filter is /* https://stackoverflow.com/questions/29634992/shunting-yard-validate-expression */ - function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list is + function shunt_logical_expression(a_tags in ut_varchar2_list) return ut_varchar2_list is l_operator_stack ut_stack := ut_stack(); - l_input_tokens ut_varchar2_list := tokenize_tags_string(a_tags); l_rnp_tokens ut_varchar2_list := ut_varchar2_list(); l_token varchar2(32767); l_expect_operand boolean := true; l_expect_operator boolean := false; l_idx pls_integer; begin - l_idx := l_input_tokens.first; + l_idx := a_tags.first; --Exuecute modified shunting algorithm WHILE (l_idx is not null) loop - l_token := l_input_tokens(l_idx); + l_token := a_tags(l_idx); if (l_token member of gc_operators and l_token member of gc_binary_operators) then if not(l_expect_operator) then raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); @@ -108,21 +107,21 @@ create or replace package body ut_suite_tag_filter is l_rnp_tokens.extend; l_rnp_tokens(l_rnp_tokens.last) := l_operator_stack.pop; end loop; - l_operator_stack.push(l_input_tokens(l_idx)); + l_operator_stack.push(a_tags(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif (l_token member of gc_operators and l_token member of gc_unary_operators) then if not(l_expect_operand) then raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); end if; - l_operator_stack.push(l_input_tokens(l_idx)); + l_operator_stack.push(a_tags(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif l_token = '(' then if not(l_expect_operand) then raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); end if; - l_operator_stack.push(l_input_tokens(l_idx)); + l_operator_stack.push(a_tags(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif l_token = ')' then @@ -146,7 +145,7 @@ create or replace package body ut_suite_tag_filter is l_expect_operand := false; end if; - l_idx := l_input_tokens.next(l_idx); + l_idx := a_tags.next(l_idx); end loop; while l_operator_stack.peek is not null loop @@ -198,9 +197,10 @@ create or replace package body ut_suite_tag_filter is function create_where_filter(a_tags varchar2 ) return varchar2 is l_tags varchar2(4000); + l_tokenized_tags ut_varchar2_list; begin l_tags := replace(replace_legacy_tag_notation(a_tags),' '); - l_tags := conv_postfix_to_infix_sql(shunt_logical_expression(l_tags)); + l_tags := conv_postfix_to_infix_sql(shunt_logical_expression(tokenize_tags_string(l_tags))); l_tags := replace(l_tags, '|',' or '); l_tags := replace(l_tags ,'&',' and '); l_tags := replace(l_tags ,'!','not'); diff --git a/source/core/ut_suite_tag_filter.pks b/source/core/ut_suite_tag_filter.pks index 787c72603..37ba19111 100644 --- a/source/core/ut_suite_tag_filter.pks +++ b/source/core/ut_suite_tag_filter.pks @@ -31,7 +31,7 @@ create or replace package ut_suite_tag_filter authid definer is * and return a list of elements in Reverse Polish Notation ( postfix ) * As part of execution it will validate expression. */ - function shunt_logical_expression(a_tags in varchar2) return ut_varchar2_list; + function shunt_logical_expression(a_tags in ut_varchar2_list) return ut_varchar2_list; /* * Function that converts postfix notation into infix and creating a string of sql filter diff --git a/test/ut3_tester/core/test_ut_suite_tag_filter.pkb b/test/ut3_tester/core/test_ut_suite_tag_filter.pkb index a1d0be1f7..a396c6d25 100644 --- a/test/ut3_tester/core/test_ut_suite_tag_filter.pkb +++ b/test/ut3_tester/core/test_ut_suite_tag_filter.pkb @@ -3,24 +3,65 @@ create or replace package body test_ut_suite_tag_filter is procedure test_conversion_to_rpn is l_postfix ut3_develop.ut_varchar2_list; l_postfix_string varchar2(4000); + l_input_token ut3_develop.ut_varchar2_list; begin - l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression('A'); + l_input_token := ut3_develop.ut_suite_tag_filter.tokenize_tags_string('A'); + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression(l_input_token); l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); ut.expect(l_postfix_string).to_equal('A'); - l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression('A|B'); + l_input_token := ut3_develop.ut_suite_tag_filter.tokenize_tags_string('A|B'); + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression(l_input_token); l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); ut.expect(l_postfix_string).to_equal('AB|'); - l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression('(a|b)|c&d'); + l_input_token := ut3_develop.ut_suite_tag_filter.tokenize_tags_string('(a|b)|c&d'); + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression(l_input_token); l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); ut.expect(l_postfix_string).to_equal('ab|cd&|'); - l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression('!a|b'); + l_input_token := ut3_develop.ut_suite_tag_filter.tokenize_tags_string('!a|b'); + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression(l_input_token); l_postfix_string := ut3_develop.ut_utils.table_to_clob(l_postfix,''); ut.expect(l_postfix_string).to_equal('a!b|'); end; + procedure test_conversion_opr_by_opr is + l_postfix ut3_develop.ut_varchar2_list; + l_input_token ut3_develop.ut_varchar2_list; + begin + l_input_token := ut3_develop.ut_varchar2_list('A','B'); + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression(l_input_token); + ut.fail('Expected exception but nothing was raised'); + end; + + procedure test_conversion_oprd_by_opd is + l_postfix ut3_develop.ut_varchar2_list; + l_input_token ut3_develop.ut_varchar2_list; + begin + l_input_token := ut3_develop.ut_varchar2_list('|','|'); + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression(l_input_token); + ut.fail('Expected exception but nothing was raised'); + end; + + procedure test_conversion_lb_by_oper is + l_postfix ut3_develop.ut_varchar2_list; + l_input_token ut3_develop.ut_varchar2_list; + begin + l_input_token := ut3_develop.ut_varchar2_list('(','A','|','B',')','('); + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression(l_input_token); + ut.fail('Expected exception but nothing was raised'); + end; + + procedure test_conversion_rb_by_oprd is + l_postfix ut3_develop.ut_varchar2_list; + l_input_token ut3_develop.ut_varchar2_list; + begin + l_input_token := ut3_develop.ut_varchar2_list(')','A'); + l_postfix := ut3_develop.ut_suite_tag_filter.shunt_logical_expression(l_input_token); + ut.fail('Expected exception but nothing was raised'); + end; + procedure conv_from_rpn_to_sql_filter is l_postfix_rpn ut3_develop.ut_varchar2_list; l_infix_string varchar2(4000); diff --git a/test/ut3_tester/core/test_ut_suite_tag_filter.pks b/test/ut3_tester/core/test_ut_suite_tag_filter.pks index 093fab856..6d0b9ff69 100644 --- a/test/ut3_tester/core/test_ut_suite_tag_filter.pks +++ b/test/ut3_tester/core/test_ut_suite_tag_filter.pks @@ -3,9 +3,29 @@ create or replace package test_ut_suite_tag_filter is --%suite(ut_suite_tag_filter) --%suitepath(utplsql.ut3_tester.core) + --%context( Conversion to Reverse Polish Notation) + --%test( Test conversion of expression into Reverse Polish Notation) procedure test_conversion_to_rpn; + --%test( Operator is followed by operator) + --%throws(ut3_develop.ut_utils.gc_invalid_tag_expression) + procedure test_conversion_opr_by_opr; + + --%test( Operand is followed by operand) + --%throws(ut3_develop.ut_utils.gc_invalid_tag_expression) + procedure test_conversion_oprd_by_opd; + + --%test( Left Bracket is followed by operator) + --%throws(ut3_develop.ut_utils.gc_invalid_tag_expression) + procedure test_conversion_lb_by_oper; + + --%test( Right Bracket is followed by operand) + --%throws(ut3_develop.ut_utils.gc_invalid_tag_expression) + procedure test_conversion_rb_by_oprd; + + --%endcontext + --%test( Test conversion of expression from Reverse Polish Notation into custom where filter for SQL) procedure conv_from_rpn_to_sql_filter; From 01e53646ba0e37b02ca476832061053e5aa5e786 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 14 Apr 2023 23:21:35 -0700 Subject: [PATCH 164/187] Update tests and code --- source/core/ut_suite_tag_filter.pkb | 36 +++++++++---------- source/core/ut_suite_tag_filter.pks | 9 ++++- .../core/test_ut_suite_tag_filter.pkb | 23 ++++++------ .../core/test_ut_suite_tag_filter.pks | 4 +-- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/source/core/ut_suite_tag_filter.pkb b/source/core/ut_suite_tag_filter.pkb index d5df54212..df125091d 100644 --- a/source/core/ut_suite_tag_filter.pkb +++ b/source/core/ut_suite_tag_filter.pkb @@ -22,7 +22,9 @@ create or replace package body ut_suite_tag_filter is gc_operators constant ut_varchar2_list := ut_varchar2_list('|','&','!'); gc_unary_operators constant ut_varchar2_list := ut_varchar2_list('!'); -- right side associative operator gc_binary_operators constant ut_varchar2_list := ut_varchar2_list('|','&'); -- left side associative operator - + gc_tags_column_name constant varchar2(250) := 'tags'; + gc_exception_msg constant varchar2(200) := 'Invalid tag expression'; + type t_precedence_table is table of number index by varchar2(1); g_precedence t_precedence_table; @@ -101,7 +103,7 @@ create or replace package body ut_suite_tag_filter is l_token := a_tags(l_idx); if (l_token member of gc_operators and l_token member of gc_binary_operators) then if not(l_expect_operator) then - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + raise_application_error(ut_utils.gc_invalid_tag_expression, gc_exception_msg); end if; while l_operator_stack.top > 0 and (g_precedence(l_operator_stack.peek) > g_precedence(l_token)) loop l_rnp_tokens.extend; @@ -112,21 +114,21 @@ create or replace package body ut_suite_tag_filter is l_expect_operator:= false; elsif (l_token member of gc_operators and l_token member of gc_unary_operators) then if not(l_expect_operand) then - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + raise_application_error(ut_utils.gc_invalid_tag_expression, gc_exception_msg); end if; l_operator_stack.push(a_tags(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif l_token = '(' then if not(l_expect_operand) then - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + raise_application_error(ut_utils.gc_invalid_tag_expression, gc_exception_msg); end if; l_operator_stack.push(a_tags(l_idx)); l_expect_operand := true; l_expect_operator:= false; elsif l_token = ')' then if not(l_expect_operator) then - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + raise_application_error(ut_utils.gc_invalid_tag_expression, gc_exception_msg); end if; while l_operator_stack.peek <> '(' loop l_rnp_tokens.extend; @@ -137,7 +139,7 @@ create or replace package body ut_suite_tag_filter is l_expect_operator:= true; else if not(l_expect_operand) then - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + raise_application_error(ut_utils.gc_invalid_tag_expression, gc_exception_msg); end if; l_rnp_tokens.extend; l_rnp_tokens(l_rnp_tokens.last) :=l_token; @@ -150,7 +152,7 @@ create or replace package body ut_suite_tag_filter is while l_operator_stack.peek is not null loop if l_operator_stack.peek in ('(',')') then - raise_application_error(ut_utils.gc_invalid_tag_expression, 'Invalid Tag expression'); + raise_application_error(ut_utils.gc_invalid_tag_expression, gc_exception_msg); end if; l_rnp_tokens.extend; l_rnp_tokens(l_rnp_tokens.last):=l_operator_stack.pop; @@ -159,13 +161,13 @@ create or replace package body ut_suite_tag_filter is return l_rnp_tokens; end shunt_logical_expression; - function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) + function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list,a_tags_column_name in varchar2) return varchar2 is l_infix_stack ut_stack := ut_stack(); l_right_side varchar2(32767); l_left_side varchar2(32767); l_infix_exp varchar2(32767); - l_member_token varchar2(20) := ' member of tags'; + l_member_token varchar2(20) := ' member of '||a_tags_column_name; l_idx pls_integer; begin l_idx := a_postfix_exp.first; @@ -173,9 +175,6 @@ create or replace package body ut_suite_tag_filter is --If token is operand but also single tag if regexp_count(a_postfix_exp(l_idx),'[!()|&]') = 0 then l_infix_stack.push(q'[']'||a_postfix_exp(l_idx)||q'[']'||l_member_token); - --If token is operand but containing other expressions - elsif a_postfix_exp(l_idx) not member of gc_operators then - l_infix_stack.push(a_postfix_exp(l_idx)); --If token is unary operator not elsif a_postfix_exp(l_idx) member of gc_unary_operators then l_right_side := l_infix_stack.pop; @@ -197,10 +196,9 @@ create or replace package body ut_suite_tag_filter is function create_where_filter(a_tags varchar2 ) return varchar2 is l_tags varchar2(4000); - l_tokenized_tags ut_varchar2_list; begin l_tags := replace(replace_legacy_tag_notation(a_tags),' '); - l_tags := conv_postfix_to_infix_sql(shunt_logical_expression(tokenize_tags_string(l_tags))); + l_tags := conv_postfix_to_infix_sql(shunt_logical_expression(tokenize_tags_string(l_tags)),gc_tags_column_name); l_tags := replace(l_tags, '|',' or '); l_tags := replace(l_tags ,'&',' and '); l_tags := replace(l_tags ,'!','not'); @@ -224,7 +222,7 @@ create or replace package body ut_suite_tag_filter is q'[ with suites_mv as ( - select c.id,value(c) as obj,c.path as path,c.self_type,c.object_owner,c.tags + select c.id,value(c) as obj,c.path as path,c.self_type,c.object_owner,c.tags as ]'||gc_tags_column_name||q'[ from table(:suite_items) c ), suites_matching_expr as ( @@ -234,17 +232,17 @@ with and ]'||l_tags||q'[ ), tests_matching_expr as ( - select c.id,c.path as path,c.self_type,c.object_owner,c.tags - from suites_mv c where c.self_type in ('UT_TEST') + select c.id,c.path as path,c.self_type,c.object_owner,c.tags as ]'||gc_tags_column_name||q'[ + from suites_mv c where c.self_type in ('UT_TEST') and ]'||l_tags||q'[ ), tests_with_tags_inh_from_suite as ( - select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner + select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags as ]'||gc_tags_column_name||q'[ ,c.object_owner from suites_mv c join suites_matching_expr t on (c.path||'.' like t.path || '.%' /*all descendants and self*/ and c.object_owner = t.object_owner) ), tests_with_tags_prom_to_suite as ( - select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags tags,c.object_owner + select c.id,c.self_type,c.path,c.tags multiset union distinct t.tags as ]'||gc_tags_column_name||q'[ ,c.object_owner from suites_mv c join tests_matching_expr t on (t.path||'.' like c.path || '.%' /*all ancestors and self*/ and c.object_owner = t.object_owner) ) diff --git a/source/core/ut_suite_tag_filter.pks b/source/core/ut_suite_tag_filter.pks index 37ba19111..e824ae275 100644 --- a/source/core/ut_suite_tag_filter.pks +++ b/source/core/ut_suite_tag_filter.pks @@ -37,8 +37,15 @@ create or replace package ut_suite_tag_filter authid definer is * Function that converts postfix notation into infix and creating a string of sql filter * that checking a tags collections for tags according to posted logic. */ - function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list) return varchar2; + function conv_postfix_to_infix_sql(a_postfix_exp in ut_varchar2_list,a_tags_column_name in varchar2) + return varchar2; + /* + * Generates a part where clause sql + */ + function create_where_filter(a_tags varchar2) + return varchar2; + function apply( a_unfiltered_rows ut_suite_cache_rows, a_tags varchar2 := null diff --git a/test/ut3_tester/core/test_ut_suite_tag_filter.pkb b/test/ut3_tester/core/test_ut_suite_tag_filter.pkb index a396c6d25..edfb27cfc 100644 --- a/test/ut3_tester/core/test_ut_suite_tag_filter.pkb +++ b/test/ut3_tester/core/test_ut_suite_tag_filter.pkb @@ -62,21 +62,20 @@ create or replace package body test_ut_suite_tag_filter is ut.fail('Expected exception but nothing was raised'); end; - procedure conv_from_rpn_to_sql_filter is - l_postfix_rpn ut3_develop.ut_varchar2_list; - l_infix_string varchar2(4000); + procedure conv_from_tag_to_sql_filter is + l_sql_filter varchar2(4000); begin - l_postfix_rpn := ut3_develop.ut_varchar2_list('A'); - l_infix_string := ut3_develop.ut_suite_tag_filter.conv_postfix_to_infix_sql(l_postfix_rpn); - ut.expect(l_infix_string).to_equal(q'['A' member of tags]'); + l_sql_filter := ut3_develop.ut_suite_tag_filter.create_where_filter('test1'); + ut.expect(l_sql_filter).to_equal(q'['test1' member of tags]'); - l_postfix_rpn := ut3_develop.ut_varchar2_list('A','B','|'); - l_infix_string := ut3_develop.ut_suite_tag_filter.conv_postfix_to_infix_sql(l_postfix_rpn); - ut.expect(l_infix_string).to_equal(q'[('A' member of tags|'B' member of tags)]'); + l_sql_filter := ut3_develop.ut_suite_tag_filter.create_where_filter('test1|test2'); + ut.expect(l_sql_filter).to_equal(q'[('test1' member of tags or 'test2' member of tags)]'); - l_postfix_rpn := ut3_develop.ut_varchar2_list('a','b','!','|'); - l_infix_string := ut3_develop.ut_suite_tag_filter.conv_postfix_to_infix_sql(l_postfix_rpn); - ut.expect(l_infix_string).to_equal(q'[('a' member of tags|!('b' member of tags))]'); + l_sql_filter := ut3_develop.ut_suite_tag_filter.create_where_filter('test1|!test2'); + ut.expect(l_sql_filter).to_equal(q'[('test1' member of tags or not('test2' member of tags))]'); + + l_sql_filter := ut3_develop.ut_suite_tag_filter.create_where_filter('test1&!test2'); + ut.expect(l_sql_filter).to_equal(q'[('test1' member of tags and not('test2' member of tags))]'); end; end test_ut_suite_tag_filter; diff --git a/test/ut3_tester/core/test_ut_suite_tag_filter.pks b/test/ut3_tester/core/test_ut_suite_tag_filter.pks index 6d0b9ff69..0f84b751b 100644 --- a/test/ut3_tester/core/test_ut_suite_tag_filter.pks +++ b/test/ut3_tester/core/test_ut_suite_tag_filter.pks @@ -26,8 +26,8 @@ create or replace package test_ut_suite_tag_filter is --%endcontext - --%test( Test conversion of expression from Reverse Polish Notation into custom where filter for SQL) - procedure conv_from_rpn_to_sql_filter; + --%test( Test conversion of expression from tag into custom where filter for SQL) + procedure conv_from_tag_to_sql_filter; end test_ut_suite_tag_filter; / From dc0b4a60dfa799b360245bc7c39480e11861f564 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 17 Apr 2023 19:37:03 -0700 Subject: [PATCH 165/187] Addressing changes via PR review. --- docs/userguide/annotations.md | 40 +----------- docs/userguide/running-unit-tests.md | 90 +++++++++++++++++++------- source/core/ut_suite_cache_manager.pkb | 14 +--- source/core/ut_suite_cache_manager.pks | 9 ++- source/core/ut_suite_manager.pkb | 5 +- 5 files changed, 75 insertions(+), 83 deletions(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 552b02b52..17fb7d1f2 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1617,46 +1617,8 @@ or Tags are defined as a comma separated list within the `--%tags` annotation. When a suite/context is tagged, all of its children will automatically inherit the tag and get executed along with the parent, unless they are excluded explicitly at runtime with a negated tag expression. -Parent suite tests are not executed, but a suitepath hierarchy is kept. +See [running unit tests](running-unit-tests.md) for more information on using tags to filter test suites that are to be executed. -Sample test suite package with tags. -```sql linenums="1" -create or replace package ut_sample_test is - - --%suite(Sample Test Suite) - --%tags(api) - - --%test(Compare Ref Cursors) - --%tags(complex,fast) - procedure ut_refcursors1; - - --%test(Run equality test) - --%tags(simple,fast) - procedure ut_test; - -end ut_sample_test; -/ - -create or replace package body ut_sample_test is - - procedure ut_refcursors1 is - v_actual sys_refcursor; - v_expected sys_refcursor; - begin - open v_expected for select 1 as test from dual; - open v_actual for select 2 as test from dual; - - ut.expect(v_actual).to_equal(v_expected); - end; - - procedure ut_test is - begin - ut.expect(1).to_equal(0); - end; - -end ut_sample_test; -/ -``` #### Tag naming convention Tags must follow the below naming convention: diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 9abc7c964..7597ae72a 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -323,7 +323,7 @@ Multiple tags are separated by comma. ### Tag Expressions -Tag expressions are boolean expressions with the operators !, & and |. In addition, ( and ) can be used to adjust for operator precedence. +Tag expressions are boolean expressions created by combining tags with the `!`, `&`, `|` operators. Tag expressions can be grouped using `(` and `)` braces. Grouping tag expressions affects operator precedence. | Operator | Meaning | | -------- | --------| @@ -338,18 +338,76 @@ If you are tagging your tests across multiple dimensions, tag expressions help y | -------- | --------| | product | all tests for product | | catalog \| shipping | all tests for catalog plus all tests for shipping | -| catalog & shipping | all tests for the intersection between catalog and shipping | -| product & !end-to-end | all tests for product, but not the end-to-end tests | +| catalog & shipping | all tests that are tagged with both `catalog` and `shipping` tags | +| product & !end-to-end | all tests tagged `product`, except the tests tagged `end-to-end` | | (micro \| integration) & (product \| shipping) | all micro or integration tests for product or shipping | -Execution of the test is done by using the parameter `a_tags` with tag expressions +Taking the last expression above `(micro | integration) & (product | shipping)` +| --%tags |included in run | +| -------- | --------| +| micro | no | +| integration | no | +| micro | no | +| product | no | +| shipping | no | +| micro | no | +| micro, integration | no | +| product, shipping | no | +| micro, product | yes | +| micro, shipping | yes | +| integration, product | yes | +| integration, shipping | yes | +| integration, micro, shipping | yes | +| integration, micro, product | yes | +| integration, shipping ,product | yes | +| micro, shipping ,product | yes | +| integration, micro, shipping ,product | yes | + + +### Sample execution of test with tags. + +Execution of the test with tag expressions is done using the parameter `a_tags`. +Given a test package `ut_sample_test` defined below ```sql linenums="1" -select * from table(ut.run(a_tags => 'fast|!complex')); +create or replace package ut_sample_test is + + --%suite(Sample Test Suite) + --%tags(api) + + --%test(Compare Ref Cursors) + --%tags(complex,fast) + procedure ut_refcursors1; + + --%test(Run equality test) + --%tags(simple,fast) + procedure ut_test; + +end ut_sample_test; +/ + +create or replace package body ut_sample_test is + + procedure ut_refcursors1 is + v_actual sys_refcursor; + v_expected sys_refcursor; + begin + open v_expected for select 1 as test from dual; + open v_actual for select 2 as test from dual; + + ut.expect(v_actual).to_equal(v_expected); + end; + + procedure ut_test is + begin + ut.expect(1).to_equal(0); + end; + +end ut_sample_test; +/ ``` -The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` because a suite meet expression condition. ```sql linenums="1" select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'api')); @@ -357,9 +415,9 @@ select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'api')); The above call will execute all tests from `ut_sample_test` package as the whole suite is tagged with `api` ```sql linenums="1" -select * from table(ut.run(a_tags => 'complex')); +select * from table(ut.run(a_tags => 'fast&complex')); ``` -The above call will execute only the `ut_sample_test.ut_refcursors1` test, as only the test `ut_refcursors1` is tagged with `complex` +The above call will execute only the `ut_sample_test.ut_refcursors1` test, as only the test `ut_refcursors1` is tagged with `complex` and `fast` ```sql linenums="1" select * from table(ut.run(a_tags => 'fast')); @@ -376,25 +434,13 @@ Examples (based on above sample test suite) select * from table(ut.run(a_tags => '(api|fast)&!complex')); ``` -which is equivalent of legacy calling: - -```sql linenums="1" -select * from table(ut.run(a_tags => 'api,fast,-complex')); -``` - or ```sql linenums="1" -select * from table(ut.run(a_tags => '(api|fast)&(!complex&!test1)')); -``` - -which is equivalent of legacy calling: - -```sql linenums="1" -select * from table(ut.run(a_tags => 'api,fast,-complex,-test1')); +select * from table(ut.run(a_tags => '(api|fast)&!complex&!test1')); ``` -The above call will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex`. +The above call will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex` and except those suites/contexts/tests that are marked as `test1`. Given the above example package `ut_sample_test`, only `ut_sample_test.ut_test` will be executed. diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 3bb679517..680624f02 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -285,18 +285,6 @@ create or replace package body ut_suite_cache_manager is return l_results; end; - function get_cached_suites( - a_schema_paths ut_path_items, - a_random_seed positive := null - ) return ut_suite_cache_rows is - l_suite_items ut_suite_cache_rows := ut_suite_cache_rows(); - l_schema_paths ut_path_items; - begin - l_schema_paths := a_schema_paths; - l_suite_items := get_suite_items(a_schema_paths); - return l_suite_items; - end; - function get_schema_parse_time(a_schema_name varchar2) return timestamp result_cache is l_cache_parse_time timestamp; begin @@ -443,7 +431,7 @@ create or replace package body ut_suite_cache_manager is a_schema_paths ut_path_items ) return ut_suite_cache_rows is begin - return get_cached_suite_rows(get_cached_suites( a_schema_paths )); + return get_cached_suite_rows(get_suite_items(a_schema_paths)); end; function get_suite_items_info( diff --git a/source/core/ut_suite_cache_manager.pks b/source/core/ut_suite_cache_manager.pks index c217abeed..81b1e0136 100644 --- a/source/core/ut_suite_cache_manager.pks +++ b/source/core/ut_suite_cache_manager.pks @@ -58,11 +58,6 @@ create or replace package ut_suite_cache_manager authid definer is a_suites_filtered ut_suite_cache_rows ) return ut_suite_cache_rows; - function get_cached_suites( - a_schema_paths ut_path_items, - a_random_seed positive := null - ) return ut_suite_cache_rows; - function get_schema_paths(a_paths in ut_varchar2_list) return ut_path_items; /* @@ -77,6 +72,10 @@ create or replace package ut_suite_cache_manager authid definer is function get_suite_items_info( a_suite_cache_items ut_suite_cache_rows ) return ut_suite_items_info; + + function get_suite_items ( + a_schema_paths ut_path_items + ) return ut_suite_cache_rows; /* * Retrieves list of cached suite packages. diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index f8a2e002c..c46ba66b8 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -360,10 +360,7 @@ create or replace package body ut_suite_manager is l_filtered_rows ut_suite_cache_rows; l_result t_cached_suites_cursor; begin - l_unfiltered_rows := ut_suite_cache_manager.get_cached_suites( - a_schema_paths, - a_random_seed - ); + l_unfiltered_rows := ut_suite_cache_manager.get_suite_items(a_schema_paths); l_tag_filter_applied := ut_suite_tag_filter.apply(l_unfiltered_rows,a_tags); l_filtered_rows := get_filtered_cursor(ut_suite_cache_manager.get_cached_suite_rows(l_tag_filter_applied),a_skip_all_objects); From ef1c02b3eee5b3a5a71076f1db24a58765cddbda Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 18 Apr 2023 15:36:11 -0700 Subject: [PATCH 166/187] Update docs --- docs/userguide/running-unit-tests.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 7597ae72a..fb9a9f602 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -440,7 +440,13 @@ or select * from table(ut.run(a_tags => '(api|fast)&!complex&!test1')); ``` -The above call will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex` and except those suites/contexts/tests that are marked as `test1`. +which is equivalent of exclusion on whole expression + +```sql linenums="1" +select * from table(ut.run(a_tags => '(api|fast)&!(complex|test1)')); +``` + +The above calls will execute all suites/contexts/tests that are marked with any of tags `api` or `fast` except those suites/contexts/tests that are marked as `complex` and except those suites/contexts/tests that are marked as `test1`. Given the above example package `ut_sample_test`, only `ut_sample_test.ut_test` will be executed. From 1551ea5583152a0d0b726005906aa6e51f42c38a Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 25 Apr 2023 09:30:40 -0700 Subject: [PATCH 167/187] Adding any and none --- docs/userguide/annotations.md | 1 + docs/userguide/running-unit-tests.md | 75 ++++++++++++ source/core/ut_suite_tag_filter.pkb | 15 ++- test/ut3_tester_helper/run_helper.pkb | 160 +++++++++++++++++++++++++- test/ut3_user/api/test_ut_run.pkb | 25 ++++ 5 files changed, 271 insertions(+), 5 deletions(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 17fb7d1f2..4ec6de59d 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1634,6 +1634,7 @@ Tags must follow the below naming convention: - tag cannot start with a dash, e.g. `-some-stuff` is **not** a valid tag - tag cannot contain spaces, e.g. `test of batch`. To create a multi-word tag use underscores or dashes, e.g. `test_of_batch`, `test-of-batch` - leading and trailing spaces are ignored in tag name, e.g. `--%tags( tag1 , tag2 )` becomes `tag1` and `tag2` tag names +- tag cannot be one of two reserved words : `none` and `any`, any tags with that will not be considered. ### Suitepath diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index fb9a9f602..b3a974d53 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -325,6 +325,8 @@ Multiple tags are separated by comma. Tag expressions are boolean expressions created by combining tags with the `!`, `&`, `|` operators. Tag expressions can be grouped using `(` and `)` braces. Grouping tag expressions affects operator precedence. +Two special expressions are supported, `any` and `none`, which select all tests with any tags at all, and all tests without any tags, respectively. These special expressions may be combined with other expressions just like normal tags. When using `none` be aware that if the suite is tagged it will exclude any tests and children belonging to that suite. + | Operator | Meaning | | -------- | --------| | ! | not | @@ -450,6 +452,79 @@ The above calls will execute all suites/contexts/tests that are marked with any Given the above example package `ut_sample_test`, only `ut_sample_test.ut_test` will be executed. +### Sample execution with `any` and `none` + +Given a sample test package: + +```sql linenums="1" +create or replace package ut_sample_test is + + --%suite(Sample Test Suite) + + --%test(Compare Ref Cursors) + --%tags(complex,fast) + procedure ut_refcursors1; + + --%test(Run equality test) + --%tags(simple,fast) + procedure ut_test; + + --%test(Run equality test no tag) + procedure ut_test_no_tag; + +end ut_sample_test; +/ + +create or replace package body ut_sample_test is + + procedure ut_refcursors1 is + v_actual sys_refcursor; + v_expected sys_refcursor; + begin + open v_expected for select 1 as test from dual; + open v_actual for select 2 as test from dual; + + ut.expect(v_actual).to_equal(v_expected); + end; + + procedure ut_test is + begin + ut.expect(1).to_equal(0); + end; + + procedure ut_test_no_tag is + begin + ut.expect(1).to_equal(0); + end; + +end ut_sample_test; +/ +``` + +```sql linenums="1" +select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'none')); +``` + +The above call will execute tests `ut_test_no_tag` + +```sql linenums="1" +select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'any')); +``` + +The above call will execute tests `ut_test` and `ut_refcursors1` + +```sql linenums="1" +select * from table(ut.run(a_path => 'ut_sample_test',a_tags => 'none|simple')); +``` + +The above call will execute tests `ut_test_no_tag` and `ut_test` + +```sql linenums="1" +select * from table(ut.run(a_tags => 'none|!simple')); +``` + +The above call will execute tests `ut_test_no_tag` and `ut_refcursors1` + ## Keeping uncommitted data after test-run utPLSQL by default runs tests in autonomous transaction and performs automatic rollback to assure that tests do not impact one-another and do not have impact on the current session in your IDE. diff --git a/source/core/ut_suite_tag_filter.pkb b/source/core/ut_suite_tag_filter.pkb index df125091d..2d9436301 100644 --- a/source/core/ut_suite_tag_filter.pkb +++ b/source/core/ut_suite_tag_filter.pkb @@ -22,9 +22,10 @@ create or replace package body ut_suite_tag_filter is gc_operators constant ut_varchar2_list := ut_varchar2_list('|','&','!'); gc_unary_operators constant ut_varchar2_list := ut_varchar2_list('!'); -- right side associative operator gc_binary_operators constant ut_varchar2_list := ut_varchar2_list('|','&'); -- left side associative operator + gc_reserved_tag_words constant ut_varchar2_list := ut_varchar2_list('none','any'); gc_tags_column_name constant varchar2(250) := 'tags'; gc_exception_msg constant varchar2(200) := 'Invalid tag expression'; - + type t_precedence_table is table of number index by varchar2(1); g_precedence t_precedence_table; @@ -172,8 +173,17 @@ create or replace package body ut_suite_tag_filter is begin l_idx := a_postfix_exp.first; while ( l_idx is not null) loop + --If the token we got is a none or any keyword + if a_postfix_exp(l_idx) member of gc_reserved_tag_words then + + l_infix_stack.push( + case + when a_postfix_exp(l_idx) = 'none' then '('||a_tags_column_name||' is empty or '||a_tags_column_name||' is null)' + else a_tags_column_name||' is not empty' + end + ); --If token is operand but also single tag - if regexp_count(a_postfix_exp(l_idx),'[!()|&]') = 0 then + elsif regexp_count(a_postfix_exp(l_idx),'[!()|&]') = 0 then l_infix_stack.push(q'[']'||a_postfix_exp(l_idx)||q'[']'||l_member_token); --If token is unary operator not elsif a_postfix_exp(l_idx) member of gc_unary_operators then @@ -256,7 +266,6 @@ with where ]'||l_tags||q'[ ) ) t where c.id = t.id and r_num = 1 ]'; - execute immediate l_sql bulk collect into l_suite_tags using a_suite_items; return l_suite_tags; end; diff --git a/test/ut3_tester_helper/run_helper.pkb b/test/ut3_tester_helper/run_helper.pkb index c73564798..6289b1642 100644 --- a/test/ut3_tester_helper/run_helper.pkb +++ b/test/ut3_tester_helper/run_helper.pkb @@ -431,12 +431,162 @@ create or replace package body run_helper is end test_tag_pkg_3; ]'; + execute immediate q'[create or replace package suite1_level1_pkg is + + --%suite(suite1_level1) + --%suitepath(any_none) + --%rollback(manual) + + --%test(Test 1 from Suite1 on level 1) + --%tags(suite1,level1,test1,test1_level1) + procedure test1_level1; + + --%test(Test 2 from Suite1 on level 1) + procedure test2_level1; + + end suite1_level1_pkg; + ]'; + + execute immediate q'[create or replace package body suite1_level1_pkg is + procedure test1_level1 is + begin + dbms_output.put_line('suite1_level1_pkg.test1_level1 executed'); + end; + procedure test2_level1 is + begin + dbms_output.put_line('suite1_level1_pkg.test2_level1 executed'); + end; + end suite1_level1_pkg; + ]'; + + execute immediate q'[create or replace package suite1_1_level2_pkg is + + --%suite(suite1_1_level2) + --%suitepath(any_none.suite1_level1) + --%rollback(manual) + + --%test(Test 1 from Suite1_2 on level 2) + --%tags(level2,test1,test1_level2) + procedure suite1_1_test1_level2; + + --%test(Test 2 from Suite1_2 on level 2) + procedure suite1_1_test2_level2; + + end suite1_1_level2_pkg; + ]'; + + execute immediate q'[create or replace package body suite1_1_level2_pkg is + procedure suite1_1_test1_level2 is + begin + dbms_output.put_line('suite1_1_level2_pkg.suite1_1_test1_level2 executed'); + end; + procedure suite1_1_test2_level2 is + begin + dbms_output.put_line('suite1_1_level2_pkg.suite1_1_test2_level2 executed'); + end; + end suite1_1_level2_pkg; + ]'; + + execute immediate q'[create or replace package suite1_2_level2_pkg is + + --%suite(suite1_2_level2) + --%tags(level2,suite1_2,suites) + --%suitepath(any_none.suite1_level1) + --%rollback(manual) + + --%test(Test 1 from Suite1_2 on level 2) + procedure suite1_2_test1_level2; + + --%test(Test 2 from Suite1_2 on level 2) + --%tags(level2,test2,test2_level2) + procedure suite1_2_test2_level1; + + end suite1_2_level2_pkg; + ]'; + + execute immediate q'[create or replace package body suite1_2_level2_pkg is + procedure suite1_2_test1_level2 is + begin + dbms_output.put_line('suite1_2_level2_pkg.suite1_2_test1_level2 executed'); + end; + procedure suite1_2_test2_level1 is + begin + dbms_output.put_line('suite1_2_level2_pkg.suite1_2_test2_level1 executed'); + end; + end suite1_2_level2_pkg; + ]'; + + execute immediate q'[create or replace package suite2_level1_pkg is + + --%suite(suite2_level1) + --%tags(level1,suite2,suites) + --%suitepath(any_none) + --%rollback(manual) + + --%test(Test 1 from Suite1 on level 1) + --%tags(suite2,level1,test1,test1_level1) + procedure test1_level1; + + --%test(Test 2 from Suite1 on level 1) + procedure test2_level1; + + end suite2_level1_pkg; + ]'; + + execute immediate q'[create or replace package body suite2_level1_pkg is + procedure test1_level1 is + begin + dbms_output.put_line('suite2_level1_pkg.test1_level1 executed'); + end; + procedure test2_level1 is + begin + dbms_output.put_line('suite2_level1_pkg.test2_level1 executed'); + end; + end suite2_level1_pkg; + ]'; + + execute immediate q'[create or replace package suite2_2_level2_pkg is + + --%suite(suite2_2_level2) + --%tags(level2,suite2_2,suites) + --%suitepath(any_none.suite2_level1) + --%rollback(manual) + + --%test(Test 1 from Suite2_2 on level 2) + procedure suite2_2_test1_level2; + + --%test(Test 2 from Suite2_2 on level 2) + --%tags(level2,test2,test2_level2) + procedure suite2_2_test2_level2; + + end suite2_2_level2_pkg; + ]'; + + execute immediate q'[create or replace package body suite2_2_level2_pkg is + procedure suite2_2_test1_level2 is + begin + dbms_output.put_line('suite2_2_level2_pkg.suite2_2_test1_level2 executed'); + end; + procedure suite2_2_test2_level2 is + begin + dbms_output.put_line('suite2_2_level2_pkg.suite2_2_test2_level2 executed'); + end; + end suite2_2_level2_pkg; + ]'; + + execute immediate q'[grant execute on test_package_1 to public]'; execute immediate q'[grant execute on test_package_2 to public]'; execute immediate q'[grant execute on test_package_3 to public]'; execute immediate q'[grant execute on test_tag_pkg_1 to public]'; execute immediate q'[grant execute on test_tag_pkg_2 to public]'; - execute immediate q'[grant execute on test_tag_pkg_3 to public]'; + execute immediate q'[grant execute on test_tag_pkg_3 to public]'; + + execute immediate q'[grant execute on suite1_level1_pkg to public]'; + execute immediate q'[grant execute on suite1_1_level2_pkg to public]'; + execute immediate q'[grant execute on suite1_2_level2_pkg to public]'; + execute immediate q'[grant execute on suite2_level1_pkg to public]'; + execute immediate q'[grant execute on suite2_2_level2_pkg to public]'; end; procedure drop_ut3_user_tests is @@ -447,7 +597,13 @@ create or replace package body run_helper is execute immediate q'[drop package test_package_3]'; execute immediate q'[drop package test_tag_pkg_1]'; execute immediate q'[drop package test_tag_pkg_2]'; - execute immediate q'[drop package test_tag_pkg_3]'; + execute immediate q'[drop package test_tag_pkg_3]'; + + execute immediate q'[drop package suite2_2_level2_pkg]'; + execute immediate q'[drop package suite2_level1_pkg]'; + execute immediate q'[drop package suite1_2_level2_pkg]'; + execute immediate q'[drop package suite1_level1_pkg]'; + execute immediate q'[drop package suite1_1_level2_pkg]'; end; procedure create_test_suite is diff --git a/test/ut3_user/api/test_ut_run.pkb b/test/ut3_user/api/test_ut_run.pkb index 25b50343e..e80235744 100644 --- a/test/ut3_user/api/test_ut_run.pkb +++ b/test/ut3_user/api/test_ut_run.pkb @@ -1244,6 +1244,31 @@ procedure tag_exclude_run_fun_pth_lst_lg is ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test3%executed%' ); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_2.test4%executed%' ); ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%test_package_3.test6%executed%' ); + + l_results := ut3_tester_helper.run_helper.run(a_tags => 'any'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite2_level1_pkg.test1_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite2_level1_pkg.test2_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_level1_pkg.test1_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite2_2_level2_pkg.suite2_2_test1_level2 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite2_2_level2_pkg.suite2_2_test2_level2 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_2_level2_pkg.suite1_2_test1_level2 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_2_level2_pkg.suite1_2_test2_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_1_level2_pkg.suite1_1_test1_level2 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_level1_pkg.test2_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_1_level2_pkg.suite1_1_test2_level2 executed%' ); + + l_results := ut3_tester_helper.run_helper.run(a_tags => 'none'); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_level1_pkg.test2_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).to_be_like( '%suite1_1_level2_pkg.suite1_1_test2_level2 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite2_level1_pkg.test1_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite2_level1_pkg.test2_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_level1_pkg.test1_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite2_2_level2_pkg.suite2_2_test1_level2 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite2_2_level2_pkg.suite2_2_test2_level2 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_2_level2_pkg.suite1_2_test1_level2 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_2_level2_pkg.suite1_2_test2_level1 executed%' ); + ut.expect( ut3_tester_helper.main_helper.table_to_clob(l_results) ).not_to_be_like( '%suite1_1_level2_pkg.suite1_1_test1_level2 executed%' ); + end; From 9dee7e0ffd4bfee0af948befd4f6b739506c11d1 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 25 Apr 2023 17:08:42 -0700 Subject: [PATCH 168/187] Update docs --- docs/userguide/running-unit-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index b3a974d53..044ffdb35 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -325,7 +325,7 @@ Multiple tags are separated by comma. Tag expressions are boolean expressions created by combining tags with the `!`, `&`, `|` operators. Tag expressions can be grouped using `(` and `)` braces. Grouping tag expressions affects operator precedence. -Two special expressions are supported, `any` and `none`, which select all tests with any tags at all, and all tests without any tags, respectively. These special expressions may be combined with other expressions just like normal tags. When using `none` be aware that if the suite is tagged it will exclude any tests and children belonging to that suite. +Two special expressions are supported, `any` and `none`, which select all tests with any tags at all, and all tests without any tags, respectively. These special expressions may be combined with other expressions just like normal tags. When using `none` be aware that if the suite is tagged it will exclude any tests and suites below. | Operator | Meaning | | -------- | --------| From beb9a3a3207e208b7e5e2687b6d4751b4ee705b9 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 26 Apr 2023 17:30:32 -0700 Subject: [PATCH 169/187] Resolving PR --- docs/userguide/annotations.md | 2 +- docs/userguide/running-unit-tests.md | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 4ec6de59d..7c7015872 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1634,7 +1634,7 @@ Tags must follow the below naming convention: - tag cannot start with a dash, e.g. `-some-stuff` is **not** a valid tag - tag cannot contain spaces, e.g. `test of batch`. To create a multi-word tag use underscores or dashes, e.g. `test_of_batch`, `test-of-batch` - leading and trailing spaces are ignored in tag name, e.g. `--%tags( tag1 , tag2 )` becomes `tag1` and `tag2` tag names -- tag cannot be one of two reserved words : `none` and `any`, any tags with that will not be considered. +- tag cannot be one of two reserved words: `none` and `any`. `none` and `any` as a tag will be treated as no tag ### Suitepath diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 044ffdb35..e12fd6b32 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -325,7 +325,13 @@ Multiple tags are separated by comma. Tag expressions are boolean expressions created by combining tags with the `!`, `&`, `|` operators. Tag expressions can be grouped using `(` and `)` braces. Grouping tag expressions affects operator precedence. -Two special expressions are supported, `any` and `none`, which select all tests with any tags at all, and all tests without any tags, respectively. These special expressions may be combined with other expressions just like normal tags. When using `none` be aware that if the suite is tagged it will exclude any tests and suites below. +Two reserved keywords, `any` and `none`, can be used when creating a tag expression to run tests. +- `any` keyword represents tests and suites with any tags +- `none` keyword represents tests and suites without tags + +These keywords may be combined with other expressions just like normal tags. + +**Note:** When specifying `none`, be aware that it will exclude any tests/suites/contexts contained within a tagged suite. | Operator | Meaning | | -------- | --------| From 46ffe739386b92dc831a46227c17326bb85f459e Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Thu, 27 Apr 2023 11:48:26 -0700 Subject: [PATCH 170/187] Update note --- docs/userguide/running-unit-tests.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index e12fd6b32..2b18a3d3b 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -331,7 +331,8 @@ Two reserved keywords, `any` and `none`, can be used when creating a tag express These keywords may be combined with other expressions just like normal tags. -**Note:** When specifying `none`, be aware that it will exclude any tests/suites/contexts contained within a tagged suite. +!!! note + When specifying `none`, be aware that it will exclude any tests/suites/contexts contained within a tagged suite. | Operator | Meaning | | -------- | --------| From 73e9cf32bce4f0b8dbd38f7da63ad253b0ae42b6 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Thu, 27 Apr 2023 22:09:18 +0300 Subject: [PATCH 171/187] Added missing test for multiple expectation failures with exception thrown. --- test/ut3_user/reporters.pkb | 5 +-- .../reporters/test_teamcity_reporter.pkb | 37 ++++++++++++++++++- .../reporters/test_teamcity_reporter.pks | 5 ++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/test/ut3_user/reporters.pkb b/test/ut3_user/reporters.pkb index b6d43b144..031683615 100644 --- a/test/ut3_user/reporters.pkb +++ b/test/ut3_user/reporters.pkb @@ -90,11 +90,10 @@ as procedure erroring_test is - l_variable integer; + l_integer_variable integer; begin dbms_output.put_line(''); - l_variable := 'a string'; - ut3_develop.ut.expect(l_variable).to_equal(1); + l_integer_variable := 'a string'; end; procedure disabled_test diff --git a/test/ut3_user/reporters/test_teamcity_reporter.pkb b/test/ut3_user/reporters/test_teamcity_reporter.pkb index 7c4c1e513..517ddc037 100644 --- a/test/ut3_user/reporters/test_teamcity_reporter.pkb +++ b/test/ut3_user/reporters/test_teamcity_reporter.pkb @@ -36,6 +36,9 @@ create or replace package body test_teamcity_reporter as --%test procedure multi_failure; + + --%test + procedure multi_failure_on_error; end;]'; execute immediate q'[create or replace package body check_multiple_failures is procedure multi_failure is @@ -44,6 +47,14 @@ create or replace package body test_teamcity_reporter as ut3_develop.ut.expect(2).to_equal(1); ut3_develop.ut.expect('Bad').to_equal('Good'); end; + procedure multi_failure_on_error is + l_integer_variable integer; + begin + ut3_develop.ut.expect(1).to_be_null; + ut3_develop.ut.expect(2).to_equal(1); + ut3_develop.ut.expect('Bad').to_equal('Good'); + l_integer_variable := 'a string'; + end; end;]'; end; @@ -132,7 +143,7 @@ create or replace package body test_teamcity_reporter as ut.expect(ut3_tester_helper.main_helper.table_to_clob(l_output_data)).to_be_like(l_expected); end; - procedure report_mutiple_expectations is + procedure report_multiple_expectations is l_output_data ut3_develop.ut_varchar2_list; l_expected varchar2(32767); begin @@ -146,7 +157,29 @@ create or replace package body test_teamcity_reporter as --act select * bulk collect into l_output_data - from table(ut3_develop.ut.run('check_multiple_failures',ut3_develop.ut_teamcity_reporter())); + from table(ut3_develop.ut.run('check_multiple_failures.multi_failure',ut3_develop.ut_teamcity_reporter())); + + --assert + ut.expect(ut3_tester_helper.main_helper.table_to_clob(l_output_data)).to_be_like(l_expected); + end; + + procedure report_multiple_expect_on_err is + l_output_data ut3_develop.ut_varchar2_list; + l_expected varchar2(32767); + begin + l_expected := q'{%##teamcity[testSuiteStarted timestamp='%' name='check_multiple_failures'] +%##teamcity[testStarted timestamp='%' captureStandardOutput='true' name='ut3_user.check_multiple_failures.multi_failure_on_error'] +%##teamcity[testStdErr timestamp='%' name='ut3_user.check_multiple_failures.multi_failure_on_error' out='Test exception:|nORA-06502: PL/SQL: %: character to number conversion error|nORA-06512: at "UT3_USER.CHECK_MULTIPLE_FAILURES", line %|nORA-06512: at %|n'] +%##teamcity[testFailed timestamp='%' details='Test exception:|nORA-06502: PL/SQL: %: character to number conversion error|nORA-06512: at "UT3_USER.CHECK_MULTIPLE_FAILURES", line %|nORA-06512: at %|n' message='Error occured' name='ut3_user.check_multiple_failures.multi_failure_on_error'] +%##teamcity[testFailed timestamp='%' details='Actual: 1 (number) was expected to be null' name='ut3_user.check_multiple_failures.multi_failure_on_error'] +%##teamcity[testFailed timestamp='%' details='Actual: 2 (number) was expected to equal: 1 (number)' name='ut3_user.check_multiple_failures.multi_failure_on_error'] +%##teamcity[testFailed timestamp='%' details='Actual: |'Bad|' (varchar2) was expected to equal: |'Good|' (varchar2)' name='ut3_user.check_multiple_failures.multi_failure_on_error'] +%##teamcity[testFinished timestamp='%' duration='%' name='ut3_user.check_multiple_failures.multi_failure_on_error'] +%##teamcity[testSuiteFinished timestamp='%' name='check_multiple_failures']}'; + --act + select * + bulk collect into l_output_data + from table(ut3_develop.ut.run('check_multiple_failures.multi_failure_on_error',ut3_develop.ut_teamcity_reporter())); --assert ut.expect(ut3_tester_helper.main_helper.table_to_clob(l_output_data)).to_be_like(l_expected); diff --git a/test/ut3_user/reporters/test_teamcity_reporter.pks b/test/ut3_user/reporters/test_teamcity_reporter.pks index 30ae7e26b..1b9277e7a 100644 --- a/test/ut3_user/reporters/test_teamcity_reporter.pks +++ b/test/ut3_user/reporters/test_teamcity_reporter.pks @@ -16,7 +16,10 @@ create or replace package test_teamcity_reporter as procedure trims_long_output; --%test(Reports failures on multiple expectations) - procedure report_mutiple_expectations; + procedure report_multiple_expectations; + + --%test(Reports failures on multiple expectations) + procedure report_multiple_expect_on_err; --%afterall procedure remove_test_package; From 6a32cbd572dd9cbbcb8858a32693cd6f41376267 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 28 Apr 2023 10:29:06 +0100 Subject: [PATCH 172/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index a47004a3c..afdf64bdd 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 8b6437299..37bc28342 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 02eabab07..c4a36c2fc 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index aacb289f2..450bde3ad 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 5e30a9fc6..926b89912 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 8db920ee7..2efea8de6 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 7c7015872..0ef65a9e8 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index b83fb78c3..3582c1968 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 04b3db380..35cdd3a3f 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index a7b0ae0a5..bbda24125 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 2b436250e..af07865b1 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 37c22c882..afd4ad124 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 00a74b288..7e6af19cd 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 164c0cbc0..0a5584ba9 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index e92558e3d..ca62b674e 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 2b18a3d3b..a24145f82 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 794e75070..160c51fd4 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4105--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index b60fc4cdf..954d4f8be 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4105-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4167-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 962f6fd4446d8369af56360dcc591e2a7cc919f7 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 21 May 2023 12:54:53 +0300 Subject: [PATCH 173/187] Resolves #1252 Replaced all regexp ranges with posix representations to avoid NLS_SORT impact on regex behavior. --- .../core/annotations/ut_annotation_manager.pkb | 2 +- .../core/annotations/ut_annotation_parser.pkb | 2 +- source/core/types/ut_executable_test.tpb | 2 +- source/core/ut_expectation_processor.pkb | 12 ++++++------ source/core/ut_metadata.pkb | 2 +- source/core/ut_suite_cache_manager.pkb | 4 ++-- source/core/ut_suite_manager.pkb | 8 ++++---- source/core/ut_utils.pkb | 6 +++--- test/ut3_tester/core/test_suite_manager.pkb | 17 +++++++++++++++++ test/ut3_tester/core/test_suite_manager.pks | 10 ++++++++++ 10 files changed, 46 insertions(+), 19 deletions(-) diff --git a/source/core/annotations/ut_annotation_manager.pkb b/source/core/annotations/ut_annotation_manager.pkb index 16923bc23..65f7b3e40 100644 --- a/source/core/annotations/ut_annotation_manager.pkb +++ b/source/core/annotations/ut_annotation_manager.pkb @@ -246,7 +246,7 @@ create or replace package body ut_annotation_manager as l_sql_clob := regexp_replace(l_sql_clob, '^(.*?\s*create(\s+or\s+replace)?(\s+(editionable|noneditionable))?\s+?)((package|type).*)', '\5', 1, 1, 'ni'); -- remove "OWNER." from create or replace statement. -- Owner is not supported along with AUTHID - see issue https://github.com/utPLSQL/utPLSQL/issues/1088 - l_sql_clob := regexp_replace(l_sql_clob, '^(package|type)\s+("?[a-zA-Z][a-zA-Z0-9#_$]*"?\.)(.*)', '\1 \3', 1, 1, 'ni'); + l_sql_clob := regexp_replace(l_sql_clob, '^(package|type)\s+("?[[:alpha:]][[:alnum:]$#_]*"?\.)(.*)', '\1 \3', 1, 1, 'ni'); l_sql_lines := ut_utils.convert_collection( ut_utils.clob_to_table(l_sql_clob) ); end if; open l_result for diff --git a/source/core/annotations/ut_annotation_parser.pkb b/source/core/annotations/ut_annotation_parser.pkb index f0271c957..10bb76b3c 100644 --- a/source/core/annotations/ut_annotation_parser.pkb +++ b/source/core/annotations/ut_annotation_parser.pkb @@ -25,7 +25,7 @@ create or replace package body ut_annotation_parser as gc_annot_comment_pattern constant varchar2(30) := '^( |'||chr(09)||')*-- *('||gc_annotation_qualifier||'.*?)$'; -- chr(09) is a tab character gc_comment_replacer_patter constant varchar2(50) := '{COMMENT#%N%}'; gc_comment_replacer_regex_ptrn constant varchar2(25) := '{COMMENT#(\d+)}'; - gc_regexp_identifier constant varchar2(50) := '[a-zA-Z][a-zA-Z0-9#_$]*'; + gc_regexp_identifier constant varchar2(50) := '[[:alpha:]][[:alnum:]$#_]*'; gc_annotation_block_pattern constant varchar2(200) := '(({COMMENT#.+}'||chr(10)||')+)( |'||chr(09)||')*(procedure|function)\s+(' || gc_regexp_identifier || ')'; gc_annotation_pattern constant varchar2(50) := gc_annotation_qualifier || gc_regexp_identifier || '[ '||chr(9)||']*(\(.*?\)\s*?$)?'; diff --git a/source/core/types/ut_executable_test.tpb b/source/core/types/ut_executable_test.tpb index c5a7f29a1..fa5872e04 100644 --- a/source/core/types/ut_executable_test.tpb +++ b/source/core/types/ut_executable_test.tpb @@ -159,7 +159,7 @@ create or replace type body ut_executable_test as if self.error_stack is null then l_fail_message := 'Expected one of exceptions ('||l_expected_error_codes||') but nothing was raised.'; else - l_actual_error_no := regexp_substr(self.error_stack, '^[a-zA-Z]{3}(-[0-9]+)', subexpression=>1); + l_actual_error_no := regexp_substr(self.error_stack, '^[[:alpha:]]{3}(-[0-9]+)', subexpression=>1); if not l_actual_error_no member of a_expected_error_codes or l_actual_error_no is null then l_fail_message := 'Actual: '||l_actual_error_no||' was expected to '; if cardinality(a_expected_error_codes) > 1 then diff --git a/source/core/ut_expectation_processor.pkb b/source/core/ut_expectation_processor.pkb index 77b734b30..c165a9ee5 100644 --- a/source/core/ut_expectation_processor.pkb +++ b/source/core/ut_expectation_processor.pkb @@ -159,17 +159,17 @@ create or replace package body ut_expectation_processor as -- when 11g and 12c reports only package name function cut_header_and_expectations( a_stack varchar2 ) return varchar2 is begin - return regexp_substr( a_stack, '(.*\.(UT_EQUAL|UT_BE_WITHIN[A-Z0-9#_$]*|UT_EXPECTATION[A-Z0-9#_$]*|UT|UTASSERT2?)(\.[A-Z0-9#_$]+)?\s+)+((.|\s)*)', 1, 1, 'm', 4); + return regexp_substr( a_stack, '(.*\.(UT_EQUAL|UT_BE_WITHIN[[:alnum:]$#_]*|UT_EXPECTATION[[:alnum:]$#_]*|UT|UTASSERT2?)(\.[[:alnum:]$#_]+)?\s+)+((.|\s)*)', 1, 1, 'm', 4); end; function cut_address_columns( a_stack varchar2 ) return varchar2 is begin - return regexp_replace( a_stack, '^(0x)?[0-9a-f]+\s+', '', 1, 0, 'mi' ); + return regexp_replace( a_stack, '^(0x)?[[:digit:]abcdef]+\s+', '', 1, 0, 'mi' ); end; function cut_framework_stack( a_stack varchar2 ) return varchar2 is begin return regexp_replace( a_stack, - '[0-9]+\s+anonymous\s+block\s+[0-9]+\s+package\s+body\s+sys\.dbms_sql(\.execute)?\s+[0-9]+\s+[0-9_$#a-z ]+\.ut_executable.*', + '[0-9]+\s+anonymous\s+block\s+[0-9]+\s+package\s+body\s+sys\.dbms_sql(\.execute)?\s+[0-9]+\s+[[:alnum:]_$# ]+\.ut_executable.*', '', 1, 1, 'mni' ); @@ -178,7 +178,7 @@ create or replace package body ut_expectation_processor as begin return regexp_replace( a_stack, - '([0-9]+)\s+(.* )?((anonymous block)|(([0-9_$#a-z]+\.[0-9_$#a-z]+(\.([0-9_$#a-z])+)?)))', + '([0-9]+)\s+(.* )?((anonymous block)|(([[:alnum:]$#_]+\.[[:alnum:]$#_]+(\.([[:alnum:]$#_])+)?)))', 'at "\3", line \1', 1, 0, 'i' ); end; @@ -190,8 +190,8 @@ create or replace package body ut_expectation_processor as l_caller_stack_line := regexp_substr(l_call_stack,'^(.*)'); if l_caller_stack_line like '%.%' then l_line_no := to_number( regexp_substr( l_caller_stack_line, ', line (\d+)', subexpression => 1 ) ); - l_owner := regexp_substr( l_caller_stack_line, 'at "([A-Za-z0-9$#_]+)\.(([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_]+))?)", line (\d+)', subexpression => 1 ); - l_object_name := regexp_substr( l_caller_stack_line, 'at "([A-Za-z0-9$#_]+)\.(([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_]+))?)", line (\d+)', subexpression => 3 ); + l_owner := regexp_substr( l_caller_stack_line, 'at "([[:alnum:]$#_]+)\.(([[:alnum:]$#_]+)(\.([[:alnum:]$#_]+))?)", line (\d+)', subexpression => 1 ); + l_object_name := regexp_substr( l_caller_stack_line, 'at "([[:alnum:]$#_]+)\.(([[:alnum:]$#_]+)(\.([[:alnum:]$#_]+))?)", line (\d+)', subexpression => 3 ); l_result := l_caller_stack_line || ' ' || rtrim(ut_metadata.get_source_definition_line(l_owner, l_object_name, l_line_no),chr(10)) || replace( l_call_stack, l_caller_stack_line ); diff --git a/source/core/ut_metadata.pkb b/source/core/ut_metadata.pkb index 700c0efb0..360b7b97d 100644 --- a/source/core/ut_metadata.pkb +++ b/source/core/ut_metadata.pkb @@ -304,7 +304,7 @@ create or replace package body ut_metadata as begin l_result := regexp_substr( a_full_object_name, - '^([A-Za-z0-9$#_]+|".*?")\.([A-Za-z0-9$#_]+|".*?")', subexpression => 2 + '^([[:alnum:]$#_]+|".*?")\.([[:alnum:]$#_]+|".*?")', subexpression => 2 ); if not l_result like '"%"' then l_result := upper(l_result); diff --git a/source/core/ut_suite_cache_manager.pkb b/source/core/ut_suite_cache_manager.pkb index 680624f02..6d621c339 100644 --- a/source/core/ut_suite_cache_manager.pkb +++ b/source/core/ut_suite_cache_manager.pkb @@ -88,7 +88,7 @@ create or replace package body ut_suite_cache_manager is end; function group_paths_by_schema(a_paths ut_varchar2_list) return ut_path_items is - c_package_path_regex constant varchar2(100) := '^([A-Za-z0-9$#_]+)(\.([A-Za-z0-9$#_\*]+))?(\.([A-Za-z0-9$#_\*]+))?$'; + c_package_path_regex constant varchar2(100) := '^([[:alnum:]$#_]+)(\.([[:alnum:]$#_\*]+))?(\.([[:alnum:]$#_\*]+))?$'; l_results ut_path_items := ut_path_items(); l_path_item ut_path_item; i pls_integer; @@ -157,7 +157,7 @@ create or replace package body ut_suite_cache_manager is from schema_paths sp left outer join ut_suite_cache c on ( c.object_owner = upper(sp.schema_name) --and c.path like replace(sp.suite_path,'*','%')) - and regexp_like(c.path,'^'||replace(sp.suite_path,'*','[A-Za-z0-9$#_]*'))) + and regexp_like(c.path,'^'||replace(sp.suite_path,'*','[[:alnum:]$#_]*'))) where sp.suite_path is not null and instr(sp.suite_path,'*') > 0 ), straigth_suite_paths as ( diff --git a/source/core/ut_suite_manager.pkb b/source/core/ut_suite_manager.pkb index c46ba66b8..c418de638 100644 --- a/source/core/ut_suite_manager.pkb +++ b/source/core/ut_suite_manager.pkb @@ -32,7 +32,7 @@ create or replace package body ut_suite_manager is for i in 1 .. a_paths.count loop l_path := a_paths(i); if l_path is null or not ( - regexp_like(l_path, '^[A-Za-z0-9$#_\*]+(\.[A-Za-z0-9$#_\*]+){0,2}$') or regexp_like(l_path, '^([A-Za-z0-9$#_]+)?:[A-Za-z0-9$#_\*]+(\.[A-Za-z0-9$#_\*]+)*$')) then + regexp_like(l_path, '^[[:alnum:]$#_\*]+(\.[[:alnum:]$#_\*]+){0,2}$') or regexp_like(l_path, '^([[:alnum:]$#_]+)?:[[:alnum:]$#_\*]+(\.[[:alnum:]$#_\*]+)*$')) then raise_application_error(ut_utils.gc_invalid_path_format, 'Invalid path format: ' || nvl(l_path, 'NULL')); end if; end loop; @@ -61,9 +61,9 @@ create or replace package body ut_suite_manager is for i in 1 .. a_paths.count loop --if path is suite-path - if regexp_like(a_paths(i), '^([A-Za-z0-9$#_]+)?:') then + if regexp_like(a_paths(i), '^([[:alnum:]$#_]+)?:') then --get schema name / path - l_schema := regexp_substr(a_paths(i), '^([A-Za-z0-9$#_]+)?:',subexpression => 1); + l_schema := regexp_substr(a_paths(i), '^([[:alnum:]$#_]+)?:',subexpression => 1); -- transform ":path1[.path2]" to "schema:path1[.path2]" if l_schema is not null then l_schema := sys.dbms_assert.schema_name(upper(l_schema)); @@ -78,7 +78,7 @@ create or replace package body ut_suite_manager is -- Object name or procedure is allowed to have filter char -- However this is not allowed on schema begin - l_object := regexp_substr(a_paths(i), '^[A-Za-z0-9$#_\*]+'); + l_object := regexp_substr(a_paths(i), '^[[:alnum:]$#_\*]+'); l_schema := sys.dbms_assert.schema_name(upper(l_object)); exception when sys.dbms_assert.invalid_schema_name then diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index 6f972e11c..f29e3b188 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -19,9 +19,9 @@ create or replace package body ut_utils is /** * Constants regex used to validate XML name */ - gc_invalid_first_xml_char constant varchar2(50) := '[^_a-zA-Z]'; - gc_invalid_xml_char constant varchar2(50) := '[^_a-zA-Z0-9\.-]'; - gc_full_valid_xml_name constant varchar2(50) := '^([_a-zA-Z])([_a-zA-Z0-9\.-])*$'; + gc_invalid_first_xml_char constant varchar2(50) := '[^_[:alpha:]]'; + gc_invalid_xml_char constant varchar2(50) := '[^_[:alnum:]\.-]'; + gc_full_valid_xml_name constant varchar2(50) := '^([[:alpha:]])([_[:alnum:]\.-])*$'; gc_owner_hash constant integer(11) := dbms_utility.get_hash_value( ut_owner(), 0, power(2,31)-1); diff --git a/test/ut3_tester/core/test_suite_manager.pkb b/test/ut3_tester/core/test_suite_manager.pkb index fbac0f3f5..c818ad212 100644 --- a/test/ut3_tester/core/test_suite_manager.pkb +++ b/test/ut3_tester/core/test_suite_manager.pkb @@ -2217,5 +2217,22 @@ end;]'; end loop; end; + --%test(Path validation does not fail on Estonian NLS_SORT - fix #1252) + procedure path_validate_nls_sort is + l_schema_names ut3_develop.ut_varchar2_rows; + begin + --Arrange + execute immediate q'[alter session set nls_sort='estonian']'; + --Act + l_schema_names := ut3_develop.ut_suite_manager.get_schema_names(ut3_develop.ut_varchar2_list('ut3')); + --Asseert + ut.expect(sqlcode).to_equal(0); + end; + + + procedure reset_nls_sort is + begin + execute immediate q'[alter session set nls_sort='binary']'; + end; end test_suite_manager; / diff --git a/test/ut3_tester/core/test_suite_manager.pks b/test/ut3_tester/core/test_suite_manager.pks index d9d4efc09..ac7818f4f 100644 --- a/test/ut3_tester/core/test_suite_manager.pks +++ b/test/ut3_tester/core/test_suite_manager.pks @@ -237,5 +237,15 @@ create or replace package test_suite_manager is --%endcontext + --%context(paths validation) + + --%test(Path validation does not fail on Estonian NLS_SORT - fix #1252) + --%aftertest(reset_nls_sort) + procedure path_validate_nls_sort; + + procedure reset_nls_sort; + + --%endcontext + end test_suite_manager; / From 6589b8468ecaaf85258873e6484c0183b770dc17 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 27 May 2023 12:42:57 +0100 Subject: [PATCH 174/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index afdf64bdd..9d18766ae 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index 37bc28342..a9cd17bc9 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index c4a36c2fc..0b1b005c6 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 450bde3ad..639dc2970 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 926b89912..bd908d60c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 2efea8de6..eb3b311a5 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 0ef65a9e8..4f1c6b420 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 3582c1968..f5f889ca6 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 35cdd3a3f..dbd584a7c 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index bbda24125..cad56f1b8 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index af07865b1..67f851f36 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index afd4ad124..b2c67054e 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 7e6af19cd..4e1b3e903 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 0a5584ba9..d68240a5d 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index ca62b674e..ca3878f9f 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index a24145f82..4fdb74073 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 160c51fd4..bd401f5d9 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4167--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 954d4f8be..90c165bbb 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4167-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4171-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 8b45b0d670d7212f4e1ffbc9635a4a1b2a621cf1 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 28 May 2023 16:00:15 +0300 Subject: [PATCH 175/187] Fix output length error and output buffer. When dealing with multibyte strings, the substring limit of 4000 **chars** is not correct. We need to apply a limit of 4000 **bytes** to both VARCHAR2 and to CLOB data types. This means we need to have a function to calculate lenght of CLOB in bytes. This is now added and all the conversions/trimming/string-splitting is done using the string length in **bytes** Additionally, a different approach (with sequences) was introduced into output buffers to avoid the sometime occurring PK violation on the output buffer tables. The new approach may add a but overhead on reading from / saving into buffer, but will definitely address the threat of PK errors. Resolves #1254 Resolves #1128 Replaced all regexp ranges with posix representations to avoid NLS_SORT impact on regex behavior. --- .../output_buffers/ut_output_buffer_base.tpb | 1 - .../output_buffers/ut_output_buffer_base.tps | 1 - .../output_buffers/ut_output_buffer_tmp.sql | 1 + .../output_buffers/ut_output_bulk_buffer.tpb | 9 ++-- .../ut_output_clob_buffer_tmp.sql | 2 + .../ut_output_clob_table_buffer.tpb | 17 ++----- .../output_buffers/ut_output_table_buffer.tpb | 27 ++++------ source/core/ut_utils.pkb | 48 ++++++++++++++--- source/core/ut_utils.pks | 5 ++ source/uninstall_objects.sql | 4 ++ test/ut3_tester/core/test_output_buffer.pkb | 51 ++++++++++++++++--- test/ut3_tester/core/test_output_buffer.pks | 6 +++ test/ut3_tester/core/test_ut_utils.pkb | 18 +++++++ test/ut3_tester/core/test_ut_utils.pks | 13 +++-- 14 files changed, 149 insertions(+), 54 deletions(-) diff --git a/source/core/output_buffers/ut_output_buffer_base.tpb b/source/core/output_buffers/ut_output_buffer_base.tpb index be4c92bd8..20cec335e 100644 --- a/source/core/output_buffers/ut_output_buffer_base.tpb +++ b/source/core/output_buffers/ut_output_buffer_base.tpb @@ -24,7 +24,6 @@ create or replace type body ut_output_buffer_base is self.self_type := coalesce(a_self_type,self.self_type); self.output_id := coalesce(a_output_id, self.output_id, sys_guid()); self.start_date := coalesce(self.start_date, sysdate); - self.last_write_message_id := 0; select /*+ no_parallel */ count(*) into l_exists from ut_output_buffer_info_tmp where output_id = self.output_id; if ( l_exists > 0 ) then update /*+ no_parallel */ ut_output_buffer_info_tmp set start_date = self.start_date where output_id = self.output_id; diff --git a/source/core/output_buffers/ut_output_buffer_base.tps b/source/core/output_buffers/ut_output_buffer_base.tps index 53be365ae..f2d9ec686 100644 --- a/source/core/output_buffers/ut_output_buffer_base.tps +++ b/source/core/output_buffers/ut_output_buffer_base.tps @@ -19,7 +19,6 @@ create or replace type ut_output_buffer_base force authid definer as object( output_id raw(32), is_closed number(1,0), start_date date, - last_write_message_id number(38,0), lock_handle varchar2(30 byte), self_type varchar2(250 byte), member procedure init(self in out nocopy ut_output_buffer_base, a_output_id raw := null, a_self_type varchar2 := null), diff --git a/source/core/output_buffers/ut_output_buffer_tmp.sql b/source/core/output_buffers/ut_output_buffer_tmp.sql index 57027817e..1ab19e534 100644 --- a/source/core/output_buffers/ut_output_buffer_tmp.sql +++ b/source/core/output_buffers/ut_output_buffer_tmp.sql @@ -30,3 +30,4 @@ create table ut_output_buffer_tmp( ) organization index nologging initrans 100 overflow nologging initrans 100; +create sequence ut_output_buffer_tmp_seq cache 20; diff --git a/source/core/output_buffers/ut_output_bulk_buffer.tpb b/source/core/output_buffers/ut_output_bulk_buffer.tpb index ceae07862..cfc173e95 100644 --- a/source/core/output_buffers/ut_output_bulk_buffer.tpb +++ b/source/core/output_buffers/ut_output_bulk_buffer.tpb @@ -34,9 +34,8 @@ create or replace type body ut_output_bulk_buffer is a_item_type ); else - self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_write_message_id, a_text, a_item_type); + values (self.output_id, ut_output_buffer_tmp_seq.nextval, a_text, a_item_type); end if; commit; end if; @@ -46,10 +45,9 @@ create or replace type body ut_output_bulk_buffer is pragma autonomous_transaction; begin insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - select /*+ no_parallel */ self.output_id, self.last_write_message_id + rownum, t.column_value, a_item_type + select /*+ no_parallel */ self.output_id, ut_output_buffer_tmp_seq.nextval, t.column_value, a_item_type from table(a_text_list) t where t.column_value is not null or a_item_type is not null; - self.last_write_message_id := self.last_write_message_id + sql%rowcount; commit; end; @@ -65,9 +63,8 @@ create or replace type body ut_output_bulk_buffer is a_item_type ); else - self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_write_message_id, a_text, a_item_type); + values (self.output_id, ut_output_buffer_tmp_seq.nextval, a_text, a_item_type); end if; commit; end if; diff --git a/source/core/output_buffers/ut_output_clob_buffer_tmp.sql b/source/core/output_buffers/ut_output_clob_buffer_tmp.sql index 40dda121f..9ff9f7413 100644 --- a/source/core/output_buffers/ut_output_clob_buffer_tmp.sql +++ b/source/core/output_buffers/ut_output_clob_buffer_tmp.sql @@ -45,3 +45,5 @@ begin end; end; / + +create sequence ut_output_clob_buffer_tmp_seq cache 20; diff --git a/source/core/output_buffers/ut_output_clob_table_buffer.tpb b/source/core/output_buffers/ut_output_clob_table_buffer.tpb index c4cfdb059..3d49ab08d 100644 --- a/source/core/output_buffers/ut_output_clob_table_buffer.tpb +++ b/source/core/output_buffers/ut_output_clob_table_buffer.tpb @@ -26,9 +26,8 @@ create or replace type body ut_output_clob_table_buffer is pragma autonomous_transaction; begin if a_text is not null or a_item_type is not null then - self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_clob_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_write_message_id, a_text, a_item_type); + values (self.output_id, ut_output_clob_buffer_tmp_seq.nextval, a_text, a_item_type); end if; commit; end; @@ -37,10 +36,9 @@ create or replace type body ut_output_clob_table_buffer is pragma autonomous_transaction; begin insert /*+ no_parallel */ into ut_output_clob_buffer_tmp(output_id, message_id, text, item_type) - select /*+ no_parallel */ self.output_id, self.last_write_message_id + rownum, t.column_value, a_item_type + select /*+ no_parallel */ self.output_id, ut_output_clob_buffer_tmp_seq.nextval, t.column_value, a_item_type from table(a_text_list) t where t.column_value is not null or a_item_type is not null; - self.last_write_message_id := self.last_write_message_id + SQL%rowcount; commit; end; @@ -48,9 +46,8 @@ create or replace type body ut_output_clob_table_buffer is pragma autonomous_transaction; begin if a_text is not null and a_text != empty_clob() or a_item_type is not null then - self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_clob_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_write_message_id, a_text, a_item_type); + values (self.output_id, ut_output_clob_buffer_tmp_seq.nextval, a_text, a_item_type); end if; commit; end; @@ -60,7 +57,6 @@ create or replace type body ut_output_clob_table_buffer is l_buffer_rowids ut_varchar2_rows; l_buffer_data ut_output_data_rows; l_finished_flags ut_integer_list; - l_last_read_message_id integer; l_already_waited_sec number(10,2) := 0; l_finished boolean := false; l_sleep_time number(2,1); @@ -68,25 +64,22 @@ create or replace type body ut_output_clob_table_buffer is l_producer_started boolean := false; l_producer_finished boolean := false; procedure get_data_from_buffer_table( - a_last_read_message_id in out nocopy integer, a_buffer_data out nocopy ut_output_data_rows, a_buffer_rowids out nocopy ut_varchar2_rows, a_finished_flags out nocopy ut_integer_list ) is lc_bulk_limit constant integer := 5000; begin - a_last_read_message_id := coalesce(a_last_read_message_id, 0); with ordered_buffer as ( select /*+ no_parallel index(a) */ ut_output_data_row(a.text, a.item_type), rowidtochar(a.rowid), is_finished from ut_output_clob_buffer_tmp a where a.output_id = self.output_id - and a.message_id <= a_last_read_message_id + lc_bulk_limit + and a.message_id <= (select min(message_id) from ut_output_clob_buffer_tmp o where o.output_id = self.output_id) + lc_bulk_limit order by a.message_id ) select /*+ no_parallel */ b.* bulk collect into a_buffer_data, a_buffer_rowids, a_finished_flags from ordered_buffer b; - a_last_read_message_id := a_last_read_message_id + a_finished_flags.count; end; procedure remove_read_data(a_buffer_rowids ut_varchar2_rows) is @@ -103,7 +96,7 @@ create or replace type body ut_output_clob_table_buffer is l_sleep_time := case when l_already_waited_sec >= 1 then 0.5 else 0.1 end; l_lock_status := self.get_lock_status(); - get_data_from_buffer_table( l_last_read_message_id, l_buffer_data, l_buffer_rowids, l_finished_flags ); + get_data_from_buffer_table( l_buffer_data, l_buffer_rowids, l_finished_flags ); if l_buffer_data.count > 0 then l_already_waited_sec := 0; diff --git a/source/core/output_buffers/ut_output_table_buffer.tpb b/source/core/output_buffers/ut_output_table_buffer.tpb index 480ae9144..e8e2442a7 100644 --- a/source/core/output_buffers/ut_output_table_buffer.tpb +++ b/source/core/output_buffers/ut_output_table_buffer.tpb @@ -26,7 +26,7 @@ create or replace type body ut_output_table_buffer is pragma autonomous_transaction; begin if a_text is not null or a_item_type is not null then - if length(a_text) > ut_utils.gc_max_storage_varchar2_len then + if lengthb(a_text) > ut_utils.gc_max_storage_varchar2_len then self.send_lines( ut_utils.convert_collection( ut_utils.clob_to_table(a_text, ut_utils.gc_max_storage_varchar2_len) @@ -34,9 +34,8 @@ create or replace type body ut_output_table_buffer is a_item_type ); else - self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_write_message_id, a_text, a_item_type); + values (self.output_id, ut_output_buffer_tmp_seq.nextval, a_text, a_item_type); end if; commit; end if; @@ -46,10 +45,9 @@ create or replace type body ut_output_table_buffer is pragma autonomous_transaction; begin insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - select /*+ no_parallel */ self.output_id, self.last_write_message_id + rownum, t.column_value, a_item_type + select /*+ no_parallel */ self.output_id, ut_output_buffer_tmp_seq.nextval, t.column_value, a_item_type from table(a_text_list) t where t.column_value is not null or a_item_type is not null; - self.last_write_message_id := self.last_write_message_id + SQL%rowcount; commit; end; @@ -57,7 +55,7 @@ create or replace type body ut_output_table_buffer is pragma autonomous_transaction; begin if a_text is not null and a_text != empty_clob() or a_item_type is not null then - if length(a_text) > ut_utils.gc_max_storage_varchar2_len then + if ut_utils.lengthb_clob(a_text) > ut_utils.gc_max_storage_varchar2_len then self.send_lines( ut_utils.convert_collection( ut_utils.clob_to_table(a_text, ut_utils.gc_max_storage_varchar2_len) @@ -65,9 +63,8 @@ create or replace type body ut_output_table_buffer is a_item_type ); else - self.last_write_message_id := self.last_write_message_id + 1; insert /*+ no_parallel */ into ut_output_buffer_tmp(output_id, message_id, text, item_type) - values (self.output_id, self.last_write_message_id, a_text, a_item_type); + values (self.output_id, ut_output_buffer_tmp_seq.nextval, a_text, a_item_type); end if; commit; end if; @@ -99,7 +96,6 @@ create or replace type body ut_output_table_buffer is l_buffer_texts ut_varchar2_rows; l_buffer_item_types ut_varchar2_rows; l_finished_flags ut_integer_list; - l_last_read_message_id integer; l_already_waited_sec number(10,2) := 0; l_finished boolean := false; l_sleep_time number(2,1); @@ -108,7 +104,6 @@ create or replace type body ut_output_table_buffer is l_producer_finished boolean := false; procedure get_data_from_buffer_table( - a_last_read_message_id in out nocopy integer, a_buffer_texts out nocopy ut_varchar2_rows, a_buffer_item_types out nocopy ut_varchar2_rows, a_finished_flags out nocopy ut_integer_list @@ -116,17 +111,15 @@ create or replace type body ut_output_table_buffer is lc_bulk_limit constant integer := 20000; pragma autonomous_transaction; begin - a_last_read_message_id := coalesce(a_last_read_message_id,0); delete /*+ no_parallel */ from ( select /*+ no_parallel */ * - from ut_output_buffer_tmp o - where o.output_id = self.output_id - and o.message_id <= a_last_read_message_id + lc_bulk_limit - order by o.message_id + from ut_output_buffer_tmp a + where a.output_id = self.output_id + and a.message_id <= (select min(message_id) from ut_output_buffer_tmp o where o.output_id = self.output_id) + lc_bulk_limit + order by a.message_id ) d returning d.text, d.item_type, d.is_finished bulk collect into a_buffer_texts, a_buffer_item_types, a_finished_flags; - a_last_read_message_id := a_last_read_message_id + a_finished_flags.count; commit; end; begin @@ -134,7 +127,7 @@ create or replace type body ut_output_table_buffer is l_sleep_time := case when l_already_waited_sec >= 1 then 0.5 else 0.1 end; l_lock_status := self.get_lock_status(); - get_data_from_buffer_table( l_last_read_message_id, l_buffer_texts, l_buffer_item_types, l_finished_flags ); + get_data_from_buffer_table( l_buffer_texts, l_buffer_item_types, l_finished_flags ); if l_buffer_texts.count > 0 then l_already_waited_sec := 0; diff --git a/source/core/ut_utils.pkb b/source/core/ut_utils.pkb index f29e3b188..81d47221b 100644 --- a/source/core/ut_utils.pkb +++ b/source/core/ut_utils.pkb @@ -92,8 +92,8 @@ create or replace package body ut_utils is a_max_output_len in number := gc_max_output_string_length ) return varchar2 is l_result varchar2(32767); - c_length constant integer := coalesce( length( a_value ), 0 ); - c_max_input_string_length constant integer := a_max_output_len - coalesce( length( a_quote_char ) * 2, 0 ); + c_length constant integer := coalesce( lengthb( a_value ), 0 ); + c_max_input_string_length constant integer := a_max_output_len - coalesce( lengthb( a_quote_char ) * 2, 0 ); c_overflow_substr_len constant integer := c_max_input_string_length - gc_more_data_string_len; begin if c_length = 0 then @@ -112,8 +112,8 @@ create or replace package body ut_utils is a_max_output_len in number := gc_max_output_string_length ) return varchar2 is l_result varchar2(32767); - c_length constant integer := coalesce(dbms_lob.getlength(a_value), 0); - c_max_input_string_length constant integer := a_max_output_len - coalesce( length( a_quote_char ) * 2, 0 ); + c_length constant integer := coalesce(ut_utils.lengthb_clob(a_value), 0); + c_max_input_string_length constant integer := a_max_output_len - coalesce( lengthb( a_quote_char ) * 2, 0 ); c_overflow_substr_len constant integer := c_max_input_string_length - gc_more_data_string_len; begin if a_value is null then @@ -135,7 +135,7 @@ create or replace package body ut_utils is ) return varchar2 is l_result varchar2(32767); c_length constant integer := coalesce(dbms_lob.getlength(a_value), 0); - c_max_input_string_length constant integer := a_max_output_len - coalesce( length( a_quote_char ) * 2, 0 ); + c_max_input_string_length constant integer := a_max_output_len - coalesce( lengthb( a_quote_char ) * 2, 0 ); c_overflow_substr_len constant integer := c_max_input_string_length - gc_more_data_string_len; begin if a_value is null then @@ -412,7 +412,7 @@ create or replace package body ut_utils is if a_list is null then a_list := ut_varchar2_rows(); end if; - if length(a_item) > gc_max_storage_varchar2_len then + if lengthb(a_item) > gc_max_storage_varchar2_len then append_to_list( a_list, ut_utils.convert_collection( @@ -468,7 +468,7 @@ create or replace package body ut_utils is l_result := ut_varchar2_rows(); for i in 1 .. a_collection.count loop l_result.extend(); - l_result(i) := substr(a_collection(i),1,gc_max_storage_varchar2_len); + l_result(i) := substrb(a_collection(i),1,gc_max_storage_varchar2_len); end loop; end if; return l_result; @@ -990,5 +990,39 @@ create or replace package body ut_utils is return l_result; end; + + + /* + * Inspired by + * https://stackoverflow.com/a/48782891 + */ + function lengthb_clob( a_clob clob) return integer is + l_blob blob; + l_desc_offset PLS_INTEGER := 1; + l_src_offset PLS_INTEGER := 1; + l_lang PLS_INTEGER := 0; + l_warning PLS_INTEGER := 0; + l_result integer; + begin + if a_clob = empty_clob() then + l_result := 0; + elsif a_clob is not null then + dbms_lob.createtemporary(l_blob,true); + dbms_lob.converttoblob + ( l_blob + , a_clob + , dbms_lob.getlength(a_clob) + , l_desc_offset + , l_src_offset + , dbms_lob.default_csid + , l_lang + , l_warning + ); + l_result := length(l_blob); + dbms_lob.freetemporary(l_blob); + end if; + return l_result; + end; + end ut_utils; / diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 90c165bbb..ee5ed7876 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -476,6 +476,11 @@ create or replace package ut_utils authid definer is * Return value of interval in plain english */ function interval_to_text(a_interval yminterval_unconstrained) return varchar2; + + /* + * Return length of CLOB in bytes. Null for NULL + */ + function lengthb_clob( a_clob clob) return integer; end ut_utils; / diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index f488b8b8d..a0b53ba21 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -333,8 +333,12 @@ drop type ut_output_buffer_base force; drop table ut_output_buffer_tmp purge; +drop table ut_output_buffer_tmp_seq purge; + drop table ut_output_clob_buffer_tmp purge; +drop table ut_output_clob_buffer_tmp_seq purge; + drop table ut_output_buffer_info_tmp purge; drop package ut_session_context; diff --git a/test/ut3_tester/core/test_output_buffer.pkb b/test/ut3_tester/core/test_output_buffer.pkb index edb10e3e6..317e7e3d5 100644 --- a/test/ut3_tester/core/test_output_buffer.pkb +++ b/test/ut3_tester/core/test_output_buffer.pkb @@ -56,8 +56,8 @@ create or replace package body test_output_buffer is procedure test_doesnt_send_on_null_elem is - l_cur sys_refcursor; - l_result integer; + l_actual sys_refcursor; + l_expected sys_refcursor; l_buffer ut3_develop.ut_output_buffer_base := ut3_develop.ut_output_table_buffer(); l_message_id varchar2(255); l_text varchar2(4000); @@ -67,9 +67,12 @@ create or replace package body test_output_buffer is l_buffer.send_lines(ut3_develop.ut_varchar2_rows(null)); l_buffer.send_lines(ut3_develop.ut_varchar2_rows('test')); - select message_id, text into l_message_id, l_text from table(ut3_tester_helper.run_helper.ut_output_buffer_tmp); - ut.expect(l_message_id).to_equal('1'); - ut.expect(l_text).to_equal('test'); + open l_actual for + select text from table(ut3_tester_helper.run_helper.ut_output_buffer_tmp); + open l_expected for + select 'test' as text from dual; + + ut.expect(l_actual).to_equal(l_expected); end; procedure test_send_line is @@ -157,5 +160,41 @@ create or replace package body test_output_buffer is test_purge(ut3_develop.ut_output_clob_table_buffer()); end; -end test_output_buffer; + procedure text_buffer_send_multibyte is + l_input varchar2(32767); + l_max_len integer := ut3_develop.ut_utils.gc_max_storage_varchar2_len; + l_buffer ut3_develop.ut_output_buffer_base := ut3_develop.ut_output_table_buffer(); + l_text varchar2(4000); + begin + --Arrange + ut3_tester_helper.run_helper.delete_buffer(); + l_input := rpad( '❤', l_max_len, 'a' ); + ut.expect( lengthb( l_input ) ).to_be_greater_than(l_max_len); + + --Act + l_buffer.send_line(l_input); + --Assert + select text into l_text from table(ut3_tester_helper.run_helper.ut_output_buffer_tmp); + ut.expect(lengthb(l_text)).to_be_less_or_equal(l_max_len); + end; + + procedure text_buffer_send_clob_multib is + l_input clob; + l_max_len integer := ut3_develop.ut_utils.gc_max_storage_varchar2_len; + l_buffer ut3_develop.ut_output_buffer_base := ut3_develop.ut_output_table_buffer(); + l_text varchar2(4000); + begin + --Arrange + ut3_tester_helper.run_helper.delete_buffer(); + l_input := rpad( '❤', l_max_len, 'a' ); + ut.expect( ut3_develop.ut_utils.lengthb_clob( l_input ) ).to_be_greater_than(l_max_len); + + --Act + l_buffer.send_clob(l_input); + --Assert + select text into l_text from table(ut3_tester_helper.run_helper.ut_output_buffer_tmp); + ut.expect(lengthb(l_text)).to_be_less_or_equal(l_max_len); + end; + + end test_output_buffer; / diff --git a/test/ut3_tester/core/test_output_buffer.pks b/test/ut3_tester/core/test_output_buffer.pks index feaa337f8..5b6cd678b 100644 --- a/test/ut3_tester/core/test_output_buffer.pks +++ b/test/ut3_tester/core/test_output_buffer.pks @@ -47,5 +47,11 @@ create or replace package test_output_buffer is --%test(Purges clob buffer data older than one day and leaves the rest) procedure test_purge_clob_buffer; + --%test(Successfully sends multibyte long line into text buffer) + procedure text_buffer_send_multibyte; + + --%test(Successfully sends multibyte long clob line into text buffer) + procedure text_buffer_send_clob_multib; + end test_output_buffer; / diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index ec7e4f403..27c164e4e 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -489,5 +489,23 @@ end; ut.expect(l_expected).to_equal(l_actual); end; + procedure convert_collection_multibyte is + l_input ut3_develop.ut_varchar2_list; + l_max_len integer := ut3_develop.ut_utils.gc_max_storage_varchar2_len; + begin + --Arrange + l_input := ut3_develop.ut_varchar2_list( rpad( '❤', l_max_len, 'a' ) ); + ut.expect( lengthb( l_input( 1 ) ) ).to_be_greater_than(l_max_len); + + --Act + ut.expect( lengthb( ut3_develop.ut_utils.convert_collection(l_input)(1) ) ).to_be_less_or_equal(l_max_len); + end; + + procedure lengthb_gives_length_in_bytes is + l_clob clob; + begin + l_clob := '❤'; + ut.expect(ut3_develop.ut_utils.lengthb_clob(l_clob)).to_equal(3); + end; end test_ut_utils; / diff --git a/test/ut3_tester/core/test_ut_utils.pks b/test/ut3_tester/core/test_ut_utils.pks index 114b35e86..ca2e7b304 100644 --- a/test/ut3_tester/core/test_ut_utils.pks +++ b/test/ut3_tester/core/test_ut_utils.pks @@ -152,10 +152,15 @@ create or replace package test_ut_utils is procedure int_conv_ym_month; --%test(returns text representation of interval year to month for custom interval) - procedure int_conv_ym_date; - - + procedure int_conv_ym_date; + --%endcontext - + + --%test(convert_collection does not fail on multibyte strings - Issue #1245 ) + procedure convert_collection_multibyte; + + --%test(lengthb returns length of a CLOB in bytes ) + procedure lengthb_gives_length_in_bytes; + end test_ut_utils; / From b70ee1e742652da3c4a13231e1edcc26ecff5998 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 28 May 2023 17:03:28 +0300 Subject: [PATCH 176/187] Fixed failing unit test and the uninstall script --- source/uninstall_objects.sql | 4 ++-- test/ut3_tester/core/test_ut_utils.pkb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/uninstall_objects.sql b/source/uninstall_objects.sql index a0b53ba21..dde9a824f 100644 --- a/source/uninstall_objects.sql +++ b/source/uninstall_objects.sql @@ -333,11 +333,11 @@ drop type ut_output_buffer_base force; drop table ut_output_buffer_tmp purge; -drop table ut_output_buffer_tmp_seq purge; +drop sequence ut_output_buffer_tmp_seq; drop table ut_output_clob_buffer_tmp purge; -drop table ut_output_clob_buffer_tmp_seq purge; +drop sequence ut_output_clob_buffer_tmp_seq; drop table ut_output_buffer_info_tmp purge; diff --git a/test/ut3_tester/core/test_ut_utils.pkb b/test/ut3_tester/core/test_ut_utils.pkb index 27c164e4e..433987c01 100644 --- a/test/ut3_tester/core/test_ut_utils.pkb +++ b/test/ut3_tester/core/test_ut_utils.pkb @@ -505,7 +505,7 @@ end; l_clob clob; begin l_clob := '❤'; - ut.expect(ut3_develop.ut_utils.lengthb_clob(l_clob)).to_equal(3); + ut.expect(ut3_develop.ut_utils.lengthb_clob(l_clob)).to_be_greater_than(1); end; end test_ut_utils; / From 21462fcfa53b2d466fd7719f9f854facb06c2cdc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 28 May 2023 15:44:45 +0100 Subject: [PATCH 177/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 9d18766ae..d4bebf085 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index a9cd17bc9..adf03ba11 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 0b1b005c6..aca73a1d6 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 639dc2970..c83158ec0 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index bd908d60c..f60d80aa9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index eb3b311a5..5fc69e002 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 4f1c6b420..4b3af7c2a 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index f5f889ca6..6c1920c6b 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index dbd584a7c..0466e237a 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index cad56f1b8..5b242a0cd 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 67f851f36..d188c0aa2 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index b2c67054e..1a0aceeb9 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 4e1b3e903..e12ed3588 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index d68240a5d..d7f2a2838 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index ca3878f9f..a804d98e7 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 4fdb74073..282e07d09 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index bd401f5d9..bbca978ba 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4171--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index ee5ed7876..552f31143 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4171-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4176-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From cd3e2b940208c6f9f68d6ae74b10d86019761c3f Mon Sep 17 00:00:00 2001 From: Jonas Gassenmeyer Date: Fri, 7 Jul 2023 14:17:00 +0200 Subject: [PATCH 178/187] fix(doc): Update running-unit-tests.md - remove example --- docs/userguide/running-unit-tests.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 282e07d09..447b5eb54 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -120,14 +120,6 @@ end; ``` Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_. -```sql linenums="1" -set serveroutput on -begin - ut.run(ut_varchar2_list('hr.test_apply_bonus,cust)'); -end; -``` - -Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_. ```sql linenums="1" set serveroutput on @@ -566,4 +558,4 @@ Example call with characterset provided: begin ut.run('hr.test_apply_bonus', ut_junit_reporter(), a_client_character_set => 'Windows-1251'); end; -``` \ No newline at end of file +``` From e4d8528822254212a28e676a11ba9d578cfeee04 Mon Sep 17 00:00:00 2001 From: Jacek Gebal Date: Sun, 9 Jul 2023 19:11:21 +0300 Subject: [PATCH 179/187] Added missing grant for `ut_output_bulk_buffer`. --- source/create_grants.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/source/create_grants.sql b/source/create_grants.sql index 8a44ab371..0e9f46cc5 100644 --- a/source/create_grants.sql +++ b/source/create_grants.sql @@ -123,6 +123,7 @@ grant execute on &&ut3_owner..ut_console_reporter_base to &ut3_user; grant execute on &&ut3_owner..ut_output_buffer_base to &ut3_user; grant execute on &&ut3_owner..ut_output_table_buffer to &ut3_user; grant execute on &&ut3_owner..ut_output_clob_table_buffer to &ut3_user; +grant execute on &&ut3_owner..ut_output_bulk_buffer to &ut3_user; --needed internally for selecting from annotation objects within packages that use invoker rights grant execute on &&ut3_owner..ut_annotation_objs_cache_info to &ut3_user; From 550ea328e74cc211408292b1f481b4feabe5ce46 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 9 Jul 2023 17:20:41 +0100 Subject: [PATCH 180/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index d4bebf085..cd5f1191e 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index adf03ba11..f81d13395 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index aca73a1d6..e315c921f 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index c83158ec0..968d9acc4 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index f60d80aa9..49f5d42a7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 5fc69e002..325b831c5 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 4b3af7c2a..95b34accc 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 6c1920c6b..94ab25215 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 0466e237a..e30c87d00 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 5b242a0cd..7fdac2189 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index d188c0aa2..ceca41af8 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 1a0aceeb9..e5b636f53 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index e12ed3588..ce21e475f 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index d7f2a2838..7c4891aea 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index a804d98e7..f46d7dba4 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 282e07d09..618e61f1c 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index bbca978ba..2eecf9c85 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4176--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 552f31143..7c49dad67 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4176-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4178-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From fc8c520bfb569cee737193c7db81c7efec07a20b Mon Sep 17 00:00:00 2001 From: Jonas Gassenmeyer Date: Mon, 10 Jul 2023 08:12:46 +0200 Subject: [PATCH 181/187] fix(doc): Update running-unit-tests.md add comments --- docs/userguide/running-unit-tests.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index e35001a52..fde0330c9 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -118,7 +118,16 @@ begin ut.run(ut_varchar2_list('hr.test_apply_bonus','cust')); end; ``` -Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_. +Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_ (passing individual items to be executed as elements of the ut_varchar2_list table type). + + +```sql linenums="1" +set serveroutput on +begin + ut.run(ut_varchar2_list('hr.test_apply_bonus,cust')); +end; +``` +Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_ (passing all items as a comma-separated-list of values into a single element of the ut_varchar2_list table type). ```sql linenums="1" @@ -128,7 +137,7 @@ begin end; ``` -Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_. +Executes all tests from package _hr.test_apply_bonus_ and all tests from schema _cust_ (no explicit ut_varchar2_list table type). Using a list of items to execute allows you to execute a fine-grained set of tests. From 242695255a9751d642563bfe75ad02582032561b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 29 Aug 2023 21:51:17 +0100 Subject: [PATCH 182/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index cd5f1191e..43b94f7ab 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index f81d13395..cf10e3bd6 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index e315c921f..6889d9edb 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index 968d9acc4..c2af14837 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index 49f5d42a7..f22ea814e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index 325b831c5..f676ae4db 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index 95b34accc..a21f66424 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 94ab25215..f563fb819 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index e30c87d00..4c1e1dcb8 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 7fdac2189..467651334 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index ceca41af8..ce9e519d5 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index e5b636f53..47f2cb92e 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index ce21e475f..69183c577 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 7c4891aea..3bf028596 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index f46d7dba4..3c36676e8 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index fde0330c9..662b5b004 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index 2eecf9c85..ae4499f98 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4178--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 7c49dad67..29ce06991 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4178-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4182-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 03106637532a424c413cd34e7614ef10b0359ad0 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 22 Sep 2023 21:07:16 +0100 Subject: [PATCH 183/187] Issue #1268 The line-rate is not recorded for packages and classes. --- .../ut_coverage_cobertura_reporter.tpb | 37 +++++++++++++++---- .../test_cov_cobertura_reporter.pkb | 4 +- .../test_coverage_standalone.pkb | 4 +- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/source/reporters/ut_coverage_cobertura_reporter.tpb b/source/reporters/ut_coverage_cobertura_reporter.tpb index 50eb34631..d833ac0aa 100644 --- a/source/reporters/ut_coverage_cobertura_reporter.tpb +++ b/source/reporters/ut_coverage_cobertura_reporter.tpb @@ -29,11 +29,19 @@ create or replace type body ut_coverage_cobertura_reporter is l_report_lines ut_varchar2_list; l_coverage_data ut_coverage.t_coverage; - function get_lines_xml(a_unit_coverage ut_coverage.t_unit_coverage) return clob is + function get_line_rate(a_lines_covered in integer, a_lines_hit in integer) return varchar2 is + begin + return to_char(round((case a_lines_covered when 0 then 0 else a_lines_covered/a_lines_hit end), 17), rpad('FM0.0',20,'9') , 'NLS_NUMERIC_CHARACTERS=''. '''); + end; + + procedure get_lines_xml(a_unit_coverage ut_coverage.t_unit_coverage, + a_lines_result in out nocopy clob, a_lines_hits out number, a_lines_total out number) is l_file_part varchar2(32767); l_result clob; l_line_no binary_integer; l_pct integer; + l_lines_hits integer := 0; + l_lines_total integer := 0; begin dbms_lob.createtemporary(l_result, true); l_line_no := a_unit_coverage.lines.first; @@ -41,11 +49,14 @@ create or replace type body ut_coverage_cobertura_reporter is for i in 1 .. a_unit_coverage.total_lines loop ut_utils.append_to_clob(l_result, ''||chr(10)); end loop; + l_lines_hits:=0; + l_lines_total:= a_unit_coverage.total_lines; else while l_line_no is not null loop if a_unit_coverage.lines(l_line_no).executions = 0 then l_file_part := ''||chr(10); else + l_lines_hits:= l_lines_hits+1; l_file_part := '' + '' ); ut_utils.append_to_list( @@ -129,13 +150,13 @@ create or replace type body ut_coverage_cobertura_reporter is ut_utils.append_to_list( l_result, '' + ||dbms_xmlgen.convert(l_unit)||'" line-rate="'||get_line_rate(l_line_hits,l_line_total)||'" branch-rate="0.0" complexity="0.0">' ); ut_utils.append_to_list(l_result, ''); - - ut_utils.append_to_list( l_result, get_lines_xml(a_coverage_data.objects(l_unit)) ); - + ut_utils.append_to_list( l_result,l_lines_xml); + dbms_lob.freetemporary(l_lines_xml); + ut_utils.append_to_list(l_result, c_lines_footer); ut_utils.append_to_list(l_result, c_class_footer); ut_utils.append_to_list(l_result, c_classes_footer); diff --git a/test/ut3_user/reporters/test_coverage/test_cov_cobertura_reporter.pkb b/test/ut3_user/reporters/test_coverage/test_cov_cobertura_reporter.pkb index 2c36f37ba..ad6c9dbb4 100644 --- a/test/ut3_user/reporters/test_coverage/test_cov_cobertura_reporter.pkb +++ b/test/ut3_user/reporters/test_coverage/test_cov_cobertura_reporter.pkb @@ -25,9 +25,9 @@ create or replace package body test_cov_cobertura_reporter is ]'||l_file_path||q'[ - + - + ]'||l_block_cov||q'[ diff --git a/test/ut3_user/reporters/test_coverage/test_coverage_standalone.pkb b/test/ut3_user/reporters/test_coverage/test_coverage_standalone.pkb index e5706f885..90cfb484e 100644 --- a/test/ut3_user/reporters/test_coverage/test_coverage_standalone.pkb +++ b/test/ut3_user/reporters/test_coverage/test_coverage_standalone.pkb @@ -20,9 +20,9 @@ create or replace package body test_coverage_standalone is ]'||l_file_path||q'[ - + - + ]'||l_block_cov||q'[ From e0a9fa16a973d3a47784f58485238309fb44bb69 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 23 Sep 2023 19:28:21 +0100 Subject: [PATCH 184/187] Updated project version after build [skip ci] --- docs/about/authors.md | 2 +- docs/about/license.md | 2 +- docs/about/project-details.md | 2 +- docs/about/support.md | 2 +- docs/index.md | 2 +- docs/userguide/advanced_data_comparison.md | 2 +- docs/userguide/annotations.md | 2 +- docs/userguide/best-practices.md | 2 +- docs/userguide/coverage.md | 2 +- docs/userguide/exception-reporting.md | 2 +- docs/userguide/expectations.md | 2 +- docs/userguide/getting-started.md | 2 +- docs/userguide/install.md | 2 +- docs/userguide/querying_suites.md | 2 +- docs/userguide/reporters.md | 2 +- docs/userguide/running-unit-tests.md | 2 +- docs/userguide/upgrade.md | 2 +- source/core/ut_utils.pks | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/about/authors.md b/docs/about/authors.md index 43b94f7ab..c4c40bfad 100644 --- a/docs/about/authors.md +++ b/docs/about/authors.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) ### utPLSQL v3 Major Contributors diff --git a/docs/about/license.md b/docs/about/license.md index cf10e3bd6..702ea3f9c 100644 --- a/docs/about/license.md +++ b/docs/about/license.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) # Version Information diff --git a/docs/about/project-details.md b/docs/about/project-details.md index 6889d9edb..60aa6a657 100644 --- a/docs/about/project-details.md +++ b/docs/about/project-details.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) # utPLSQL Project Details diff --git a/docs/about/support.md b/docs/about/support.md index c2af14837..fc412205d 100644 --- a/docs/about/support.md +++ b/docs/about/support.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) # How to get support diff --git a/docs/index.md b/docs/index.md index f22ea814e..8325ec636 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) ## What is utPLSQL diff --git a/docs/userguide/advanced_data_comparison.md b/docs/userguide/advanced_data_comparison.md index f676ae4db..1f7f2d191 100644 --- a/docs/userguide/advanced_data_comparison.md +++ b/docs/userguide/advanced_data_comparison.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) # Advanced data comparison diff --git a/docs/userguide/annotations.md b/docs/userguide/annotations.md index a21f66424..d1ff5da07 100644 --- a/docs/userguide/annotations.md +++ b/docs/userguide/annotations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) Annotations are used to configure tests and suites in a declarative way similar to modern OOP languages. This way, test configuration is stored along with the test logic inside the test package. No additional configuration files or tables are needed for test cases. The annotation names are based on popular testing frameworks such as JUnit. diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index f563fb819..5148273e6 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) The following are best practices we at utPLSQL have learned about PL/SQL and Unit Testing. diff --git a/docs/userguide/coverage.md b/docs/userguide/coverage.md index 4c1e1dcb8..5d071335e 100644 --- a/docs/userguide/coverage.md +++ b/docs/userguide/coverage.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) utPLSQL comes with a built-in coverage reporting engine. The code coverage reporting uses package DBMS_PROFILER (and DBMS_PLSQL_CODE_COVERAGE on Oracle database version 12.2 and above) provided with Oracle database. Code coverage is gathered for the following source types: diff --git a/docs/userguide/exception-reporting.md b/docs/userguide/exception-reporting.md index 467651334..ca52ac951 100644 --- a/docs/userguide/exception-reporting.md +++ b/docs/userguide/exception-reporting.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) utPLSQL is responsible for handling exceptions wherever they occur in the test run. The framework is trapping most of the exceptions so that the test execution is not affected by individual tests or test packages throwing an exception. The framework provides a full stacktrace for every exception that was thrown. The reported stacktrace does not include any utPLSQL library calls in it. diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index ce9e519d5..b6f3d7e29 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) ## Expectation concepts diff --git a/docs/userguide/getting-started.md b/docs/userguide/getting-started.md index 47f2cb92e..9620878ad 100644 --- a/docs/userguide/getting-started.md +++ b/docs/userguide/getting-started.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) # Getting started with TDD and utPLSQL diff --git a/docs/userguide/install.md b/docs/userguide/install.md index 69183c577..8f32c5a10 100644 --- a/docs/userguide/install.md +++ b/docs/userguide/install.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) ## Supported database versions diff --git a/docs/userguide/querying_suites.md b/docs/userguide/querying_suites.md index 3bf028596..e3ec1f53d 100644 --- a/docs/userguide/querying_suites.md +++ b/docs/userguide/querying_suites.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) ## Obtaining information about suites diff --git a/docs/userguide/reporters.md b/docs/userguide/reporters.md index 3c36676e8..e37ac6627 100644 --- a/docs/userguide/reporters.md +++ b/docs/userguide/reporters.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) utPLSQL provides several reporting formats. The sections below describe most of them. diff --git a/docs/userguide/running-unit-tests.md b/docs/userguide/running-unit-tests.md index 662b5b004..3b23f5f98 100644 --- a/docs/userguide/running-unit-tests.md +++ b/docs/userguide/running-unit-tests.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) utPLSQL framework provides two main entry points to run unit tests from within the database: diff --git a/docs/userguide/upgrade.md b/docs/userguide/upgrade.md index ae4499f98..e5537f520 100644 --- a/docs/userguide/upgrade.md +++ b/docs/userguide/upgrade.md @@ -1,4 +1,4 @@ -![version](https://img.shields.io/badge/version-v3.1.14.4182--develop-blue.svg) +![version](https://img.shields.io/badge/version-v3.1.14.4187--develop-blue.svg) # Upgrading from version 2 diff --git a/source/core/ut_utils.pks b/source/core/ut_utils.pks index 29ce06991..522da1480 100644 --- a/source/core/ut_utils.pks +++ b/source/core/ut_utils.pks @@ -21,7 +21,7 @@ create or replace package ut_utils authid definer is * */ - gc_version constant varchar2(50) := 'v3.1.14.4182-develop'; + gc_version constant varchar2(50) := 'v3.1.14.4187-develop'; subtype t_executable_type is varchar2(30); gc_before_all constant t_executable_type := 'beforeall'; From 0474d7a8f2944b864e8b221e9a7c79f11d23c245 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 24 Sep 2023 23:52:15 +0100 Subject: [PATCH 185/187] First checking. Still some more tests to go for complex nesting. --- source/reporters/ut_tfs_junit_reporter.tpb | 92 ++++++---- .../reporters/test_tfs_junit_reporter.pkb | 161 +++++++++++++++++- .../reporters/test_tfs_junit_reporter.pks | 9 + 3 files changed, 218 insertions(+), 44 deletions(-) diff --git a/source/reporters/ut_tfs_junit_reporter.tpb b/source/reporters/ut_tfs_junit_reporter.tpb index e2d45a369..5b8702808 100644 --- a/source/reporters/ut_tfs_junit_reporter.tpb +++ b/source/reporters/ut_tfs_junit_reporter.tpb @@ -51,11 +51,12 @@ create or replace type body ut_tfs_junit_reporter is return regexp_substr(a_path_with_name, '(.*)\.' ||a_name||'$',subexpression=>1); end; - procedure print_test_results(a_test ut_test) is + function add_test_results(a_test ut_test) return ut_varchar2_rows is l_results ut_varchar2_rows := ut_varchar2_rows(); begin - self.print_text(''); + /* According to specs : - A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. @@ -83,64 +84,83 @@ create or replace type body ut_tfs_junit_reporter is ut_utils.append_to_list( l_results, ''); - self.print_text_lines(l_results); + return l_results; end; - procedure print_suite_results(a_suite ut_logical_suite, a_suite_id in out nocopy integer) is + procedure print_suite_results(a_suite ut_logical_suite, a_suite_id in out nocopy integer, a_nested_tests in out nocopy ut_varchar2_rows) is l_tests_count integer := a_suite.results_count.disabled_count + a_suite.results_count.success_count + a_suite.results_count.failure_count + a_suite.results_count.errored_count; l_results ut_varchar2_rows := ut_varchar2_rows(); l_suite ut_suite; l_outputs clob; l_errors ut_varchar2_list; - begin - + l_tests ut_varchar2_list; + begin for i in 1 .. a_suite.items.count loop if a_suite.items(i) is of(ut_logical_suite) then - print_suite_results(treat(a_suite.items(i) as ut_logical_suite), a_suite_id); + print_suite_results(treat(a_suite.items(i) as ut_logical_suite), a_suite_id, a_nested_tests); end if; end loop; - - if a_suite is of(ut_suite) then - a_suite_id := a_suite_id + 1; - self.print_text(''); - self.print_text(''); + --Due to fact tha TFS and junit5 accepts only flat structure we have to report in suite level only. + if a_suite.self_type ='UT_SUITE_CONTEXT' then for i in 1 .. a_suite.items.count loop if a_suite.items(i) is of(ut_test) then - print_test_results(treat(a_suite.items(i) as ut_test)); + ut_utils.append_to_list( a_nested_tests,(add_test_results(treat(a_suite.items(i) as ut_test)))); end if; end loop; - l_suite := treat(a_suite as ut_suite); - l_outputs := l_suite.get_serveroutputs(); - if l_outputs is not null and l_outputs != empty_clob() then - ut_utils.append_to_list( l_results, ''); - ut_utils.append_to_list( l_results, ut_utils.to_cdata( l_suite.get_serveroutputs() ) ); - ut_utils.append_to_list( l_results, ''); - else - ut_utils.append_to_list( l_results, ''); - end if; - - l_errors := l_suite.get_error_stack_traces(); - if l_errors is not empty then - ut_utils.append_to_list( l_results, ''); - ut_utils.append_to_list( l_results, ut_utils.to_cdata( ut_utils.convert_collection( l_errors ) ) ); - ut_utils.append_to_list( l_results, ''); - else - ut_utils.append_to_list( l_results, ''); - end if; - ut_utils.append_to_list( l_results, ''); - - self.print_text_lines(l_results); + elsif a_suite.self_type ='UT_SUITE' then + for i in 1 .. a_suite.items.count loop + if a_suite.items(i) is of(ut_test) then + ut_utils.append_to_list( a_nested_tests,(add_test_results(treat(a_suite.items(i) as ut_test)))); + end if; + end loop; + --TFS doesnt report on empty test suites, however all we want to make sure is that we dont pring parents suites + -- showing test count but not tests. + if (a_nested_tests.count > 0 and l_tests_count > 0) or (a_nested_tests.count = 0 and l_tests_count = 0) then + a_suite_id := a_suite_id + 1; + ut_utils.append_to_list( l_results,''); + ut_utils.append_to_list( l_results,''); + ut_utils.append_to_list(l_results,a_nested_tests); + l_suite := treat(a_suite as ut_suite); + l_outputs := l_suite.get_serveroutputs(); + if l_outputs is not null and l_outputs != empty_clob() then + ut_utils.append_to_list( l_results, ''); + ut_utils.append_to_list( l_results, ut_utils.to_cdata( l_suite.get_serveroutputs() ) ); + ut_utils.append_to_list( l_results, ''); + else + ut_utils.append_to_list( l_results, ''); + end if; + + l_errors := l_suite.get_error_stack_traces(); + if l_errors is not empty then + ut_utils.append_to_list( l_results, ''); + ut_utils.append_to_list( l_results, ut_utils.to_cdata( ut_utils.convert_collection( l_errors ) ) ); + ut_utils.append_to_list( l_results, ''); + else + ut_utils.append_to_list( l_results, ''); + end if; + ut_utils.append_to_list( l_results, ''); + + self.print_text_lines(l_results); + --We have resolved a context and we now reset value. + a_nested_tests := ut_varchar2_rows(); + end if; end if; end; + + procedure get_suite_results(a_suite ut_logical_suite, a_suite_id in out nocopy integer) is + l_nested_tests ut_varchar2_rows:= ut_varchar2_rows(); + begin + print_suite_results(a_suite, l_suite_id,l_nested_tests); + end; begin l_suite_id := 0; self.print_text(ut_utils.get_xml_header(a_run.client_character_set)); self.print_text(''); for i in 1 .. a_run.items.count loop - print_suite_results(treat(a_run.items(i) as ut_logical_suite), l_suite_id); + get_suite_results(treat(a_run.items(i) as ut_logical_suite), l_suite_id); end loop; self.print_text(''); end; diff --git a/test/ut3_user/reporters/test_tfs_junit_reporter.pkb b/test/ut3_user/reporters/test_tfs_junit_reporter.pkb index 7eb4f8ab6..1036be2ba 100644 --- a/test/ut3_user/reporters/test_tfs_junit_reporter.pkb +++ b/test/ut3_user/reporters/test_tfs_junit_reporter.pkb @@ -8,7 +8,7 @@ create or replace package body test_tfs_junit_reporter as --%test(A test with ) procedure test_do_stuff; - + end;]'; execute immediate q'[create or replace package body check_junit_reporting is procedure test_do_stuff is @@ -18,12 +18,12 @@ create or replace package body test_tfs_junit_reporter as end; end;]'; - + execute immediate q'[create or replace package check_junit_rep_suitepath is --%suitepath(core) --%suite(check_junit_rep_suitepath) --%displayname(Check JUNIT Get path for suitepath) - + --%test(check_junit_rep_suitepath) --%displayname(Check JUNIT Get path for suitepath) procedure check_junit_rep_suitepath; @@ -38,7 +38,7 @@ create or replace package body test_tfs_junit_reporter as execute immediate q'[create or replace package check_junit_flat_suitepath is --%suitepath(core.check_junit_rep_suitepath) --%suite(flatsuitepath) - + --%beforeall procedure donuffin; end;]'; @@ -49,8 +49,85 @@ create or replace package body test_tfs_junit_reporter as end; end;]'; - end; + execute immediate q'[create or replace package check_junit_in_context is + --%suitepath(core.check_junit_rep_suitepath) + --%suite(inctxsuite) + --%displayname(JUNIT test are inside context) + + -- %context(incontext) + -- %name(incontext) + + --%test(incontext) + --%displayname(Check JUNIT Get path incontext) + procedure check_junit_rep_incontext; + + -- %endcontext + end;]'; + execute immediate q'[create or replace package body check_junit_in_context is + procedure check_junit_rep_incontext is + begin + ut3_develop.ut.expect(1).to_equal(1); + end; + end;]'; + + execute immediate q'[create or replace package check_junit_out_context is + --%suitepath(core) + --%suite(outctxsuite) + --%displayname(JUNIT test are outside context) + + -- %context(outcontext) + -- %name(outcontext) + + -- %endcontext + + + --%test(outctx) + --%displayname(outctx) + procedure outctx; + + + end;]'; + execute immediate q'[create or replace package body check_junit_out_context is + procedure outctx is + begin + ut3_develop.ut.expect(1).to_equal(1); + end; + end;]'; + + execute immediate q'[create or replace package check_junit_inout_context is + --%suitepath(core) + --%suite(inoutcontext) + --%displayname(Test in and out of context) + -- %context(incontext) + -- %name(ProductincontextFeatures) + + --%test(inctx) + --%displayname(inctx) + procedure inctx; + + -- %endcontext + + + --%test(outctx) + --%displayname(outctx) + procedure outctx; + + + end;]'; + execute immediate q'[create or replace package body check_junit_inout_context is + procedure inctx is + begin + ut3_develop.ut.expect(1).to_equal(1); + end; + + procedure outctx is + begin + ut3_develop.ut.expect(1).to_equal(1); + end; + end;]'; + + end; procedure escapes_special_chars is l_results ut3_develop.ut_varchar2_list; @@ -92,7 +169,7 @@ create or replace package body test_tfs_junit_reporter as --Assert ut.expect(l_actual).to_be_like('%testcase classname="check_junit_reporting"%'); end; - + procedure check_flatten_nested_suites is l_results ut3_develop.ut_varchar2_list; l_actual clob; @@ -111,7 +188,7 @@ create or replace package body test_tfs_junit_reporter as
    %'); end; - + procedure check_nls_number_formatting is l_results ut3_develop.ut_varchar2_list; l_actual clob; @@ -163,5 +240,73 @@ create or replace package body test_tfs_junit_reporter as reporters.check_xml_encoding_included(ut3_develop.ut_tfs_junit_reporter(), 'UTF-8'); end; + procedure reports_only_test_in_ctx is + l_results ut3_develop.ut_varchar2_list; + l_actual clob; + begin + --Act + select * + bulk collect into l_results + from table(ut3_develop.ut.run('check_junit_in_context',ut3_develop.ut_tfs_junit_reporter())); + l_actual := ut3_tester_helper.main_helper.table_to_clob(l_results); + --Assert + ut.expect(l_actual).to_be_like(' + + + + + + + + +%'); + end; + + procedure reports_only_test_out_ctx is + l_results ut3_develop.ut_varchar2_list; + l_actual clob; + begin + --Act + select * + bulk collect into l_results + from table(ut3_develop.ut.run('check_junit_out_context',ut3_develop.ut_tfs_junit_reporter())); + l_actual := ut3_tester_helper.main_helper.table_to_clob(l_results); + --Assert + ut.expect(l_actual).to_be_like(' + + + + + + + + +%'); + end; + + procedure reports_only_test_inout_ctx is + l_results ut3_develop.ut_varchar2_list; + l_actual clob; + begin + --Act + select * + bulk collect into l_results + from table(ut3_develop.ut.run('check_junit_inout_context',ut3_develop.ut_tfs_junit_reporter())); + l_actual := ut3_tester_helper.main_helper.table_to_clob(l_results); + --Assert + ut.expect(l_actual).to_be_like(' + + + + + + + + + + +%'); + end; + end; -/ +/ \ No newline at end of file diff --git a/test/ut3_user/reporters/test_tfs_junit_reporter.pks b/test/ut3_user/reporters/test_tfs_junit_reporter.pks index 07acb4d21..70f78e334 100644 --- a/test/ut3_user/reporters/test_tfs_junit_reporter.pks +++ b/test/ut3_user/reporters/test_tfs_junit_reporter.pks @@ -30,6 +30,15 @@ create or replace package test_tfs_junit_reporter as --%test(Includes XML header with encoding when encoding provided) procedure check_encoding_included; + --%test(Reports only testsuites where there are any testcases, all tests are in context) + procedure reports_only_test_in_ctx; + + --%test(Reports only testsuites where there are any testcases, all tests are outside context) + procedure reports_only_test_out_ctx; + + --%test(Reports only testsuites where there are any testcases, one test in ctx one test outside) + procedure reports_only_test_inout_ctx; + --%afterall procedure remove_test_package; end; From d974ce31394118fbb6c1ca9d6aac5a290e16853d Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Fri, 29 Sep 2023 19:42:46 +0100 Subject: [PATCH 186/187] Update code --- source/reporters/ut_tfs_junit_reporter.tpb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/reporters/ut_tfs_junit_reporter.tpb b/source/reporters/ut_tfs_junit_reporter.tpb index 5b8702808..5e36aad17 100644 --- a/source/reporters/ut_tfs_junit_reporter.tpb +++ b/source/reporters/ut_tfs_junit_reporter.tpb @@ -97,18 +97,22 @@ create or replace type body ut_tfs_junit_reporter is l_tests ut_varchar2_list; begin for i in 1 .. a_suite.items.count loop - if a_suite.items(i) is of(ut_logical_suite) then - print_suite_results(treat(a_suite.items(i) as ut_logical_suite), a_suite_id, a_nested_tests); + if a_suite.items(i) is of(ut_suite_context) then + print_suite_results(treat(a_suite.items(i) as ut_suite_context), a_suite_id, a_nested_tests); + elsif a_suite.items(i) is of(ut_suite) then + print_suite_results(treat(a_suite.items(i) as ut_suite), a_suite_id, a_nested_tests); + elsif a_suite.items(i) is of(ut_logical_suite) then + print_suite_results(treat(a_suite.items(i) as ut_logical_suite), a_suite_id, a_nested_tests); end if; end loop; --Due to fact tha TFS and junit5 accepts only flat structure we have to report in suite level only. - if a_suite.self_type ='UT_SUITE_CONTEXT' then + if a_suite is of(ut_suite_context) then for i in 1 .. a_suite.items.count loop if a_suite.items(i) is of(ut_test) then ut_utils.append_to_list( a_nested_tests,(add_test_results(treat(a_suite.items(i) as ut_test)))); end if; end loop; - elsif a_suite.self_type ='UT_SUITE' then + elsif a_suite is of(ut_suite) then for i in 1 .. a_suite.items.count loop if a_suite.items(i) is of(ut_test) then ut_utils.append_to_list( a_nested_tests,(add_test_results(treat(a_suite.items(i) as ut_test)))); From 03b0566bda57947df59eb0dd3bfbdb203a6a79c4 Mon Sep 17 00:00:00 2001 From: Rachid EL AISSAOUI Date: Tue, 5 Dec 2023 23:46:45 +0100 Subject: [PATCH 187/187] Fix indentation --- docs/userguide/best-practices.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/userguide/best-practices.md b/docs/userguide/best-practices.md index 5148273e6..57a108fdd 100644 --- a/docs/userguide/best-practices.md +++ b/docs/userguide/best-practices.md @@ -15,9 +15,9 @@ The following are best practices we at utPLSQL have learned about PL/SQL and Uni - Tests should not mimic / duplicate the logic of tested code - Tests should contain zero logic (or as close to zero as possible) - The 3A rule: - - Arrange (setup inputs/data/environment for the tested code) - - Act (execute code under test) - - Assert (validate the outcomes of the execution) + - Arrange (setup inputs/data/environment for the tested code) + - Act (execute code under test) + - Assert (validate the outcomes of the execution) - Each tested procedure/function/trigger (code block) should have more than one test - Each test should check only one behavior (one requirement) of the code block under test - Tests should be maintained as thoroughly as production code