From 9b8d7f7e889593777ae46c3485d36d7ae3ef4bf9 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 31 Jan 2022 00:42:59 +0000 Subject: [PATCH 01/10] First commit of adding a new 21c json type. --- source/api/ut.pkb | 5 + source/api/ut.pks | 2 + .../data_values/ut_data_value_json.tpb | 7 + .../data_values/ut_data_value_json.tps | 1 + source/expectations/json_objects_specs.sql | 7 +- source/expectations/matchers/ut_equal.tpb | 6 + source/expectations/matchers/ut_equal.tps | 1 + source/expectations/ut_expectation.tpb | 5 + source/expectations/ut_expectation.tps | 1 + source/expectations/ut_expectation_json.tps | 2 +- .../expectations/test_expectations_json.pkb | 174 ++++++++++++++++++ .../expectations/test_expectations_json.pks | 25 ++- 12 files changed, 232 insertions(+), 4 deletions(-) diff --git a/source/api/ut.pkb b/source/api/ut.pkb index 9e3defe16..ee3d85342 100644 --- a/source/api/ut.pkb +++ b/source/api/ut.pkb @@ -98,6 +98,11 @@ create or replace package body ut is return ut_expectation_json(ut_data_value_json(a_actual), a_message); end; + function expect(a_actual in json , a_message varchar2 := null) return ut_expectation_json is + begin + return ut_expectation_json(ut_data_value_json(a_actual), a_message); + end; + procedure fail(a_message in varchar2) is begin ut_expectation_processor.report_failure(a_message); diff --git a/source/api/ut.pks b/source/api/ut.pks index 2cce4e183..df5a8d8e5 100644 --- a/source/api/ut.pks +++ b/source/api/ut.pks @@ -47,6 +47,8 @@ create or replace package ut authid current_user as function expect(a_actual in json_element_t , a_message varchar2 := null) return ut_expectation_json; + function expect(a_actual in json , a_message varchar2 := null) return ut_expectation_json; + procedure fail(a_message in varchar2); function run( diff --git a/source/expectations/data_values/ut_data_value_json.tpb b/source/expectations/data_values/ut_data_value_json.tpb index dfb3275ab..5d7232851 100644 --- a/source/expectations/data_values/ut_data_value_json.tpb +++ b/source/expectations/data_values/ut_data_value_json.tpb @@ -32,6 +32,13 @@ create or replace type body ut_data_value_json as return; end; + constructor function ut_data_value_json(self in out nocopy ut_data_value_json, a_value json) return self as result is + l_value json_element_t := case when a_value is null then cast (null as json_element_t ) else json_element_t.parse(json_query(a_value, '$' returning clob)) end; + begin + init(l_value); + return; + end; + overriding member function is_null return boolean is begin return (ut_utils.int_to_boolean(self.is_data_null)); diff --git a/source/expectations/data_values/ut_data_value_json.tps b/source/expectations/data_values/ut_data_value_json.tps index 135124e64..3b77e54eb 100644 --- a/source/expectations/data_values/ut_data_value_json.tps +++ b/source/expectations/data_values/ut_data_value_json.tps @@ -19,6 +19,7 @@ create or replace type ut_data_value_json under ut_compound_data_value( json_tree ut_json_tree_details, member procedure init (self in out nocopy ut_data_value_json, a_value json_element_t), constructor function ut_data_value_json(self in out nocopy ut_data_value_json, a_value json_element_t) return self as result, + constructor function ut_data_value_json(self in out nocopy ut_data_value_json, a_value json) return self as result, overriding member function is_null return boolean, overriding member function is_empty return boolean, overriding member function to_string return varchar2, diff --git a/source/expectations/json_objects_specs.sql b/source/expectations/json_objects_specs.sql index c0d42e8fb..58877eacd 100644 --- a/source/expectations/json_objects_specs.sql +++ b/source/expectations/json_objects_specs.sql @@ -1,7 +1,12 @@ BEGIN - $if dbms_db_version.version = 12 and dbms_db_version.release >= 2 or dbms_db_version.version > 12 $then + $if dbms_db_version.version >= 21 $then dbms_output.put_line('Object exists , dont install'); + $elsif dbms_db_version.version = 12 and dbms_db_version.release >= 2 or ( dbms_db_version.version > 12 and dbms_db_version.version < 21 ) $then + dbms_output.put_line('Installing json structures specs.'); + execute immediate q'[create or replace TYPE JSON FORCE AUTHID CURRENT_USER AS OBJECT( + dummyobjt NUMBER +) NOT FINAL NOT INSTANTIABLE;]'; $else dbms_output.put_line('Installing json structures specs.'); execute immediate q'[create or replace TYPE JSON_Element_T FORCE AUTHID CURRENT_USER AS OBJECT( diff --git a/source/expectations/matchers/ut_equal.tpb b/source/expectations/matchers/ut_equal.tpb index 05caf3b09..1519ede5b 100644 --- a/source/expectations/matchers/ut_equal.tpb +++ b/source/expectations/matchers/ut_equal.tpb @@ -158,6 +158,12 @@ create or replace type body ut_equal as return; end; + constructor function ut_equal(self in out nocopy ut_equal, a_expected json, a_nulls_are_equal boolean := null) return self as result is + begin + init(ut_data_value_json(a_expected), a_nulls_are_equal); + return; + end; + member function include(a_items varchar2) return ut_equal is l_result ut_equal := self; begin diff --git a/source/expectations/matchers/ut_equal.tps b/source/expectations/matchers/ut_equal.tps index eecbe8c1d..f348b39c7 100644 --- a/source/expectations/matchers/ut_equal.tps +++ b/source/expectations/matchers/ut_equal.tps @@ -42,6 +42,7 @@ create or replace type ut_equal force under ut_comparison_matcher( constructor function ut_equal(self in out nocopy ut_equal, a_expected yminterval_unconstrained, a_nulls_are_equal boolean := null) return self as result, constructor function ut_equal(self in out nocopy ut_equal, a_expected dsinterval_unconstrained, a_nulls_are_equal boolean := null) return self as result, constructor function ut_equal(self in out nocopy ut_equal, a_expected json_element_t, a_nulls_are_equal boolean := null) return self as result, + constructor function ut_equal(self in out nocopy ut_equal, a_expected json, a_nulls_are_equal boolean := null) return self as result, member function include(a_items varchar2) return ut_equal, member function include(a_items ut_varchar2_list) return ut_equal, member function exclude(a_items varchar2) return ut_equal, diff --git a/source/expectations/ut_expectation.tpb b/source/expectations/ut_expectation.tpb index dfad630a6..6579e2a00 100644 --- a/source/expectations/ut_expectation.tpb +++ b/source/expectations/ut_expectation.tpb @@ -201,6 +201,11 @@ create or replace type body ut_expectation as self.to_( ut_equal(a_expected, a_nulls_are_equal) ); end; + member procedure to_equal(self in ut_expectation, a_expected json, a_nulls_are_equal boolean := null) is + begin + self.to_( ut_equal(a_expected, a_nulls_are_equal) ); + end; + member procedure not_to_equal(self in ut_expectation, a_expected anydata, a_nulls_are_equal boolean := null) is begin self.not_to( ut_equal(a_expected, a_nulls_are_equal) ); diff --git a/source/expectations/ut_expectation.tps b/source/expectations/ut_expectation.tps index 45d768200..57691d109 100644 --- a/source/expectations/ut_expectation.tps +++ b/source/expectations/ut_expectation.tps @@ -55,6 +55,7 @@ create or replace type ut_expectation authid current_user as object( member procedure to_equal(self in ut_expectation, a_expected yminterval_unconstrained, a_nulls_are_equal boolean := null), member procedure to_equal(self in ut_expectation, a_expected dsinterval_unconstrained, a_nulls_are_equal boolean := null), member procedure to_equal(self in ut_expectation, a_expected json_element_t, a_nulls_are_equal boolean := null), + member procedure to_equal(self in ut_expectation, a_expected json, a_nulls_are_equal boolean := null), member procedure not_to_equal(self in ut_expectation, a_expected anydata, a_nulls_are_equal boolean := null), member procedure not_to_equal(self in ut_expectation, a_expected anydata, a_exclude varchar2, a_nulls_are_equal boolean := null), diff --git a/source/expectations/ut_expectation_json.tps b/source/expectations/ut_expectation_json.tps index f33c6a580..561c5d11f 100644 --- a/source/expectations/ut_expectation_json.tps +++ b/source/expectations/ut_expectation_json.tps @@ -24,4 +24,4 @@ create or replace type ut_expectation_json under ut_expectation( member procedure to_have_count(self in ut_expectation_json, a_expected integer), member procedure not_to_have_count(self in ut_expectation_json, a_expected integer) ) -/ +/ \ No newline at end of file diff --git a/test/ut3_user/expectations/test_expectations_json.pkb b/test/ut3_user/expectations/test_expectations_json.pkb index 9516ecb04..731cbcfd9 100644 --- a/test/ut3_user/expectations/test_expectations_json.pkb +++ b/test/ut3_user/expectations/test_expectations_json.pkb @@ -1608,5 +1608,179 @@ create or replace package body test_expectations_json is end; + procedure success_on_same_data_njson + as + l_actual json; + begin + -- Arrange + l_actual := json(' { + "Actors": [ + { + "name": "Tom Cruise", + "age": 56, + "Born At": "Syracuse, NY", + "Birthdate": "July 3, 1962", + "photo": "https://jsonformatter.org/img/tom-cruise.jpg", + "wife": null, + "weight": 67.5, + "hasChildren": true, + "hasGreyHair": false, + "children": [ + "Suri", + "Isabella Jane", + "Connor" + ] + }, + { + "name": "Robert Downey Jr.", + "age": 53, + "Born At": "New York City, NY", + "Birthdate": "April 4, 1965", + "photo": "https://jsonformatter.org/img/Robert-Downey-Jr.jpg", + "wife": "Susan Downey", + "weight": 77.1, + "hasChildren": true, + "hasGreyHair": false, + "children": [ + "Indio Falconer", + "Avri Roel", + "Exton Elias" + ] + } + ] + }'); + + --Act + ut3_develop.ut.expect( l_actual ).to_equal( l_actual ); + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + + procedure fail_on_diff_data_njson + as + l_expected json; + l_actual json; + l_expected_message varchar2(32767); + l_actual_message varchar2(32767); + begin + -- Arrange + l_expected := json('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); + l_actual := json('{"Aidan Gillen": {"array": ["Game of Thron\"es","The Wire"],"string": "some string","int": 2,"aboolean": true, "boolean": true,"object": {"foo": "bar","object1": {"new prop1": "new prop value"},"object2": {"new prop1": "new prop value"},"object3": {"new prop1": "new prop value"},"object4": {"new prop1": "new prop value"}}},"Amy Ryan": {"one": "In Treatment","two": "The Wire"},"Annie Fitzgerald": ["Big Love","True Blood"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsgard": ["Generation Kill","True Blood"], "Clarke Peters": null}'); + + --Act + ut3_develop.ut.expect( l_actual ).to_equal( l_expected ); + --Assert + l_expected_message := q'[%Missing property: "Alexander Skarsg?rd" on path: $ +%Extra property: "Alexander Skarsgard" on path: $ +%Missing property: "Alice Farmer" on path: $ +%Extra property: "Clarke Peters" on path: $ +%Extra property: "one" on path: $."Amy Ryan" +%Missing property: "The Sopranos" on path: $."Annie Fitzgerald"[2] +%Extra property: "two" on path: $."Amy Ryan" +%Missing property: "Oz" on path: $."Annie Fitzgerald"[3] +%Missing property: "otherint" on path: $."Aidan Gillen" +%Extra property: "object1" on path: $."Aidan Gillen"."object" +%Extra property: "object2" on path: $."Aidan Gillen"."object" +%Extra property: "object3" on path: $."Aidan Gillen"."object" +%Extra property: "object4" on path: $."Aidan Gillen"."object" +%Actual type: 'array' was expected to be: 'object' on path: $."Amy Ryan" +%Actual type: 'string' was expected to be: 'number' on path: $."Aidan Gillen"."int" +%Actual type: 'string' was expected to be: 'boolean' on path: $."Aidan Gillen"."aboolean" +%Actual value: "True Blood" was expected to be: "Big Love" on path: $."Annie Fitzgerald"[0] +%Actual value: "Big Love" was expected to be: "True Blood" on path: $."Annie Fitzgerald"[1] +%Actual value: FALSE was expected to be: TRUE on path: $."Aidan Gillen"."boolean" +%Actual value: "Game of Thrones" was expected to be: "Game of Thron\"es" on path: $."Aidan Gillen"."array"[0]%]'; + l_actual_message := ut3_tester_helper.main_helper.get_failed_expectations(1); + --Assert + ut.expect(l_actual_message).to_be_like(l_expected_message); + ut.expect(l_actual_message).to_be_like('%Diff: 20 differences found%'); + ut.expect(l_actual_message).to_be_like('%13 missing properties%'); + ut.expect(l_actual_message).to_be_like('%4 unequal values%'); + ut.expect(l_actual_message).to_be_like('%3 incorrect types%'); + end; + + + --Please note that by the looks of things the call to json() results in null value being returned. + procedure null_json_variable_njson + as + l_expected json ; + begin + -- Arrange + l_expected := cast (null as json ); + + --Act + ut3_develop.ut.expect( l_expected ).to_be_null; + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + + procedure to_have_count_njson as + l_actual json; + l_expected_message varchar2(32767); + l_actual_message varchar2(32767); + begin + -- Arrange + l_actual := json('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); + + --Act + ut3_develop.ut.expect( l_actual ).to_have_count( 6 ); + + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + + end; + + procedure fail_to_have_count_njson + as + l_actual json; + l_expected_message varchar2(32767); + l_actual_message varchar2(32767); + begin + -- Arrange + l_actual := json('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); + + --Act + ut3_develop.ut.expect( l_actual ).to_have_count( 2 ); + --Assert + l_expected_message := q'[%Actual: (json [ count = 6 ]) was expected to have [ count = 2 ]%]'; + 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 not_to_have_count_njson + as + l_actual json; + l_expected_message varchar2(32767); + l_actual_message varchar2(32767); + begin + -- Arrange + l_actual := json('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); + + --Act + ut3_develop.ut.expect( l_actual ).not_to_have_count( 7 ); + --Assert + ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); + end; + + procedure fail_not_to_have_count_njson + as + l_actual json; + l_expected_message varchar2(32767); + l_actual_message varchar2(32767); + begin + -- Arrange + l_actual := json('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); + + --Act + ut3_develop.ut.expect( l_actual ).not_to_have_count( 6 ); + --Assert + l_expected_message := q'[%Actual: json [ count = 6 ] was expected not to have [ count = 6 ]%]'; + 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; + end; / diff --git a/test/ut3_user/expectations/test_expectations_json.pks b/test/ut3_user/expectations/test_expectations_json.pks index 64dff42e8..4cee67526 100644 --- a/test/ut3_user/expectations/test_expectations_json.pks +++ b/test/ut3_user/expectations/test_expectations_json.pks @@ -39,13 +39,13 @@ create or replace package test_expectations_json is --%test( Json object to have count ) procedure to_have_count; - --%test( Fail Json object to have count) + --%test( Fail Json object to have count) procedure fail_to_have_count; --%test( Json object not to have count) procedure not_to_have_count; - --%test( Fail Json object not to have count) + --%test( Fail Json object not to have count) procedure fail_not_to_have_count; --%test( Json object to have count on array) @@ -74,6 +74,27 @@ create or replace package test_expectations_json is --%test( Compare two json arrays ) procedure check_json_arrays; + + --%test(Gives success for identical data using native json for 21c and above) + procedure success_on_same_data_njson; + + --%test(Gives failure for different data using native json for 21c and above) + procedure fail_on_diff_data_njson; + + --%test( Json variable is null using native json for 21c and above) + procedure null_json_variable_njson; + + --%test( Json object to have count using native json for 21c and above) + procedure to_have_count_njson; + + --%test( Fail Json object to have count using native json for 21c and above) + procedure fail_to_have_count_njson; + + --%test( Json object not to have count using native json for 21c and above) + procedure not_to_have_count_njson; + + --%test( Fail Json object not to have count using native json for 21c and above) + procedure fail_not_to_have_count_njson; end; / From 3d3f0bee3e9708f6402e59029e9728b0d82bdefc Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Mon, 31 Jan 2022 00:50:46 +0000 Subject: [PATCH 02/10] Update install on 11c to add new json type. --- source/expectations/json_objects_specs.sql | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/expectations/json_objects_specs.sql b/source/expectations/json_objects_specs.sql index 58877eacd..39c2c4e23 100644 --- a/source/expectations/json_objects_specs.sql +++ b/source/expectations/json_objects_specs.sql @@ -3,11 +3,16 @@ BEGIN $if dbms_db_version.version >= 21 $then dbms_output.put_line('Object exists , dont install'); $elsif dbms_db_version.version = 12 and dbms_db_version.release >= 2 or ( dbms_db_version.version > 12 and dbms_db_version.version < 21 ) $then - dbms_output.put_line('Installing json structures specs.'); + dbms_output.put_line('Installing json structures specs for native json.'); + execute immediate q'[create or replace TYPE JSON FORCE AUTHID CURRENT_USER AS OBJECT( + dummyobjt NUMBER +) NOT FINAL NOT INSTANTIABLE;]'; + $else + dbms_output.put_line('Installing json structures specs for native json.'); execute immediate q'[create or replace TYPE JSON FORCE AUTHID CURRENT_USER AS OBJECT( dummyobjt NUMBER ) NOT FINAL NOT INSTANTIABLE;]'; - $else + dbms_output.put_line('Installing json structures specs.'); execute immediate q'[create or replace TYPE JSON_Element_T FORCE AUTHID CURRENT_USER AS OBJECT( dummyobjt NUMBER, From 9002fbce682677e8983e3a3e1f338f58aecc0817 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 1 Feb 2022 00:14:40 +0000 Subject: [PATCH 03/10] Making tests below 21 compilation conditional so it wont fail. --- .../data_values/ut_compound_data_helper.pkb | 11 +++++++++++ .../data_values/ut_compound_data_helper.pks | 2 ++ .../expectations/data_values/ut_data_value_json.tpb | 2 +- test/ut3_user/expectations/test_expectations_json.pkb | 6 ++++-- test/ut3_user/expectations/test_expectations_json.pks | 5 ++++- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/source/expectations/data_values/ut_compound_data_helper.pkb b/source/expectations/data_values/ut_compound_data_helper.pkb index 37d9901ff..4847a248c 100644 --- a/source/expectations/data_values/ut_compound_data_helper.pkb +++ b/source/expectations/data_values/ut_compound_data_helper.pkb @@ -781,6 +781,17 @@ create or replace package body ut_compound_data_helper is return l_diffs; end; + function get_json_object(a_json_t json) return json_element_t is + l_json JSON; + l_obj json_element_t; + begin + $if dbms_db_version.version >= 21 $then + l_obj := case when a_json_t is null then cast (null as json_element_t ) else json_element_t.parse(json_query(a_value, '$' returning clob)) end; + $else + l_obj := null; + $end + end; + begin g_anytype_name_map(dbms_types.typecode_date) := 'DATE'; g_anytype_name_map(dbms_types.typecode_number) := 'NUMBER'; diff --git a/source/expectations/data_values/ut_compound_data_helper.pks b/source/expectations/data_values/ut_compound_data_helper.pks index 53b0846b8..451cd9bac 100644 --- a/source/expectations/data_values/ut_compound_data_helper.pks +++ b/source/expectations/data_values/ut_compound_data_helper.pks @@ -134,5 +134,7 @@ create or replace package ut_compound_data_helper authid definer is function get_json_diffs_type(a_diff_id raw) return tt_json_diff_type_tab; + function get_json_object(a_json_t json) return json_element_t; + end; / diff --git a/source/expectations/data_values/ut_data_value_json.tpb b/source/expectations/data_values/ut_data_value_json.tpb index 5d7232851..40bf81dbb 100644 --- a/source/expectations/data_values/ut_data_value_json.tpb +++ b/source/expectations/data_values/ut_data_value_json.tpb @@ -33,7 +33,7 @@ create or replace type body ut_data_value_json as end; constructor function ut_data_value_json(self in out nocopy ut_data_value_json, a_value json) return self as result is - l_value json_element_t := case when a_value is null then cast (null as json_element_t ) else json_element_t.parse(json_query(a_value, '$' returning clob)) end; + l_value json_element_t := ut_compound_data_helper.get_json_object(a_value); begin init(l_value); return; diff --git a/test/ut3_user/expectations/test_expectations_json.pkb b/test/ut3_user/expectations/test_expectations_json.pkb index 731cbcfd9..3fc28ff03 100644 --- a/test/ut3_user/expectations/test_expectations_json.pkb +++ b/test/ut3_user/expectations/test_expectations_json.pkb @@ -1607,7 +1607,8 @@ create or replace package body test_expectations_json is ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0); end; - + $if dbms_db_version.version >= 21 $then + procedure success_on_same_data_njson as l_actual json; @@ -1781,6 +1782,7 @@ create or replace package body test_expectations_json is --Assert ut.expect(l_actual_message).to_be_like(l_expected_message); end; - + + $end end; / diff --git a/test/ut3_user/expectations/test_expectations_json.pks b/test/ut3_user/expectations/test_expectations_json.pks index 4cee67526..286106a58 100644 --- a/test/ut3_user/expectations/test_expectations_json.pks +++ b/test/ut3_user/expectations/test_expectations_json.pks @@ -75,6 +75,8 @@ create or replace package test_expectations_json is --%test( Compare two json arrays ) procedure check_json_arrays; + $if dbms_db_version.version >= 21 $then + --%test(Gives success for identical data using native json for 21c and above) procedure success_on_same_data_njson; @@ -95,6 +97,7 @@ create or replace package test_expectations_json is --%test( Fail Json object not to have count using native json for 21c and above) procedure fail_not_to_have_count_njson; - + + $end end; / From b270d4e02745ca3455c4b1db2523161d683b369c Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 1 Feb 2022 00:26:56 +0000 Subject: [PATCH 04/10] Fixing conditional compilation --- source/expectations/data_values/ut_compound_data_helper.pkb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/expectations/data_values/ut_compound_data_helper.pkb b/source/expectations/data_values/ut_compound_data_helper.pkb index 4847a248c..fe3dc6946 100644 --- a/source/expectations/data_values/ut_compound_data_helper.pkb +++ b/source/expectations/data_values/ut_compound_data_helper.pkb @@ -786,7 +786,7 @@ create or replace package body ut_compound_data_helper is l_obj json_element_t; begin $if dbms_db_version.version >= 21 $then - l_obj := case when a_json_t is null then cast (null as json_element_t ) else json_element_t.parse(json_query(a_value, '$' returning clob)) end; + l_obj := case when a_json_t is null then cast (null as json_element_t ) else json_element_t.parse(json_query(a_json_t, '$' returning clob)) end; $else l_obj := null; $end From 5b1c1d38984e08f04467e3a4e44cc6032b2f6fef Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 1 Feb 2022 00:36:02 +0000 Subject: [PATCH 05/10] Missing return from function. --- source/expectations/data_values/ut_compound_data_helper.pkb | 1 + 1 file changed, 1 insertion(+) diff --git a/source/expectations/data_values/ut_compound_data_helper.pkb b/source/expectations/data_values/ut_compound_data_helper.pkb index fe3dc6946..558b007d9 100644 --- a/source/expectations/data_values/ut_compound_data_helper.pkb +++ b/source/expectations/data_values/ut_compound_data_helper.pkb @@ -790,6 +790,7 @@ create or replace package body ut_compound_data_helper is $else l_obj := null; $end + return l_obj; end; begin From 0d8cbea403026db10e939e942fdca01de98adec0 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 1 Feb 2022 01:01:13 +0000 Subject: [PATCH 06/10] Added mention about new type into userguide. --- docs/userguide/expectations.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index c07f3782e..07ff647e5 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1643,7 +1643,7 @@ FAILURE # Comparing Json objects -utPLSQL is capable of comparing json data-types **on Oracle 12.2 and above**. +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** ### Notes on comparison of json data @@ -1651,10 +1651,11 @@ utPLSQL is capable of comparing json data-types **on Oracle 12.2 and above**. - During comparison of json objects the order doesn't matter. - During comparison of json arrays the index of element is taken into account - To compare json you have to make sure its type of `json_element_t` or its subtypes +- From version 21 and above a native `json` type is supported. -Compare JSON example: +Compare JSON example using `json_element_t`: ```sql declare l_expected json_element_t; @@ -1736,7 +1737,7 @@ FAILURE at "anonymous block", line 59 ``` -Comparing parts of JSON example: +Comparing parts of JSON example using `json_element_t` subtypes: ```sql declare l_actual json_object_t; From 21b3cb39415331a93378ffc61752c149a5481cbf Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 1 Feb 2022 01:15:19 +0000 Subject: [PATCH 07/10] Fixing sonar. --- source/expectations/data_values/ut_compound_data_helper.pkb | 1 - 1 file changed, 1 deletion(-) diff --git a/source/expectations/data_values/ut_compound_data_helper.pkb b/source/expectations/data_values/ut_compound_data_helper.pkb index 558b007d9..e29f10279 100644 --- a/source/expectations/data_values/ut_compound_data_helper.pkb +++ b/source/expectations/data_values/ut_compound_data_helper.pkb @@ -782,7 +782,6 @@ create or replace package body ut_compound_data_helper is end; function get_json_object(a_json_t json) return json_element_t is - l_json JSON; l_obj json_element_t; begin $if dbms_db_version.version >= 21 $then From 075fe522031534e5aceea1f0d33a531dec8b522b Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Tue, 1 Feb 2022 19:58:30 +0000 Subject: [PATCH 08/10] Adding conditional execution of sonarcloud. --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 87d577554..7d42b08f1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -131,6 +131,7 @@ jobs: - name: SonarCloud Scan id: sonar + if: ${{ matrix.db_version_name == '21xe' }} uses: SonarSource/sonarcloud-github-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any From dc14dc754505f4d979fd21dcded366bd94c84a84 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Wed, 2 Feb 2022 09:39:52 +0000 Subject: [PATCH 09/10] Fixing issue 1113 where the act were inserted into exp --- .../data_values/ut_data_value_json.tpb | 2 +- .../expectations/test_expectations_json.pkb | 39 ++++++++++++++----- .../expectations/test_expectations_json.pks | 4 ++ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/source/expectations/data_values/ut_data_value_json.tpb b/source/expectations/data_values/ut_data_value_json.tpb index 40bf81dbb..b703af181 100644 --- a/source/expectations/data_values/ut_data_value_json.tpb +++ b/source/expectations/data_values/ut_data_value_json.tpb @@ -147,7 +147,7 @@ create or replace type body ut_data_value_json as l_result := case when ut_compound_data_helper.insert_json_diffs( - l_diff_id, self.json_tree.json_tree_info, l_other.json_tree.json_tree_info + l_diff_id, l_other.json_tree.json_tree_info, self.json_tree.json_tree_info ) > 0 then 1 else 0 end; diff --git a/test/ut3_user/expectations/test_expectations_json.pkb b/test/ut3_user/expectations/test_expectations_json.pkb index 3fc28ff03..677ba2578 100644 --- a/test/ut3_user/expectations/test_expectations_json.pkb +++ b/test/ut3_user/expectations/test_expectations_json.pkb @@ -62,8 +62,8 @@ create or replace package body test_expectations_json is l_actual_message varchar2(32767); begin -- Arrange - l_expected := json_element_t.parse('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); - l_actual := json_element_t.parse('{"Aidan Gillen": {"array": ["Game of Thron\"es","The Wire"],"string": "some string","int": 2,"aboolean": true, "boolean": true,"object": {"foo": "bar","object1": {"new prop1": "new prop value"},"object2": {"new prop1": "new prop value"},"object3": {"new prop1": "new prop value"},"object4": {"new prop1": "new prop value"}}},"Amy Ryan": {"one": "In Treatment","two": "The Wire"},"Annie Fitzgerald": ["Big Love","True Blood"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsgard": ["Generation Kill","True Blood"], "Clarke Peters": null}'); + l_actual := json_element_t.parse('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); + l_expected := json_element_t.parse('{"Aidan Gillen": {"array": ["Game of Thron\"es","The Wire"],"string": "some string","int": 2,"aboolean": true, "boolean": true,"object": {"foo": "bar","object1": {"new prop1": "new prop value"},"object2": {"new prop1": "new prop value"},"object3": {"new prop1": "new prop value"},"object4": {"new prop1": "new prop value"}}},"Amy Ryan": {"one": "In Treatment","two": "The Wire"},"Annie Fitzgerald": ["Big Love","True Blood"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsgard": ["Generation Kill","True Blood"], "Clarke Peters": null}'); --Act ut3_develop.ut.expect( l_actual ).to_equal( l_expected ); @@ -387,7 +387,7 @@ create or replace package body test_expectations_json is l_actual_message varchar2(32767); begin -- Arrange - l_expected := json_object_t.parse(' { + l_actual := json_object_t.parse(' { "Actors": [ { "name": "Tom Cruise", @@ -424,7 +424,7 @@ create or replace package body test_expectations_json is ] }' ); - l_actual := json_object_t.parse(' { + l_expected := json_object_t.parse(' { "Actors": { "name": "Krzystof Jarzyna", @@ -444,8 +444,8 @@ create or replace package body test_expectations_json is --Act - ut3_develop.ut.expect(json_array_t(json_query(l_actual.stringify,'$.Actors.children'))).to_equal(json_array_t(json_query(l_expected - .stringify,'$.Actors[1].children'))); + ut3_develop.ut.expect(json_array_t(json_query(l_actual.stringify,'$.Actors[1].children'))).to_equal(json_array_t(json_query(l_expected + .stringify,'$.Actors.children'))); --Assert l_expected_message := q'[%Actual: json was expected to equal: json %Diff: 1 differences found @@ -1055,7 +1055,7 @@ create or replace package body test_expectations_json is l_actual_message varchar2(32767); begin -- Arrange - l_expected := json_element_t.parse('[ + l_actual := json_element_t.parse('[ { "_id": "5ce6ec46cb9977b050f15d97", "index": 0, @@ -1282,7 +1282,7 @@ create or replace package body test_expectations_json is "favoriteFruit": "strawberry" } ]'); - l_actual := json_element_t.parse('[ + l_expected := json_element_t.parse('[ { "_id": "5ce6ec6660565269b16cf836", "index": 0, @@ -1665,8 +1665,8 @@ create or replace package body test_expectations_json is l_actual_message varchar2(32767); begin -- Arrange - l_expected := json('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); - l_actual := json('{"Aidan Gillen": {"array": ["Game of Thron\"es","The Wire"],"string": "some string","int": 2,"aboolean": true, "boolean": true,"object": {"foo": "bar","object1": {"new prop1": "new prop value"},"object2": {"new prop1": "new prop value"},"object3": {"new prop1": "new prop value"},"object4": {"new prop1": "new prop value"}}},"Amy Ryan": {"one": "In Treatment","two": "The Wire"},"Annie Fitzgerald": ["Big Love","True Blood"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsgard": ["Generation Kill","True Blood"], "Clarke Peters": null}'); + l_actual := json('{"Aidan Gillen": {"array": ["Game of Thrones","The Wire"],"string": "some string","int": "2","otherint": 4, "aboolean": "true", "boolean": false,"object": {"foo": "bar"}},"Amy Ryan": ["In Treatment","The Wire"],"Annie Fitzgerald": ["True Blood","Big Love","The Sopranos","Oz"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsg?rd": ["Generation Kill","True Blood"],"Alice Farmer": ["The Corner","Oz","The Wire"]}'); + l_expected := json('{"Aidan Gillen": {"array": ["Game of Thron\"es","The Wire"],"string": "some string","int": 2,"aboolean": true, "boolean": true,"object": {"foo": "bar","object1": {"new prop1": "new prop value"},"object2": {"new prop1": "new prop value"},"object3": {"new prop1": "new prop value"},"object4": {"new prop1": "new prop value"}}},"Amy Ryan": {"one": "In Treatment","two": "The Wire"},"Annie Fitzgerald": ["Big Love","True Blood"],"Anwan Glover": ["Treme","The Wire"],"Alexander Skarsgard": ["Generation Kill","True Blood"], "Clarke Peters": null}'); --Act ut3_develop.ut.expect( l_actual ).to_equal( l_expected ); @@ -1784,5 +1784,24 @@ create or replace package body test_expectations_json is end; $end + + procedure p_1113_reg_exp_chg_with_act is + l_expected_message varchar2(32767); + l_actual_message varchar2(32767); + begin + ut3_develop.ut.expect(json_element_t.parse('{"a":"value a"}')).to_equal(json_element_t.parse('{"a":"value b"}')); + + --Assert + l_expected_message := q'[%Actual: json was expected to equal: json +%Diff: 1 differences found +%1 unequal values +%Actual value: "value a" was expected to be: "value b" on path: $."a"%]'; + + 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; + + end; / diff --git a/test/ut3_user/expectations/test_expectations_json.pks b/test/ut3_user/expectations/test_expectations_json.pks index 286106a58..410c3050b 100644 --- a/test/ut3_user/expectations/test_expectations_json.pks +++ b/test/ut3_user/expectations/test_expectations_json.pks @@ -99,5 +99,9 @@ create or replace package test_expectations_json is procedure fail_not_to_have_count_njson; $end + + --%test( Regression scenario tests for issue #1113 where the expected has been switched with actual) + procedure p_1113_reg_exp_chg_with_act; + end; / From cbe03e830810da8ce588368eacc6504f1e42dd22 Mon Sep 17 00:00:00 2001 From: Lukasz Wasylow Date: Sun, 6 Feb 2022 16:09:07 +0000 Subject: [PATCH 10/10] Update test coverage and documentation --- docs/userguide/expectations.md | 4 ++++ source/expectations/data_values/ut_compound_data_helper.pkb | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/userguide/expectations.md b/docs/userguide/expectations.md index 07ff647e5..52e233125 100644 --- a/docs/userguide/expectations.md +++ b/docs/userguide/expectations.md @@ -1645,6 +1645,10 @@ 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. + + ### Notes on comparison of json data - Json data can contain objects, scalar or arrays. diff --git a/source/expectations/data_values/ut_compound_data_helper.pkb b/source/expectations/data_values/ut_compound_data_helper.pkb index e29f10279..94c7c1ab8 100644 --- a/source/expectations/data_values/ut_compound_data_helper.pkb +++ b/source/expectations/data_values/ut_compound_data_helper.pkb @@ -786,8 +786,6 @@ create or replace package body ut_compound_data_helper is begin $if dbms_db_version.version >= 21 $then l_obj := case when a_json_t is null then cast (null as json_element_t ) else json_element_t.parse(json_query(a_json_t, '$' returning clob)) end; - $else - l_obj := null; $end return l_obj; end;