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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Legend

2021-08-XX v.1.16.0
------------------
* DB Access in UT: Local Inheritance (#498)
* Skip 'Prefer RETURNING to EXPORTING' when both exist (#490)
* Pseudo Comment Usage: Multiple Inline Entries (#494)
* Prefer Pragmas to Pseudo Comments: Multiple Pseudo Comments (#489)
Expand Down
176 changes: 98 additions & 78 deletions src/checks/y_check_db_access_in_ut.clas.abap
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ CLASS y_check_db_access_in_ut DEFINITION PUBLIC INHERITING FROM y_check_base CRE
END OF keys.

TYPES: BEGIN OF properties,
name TYPE string,
risk_level TYPE string,
name TYPE string,
risk_level TYPE string,
has_framework TYPE abap_bool,
END OF properties.

DATA defined_classes TYPE STANDARD TABLE OF properties.
Expand All @@ -59,8 +60,8 @@ CLASS y_check_db_access_in_ut DEFINITION PUBLIC INHERITING FROM y_check_base CRE
statement TYPE sstmnt
structure TYPE sstruc.

METHODS is_part_of_framework IMPORTING structure TYPE sstruc
RETURNING VALUE(result) TYPE abap_bool.
METHODS is_it_using_framework RETURNING VALUE(result) TYPE abap_bool.
METHODS is_superclass_using_framework RETURNING VALUE(result) TYPE abap_bool.

METHODS is_persistent_object IMPORTING obj_name TYPE tadir-obj_name
RETURNING VALUE(result) TYPE abap_bool.
Expand Down Expand Up @@ -101,6 +102,15 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION.
ENDMETHOD.


METHOD inspect_structures.
relevant_statement_types = VALUE #( ( scan_struc_stmnt_type-class_definition ) ).
super->inspect_structures( ).

relevant_statement_types = VALUE #( ( scan_struc_stmnt_type-class_implementation ) ).
super->inspect_structures( ).
ENDMETHOD.


METHOD inspect_tokens.
CASE structure-stmnt_type.
WHEN scan_struc_stmnt_type-class_definition.
Expand All @@ -116,57 +126,73 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION.
ENDMETHOD.


METHOD is_persistent_object.
DATA(upper_name) = to_upper( obj_name ).

SELECT SINGLE @abap_true
FROM tadir
INTO @result
WHERE obj_name = @upper_name
AND object = @keys-table
AND delflag = @space.
ENDMETHOD.
METHOD add_line_to_defined_classes.
TRY.
DATA(class_config) = VALUE properties( name = get_class_name( structure ) ).
CATCH cx_sy_itab_line_not_found.
RETURN.
ENDTRY.

IF line_exists( defined_classes[ name = class_config-name ] ).
RETURN.
ENDIF.

METHOD is_internal_table.
CONSTANTS max_name_size TYPE i VALUE 40.
class_config-risk_level = get_risk_level( statement ).

DATA(second_token) = get_token_abs( statement-from + 1 ).
DATA(third_token) = get_token_abs( statement-from + 2 ).
DATA(fourth_token) = get_token_abs( statement-from + 2 ).
class_config-has_framework = xsdbool( is_it_using_framework( )
OR is_superclass_using_framework( ) ).

IF second_token = keys-into.
RETURN.
ENDIF.
APPEND class_config TO defined_classes.
ENDMETHOD.

DATA(table_name) = COND #( WHEN second_token = keys-from THEN third_token
WHEN third_token = keys-into THEN fourth_token
ELSE second_token ).

IF strlen( table_name ) > max_name_size.
RETURN.
METHOD get_class_name.
DATA(index) = ref_scan->statements[ structure-stmnt_from ]-from.
IF get_token_abs( index ) = keys-class.
result = get_token_abs( index + 1 ).
ENDIF.
ENDMETHOD.

result = xsdbool( is_persistent_object( CONV #( table_name ) ) = abap_false ).

METHOD get_risk_level.
LOOP AT ref_scan->tokens ASSIGNING FIELD-SYMBOL(<token>)
FROM statement-from TO statement-to
WHERE str = risk_level-harmless
OR str = risk_level-dangerous
OR str = risk_level-critical.
result = <token>-str.
ENDLOOP.
ENDMETHOD.


METHOD add_line_to_defined_classes.
TRY.
DATA(class_config) = VALUE properties( name = get_class_name( structure ) ).
CATCH cx_sy_itab_line_not_found.
METHOD is_it_using_framework.
LOOP AT ref_scan->statements ASSIGNING FIELD-SYMBOL(<statement>)
FROM structure_wa-stmnt_from TO structure_wa-stmnt_to.
LOOP AT ref_scan->tokens TRANSPORTING NO FIELDS
FROM <statement>-from TO <statement>-to
WHERE str = framework-qsql_if
OR str = framework-qsql_cl
OR str = framework-cds_if
OR str = framework-cds_cl.
result = abap_true.
RETURN.
ENDTRY.
ENDLOOP.
ENDLOOP.
ENDMETHOD.

IF line_exists( defined_classes[ name = class_config-name ] ).
RETURN.
ENDIF.

class_config-risk_level = get_risk_level( statement ).
METHOD is_superclass_using_framework.
statement_wa = ref_scan->statements[ structure_wa-stmnt_from ].

DATA(superclass) = next2( p_word1 = 'INHERITING'
p_word2 = 'FROM' ).

IF is_part_of_framework( structure ) = abap_false.
APPEND class_config TO defined_classes.
IF superclass IS INITIAL.
RETURN.
ENDIF.

result = xsdbool( line_exists( defined_classes[ name = superclass
has_framework = abap_true ] ) ).
ENDMETHOD.


Expand All @@ -177,7 +203,8 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION.
RETURN.
ENDTRY.

IF NOT line_exists( defined_classes[ name = class_name ] ).
IF NOT line_exists( defined_classes[ name = class_name
has_framework = abap_false ] ).
RETURN.
ENDIF.

Expand Down Expand Up @@ -232,54 +259,47 @@ CLASS Y_CHECK_DB_ACCESS_IN_UT IMPLEMENTATION.
ENDMETHOD.


METHOD is_part_of_framework.
LOOP AT ref_scan->statements ASSIGNING FIELD-SYMBOL(<statement>)
FROM structure-stmnt_from TO structure-stmnt_to.
LOOP AT ref_scan->tokens TRANSPORTING NO FIELDS
FROM <statement>-from TO <statement>-to
WHERE str = framework-qsql_if
OR str = framework-qsql_cl
OR str = framework-cds_if
OR str = framework-cds_cl.
result = abap_true.
RETURN.
ENDLOOP.
ENDLOOP.
METHOD has_ddic_itab_same_syntax.
result = xsdbool( token-str = check_for-modify
OR token-str = check_for-update
OR token-str = check_for-delete
OR token-str = check_for-insert ).
ENDMETHOD.


METHOD get_class_name.
DATA(index) = ref_scan->statements[ structure-stmnt_from ]-from.
IF get_token_abs( index ) = keys-class.
result = get_token_abs( index + 1 ).
ENDIF.
METHOD is_persistent_object.
DATA(upper_name) = to_upper( obj_name ).

SELECT SINGLE @abap_true
FROM tadir
INTO @result
WHERE obj_name = @upper_name
AND object = @keys-table
AND delflag = @space.
ENDMETHOD.


METHOD get_risk_level.
LOOP AT ref_scan->tokens ASSIGNING FIELD-SYMBOL(<token>)
FROM statement-from TO statement-to
WHERE str = risk_level-harmless
OR str = risk_level-dangerous
OR str = risk_level-critical.
result = <token>-str.
ENDLOOP.
ENDMETHOD.
METHOD is_internal_table.
CONSTANTS max_name_size TYPE i VALUE 40.

DATA(second_token) = get_token_abs( statement-from + 1 ).
DATA(third_token) = get_token_abs( statement-from + 2 ).
DATA(fourth_token) = get_token_abs( statement-from + 2 ).

METHOD inspect_structures.
relevant_statement_types = VALUE #( ( scan_struc_stmnt_type-class_definition ) ).
super->inspect_structures( ).
IF second_token = keys-into.
RETURN.
ENDIF.

relevant_statement_types = VALUE #( ( scan_struc_stmnt_type-class_implementation ) ).
super->inspect_structures( ).
ENDMETHOD.
DATA(table_name) = COND #( WHEN second_token = keys-from THEN third_token
WHEN third_token = keys-into THEN fourth_token
ELSE second_token ).

IF strlen( table_name ) > max_name_size.
RETURN.
ENDIF.

METHOD has_ddic_itab_same_syntax.
result = xsdbool( token-str = check_for-modify
OR token-str = check_for-update
OR token-str = check_for-delete
OR token-str = check_for-insert ).
result = xsdbool( is_persistent_object( CONV #( table_name ) ) = abap_false ).
ENDMETHOD.


ENDCLASS.
76 changes: 76 additions & 0 deletions src/checks/y_check_db_access_in_ut.clas.testclasses.abap
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,74 @@ CLASS ltc_osql_framework IMPLEMENTATION.

ENDCLASS.



CLASS ltc_osql_framework_inherited DEFINITION INHERITING FROM ltc_osql_framework FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_code_without_issue REDEFINITION.
ENDCLASS.

CLASS ltc_osql_framework_inherited IMPLEMENTATION.

METHOD get_code_without_issue.
result = VALUE #(
( ' REPORT ut_test. ' )

( ' CLASS lcl_base DEFINITION FOR TESTING. ' )
( ' PROTECTED SECTION. ' )
( ' METHODS given_fake_value. ' )
( ' METHODS when_select. ' )
( ' METHODS then_has_entry. ' )
( ' PRIVATE SECTION. ' )
( ' CLASS-DATA osql_test_environment TYPE REF TO if_osql_test_environment. ' )
( ' DATA cut TYPE tadir. ' )
( ' CLASS-METHODS class_setup. ' )
( ' CLASS-METHODS class_teardown. ' )
( ' ENDCLASS.' )

( ' CLASS lcl_base IMPLEMENTATION. ' )

( ' METHOD class_setup. ' )
( | osql_test_environment = cl_osql_test_environment=>create( VALUE #( ( 'tadir' ) ) ). | )
( ' ENDMETHOD. ' )

( ' METHOD class_teardown. ' )
( ' osql_test_environment->destroy( ). ' )
( ' ENDMETHOD. ' )

( ' METHOD given_fake_value. ' )
( ' "osql_test_environment->insert_test_data( data ). ' )
( ' ENDMETHOD. ' )

( ' METHOD when_select. ' )
( ' SELECT SINGLE * FROM tadir INTO cut. ' )
( ' ENDMETHOD. ' )

( ' METHOD then_has_entry. ' )
( ' cl_abap_unit_assert=>assert_not_initial( cut ). ' )
( ' ENDMETHOD. ' )

( ' ENDCLASS. ' )

( ' CLASS lcl_test DEFINITION FOR TESTING INHERITING FROM lcl_base. ' )
( ' PUBLIC SECTION. ' )
( ' METHODS scenario FOR TESTING. ' )
( ' ENDCLASS.' )

( ' CLASS lcl_test IMPLEMENTATION. ' )
( ' METHOD scenario. ' )
( ' DATA entries TYPE tadir. ' )
( ' given_fake_value( ). ' )
( ' SELECT SINGLE * FROM tadir INTO entries. ' )
( ' ENDMETHOD. ' )
( ' ENDCLASS. ' )
).
ENDMETHOD.

ENDCLASS.



CLASS ltc_risk_harmless DEFINITION INHERITING FROM y_unit_test_base FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_cut REDEFINITION.
Expand Down Expand Up @@ -205,6 +273,8 @@ CLASS ltc_risk_harmless IMPLEMENTATION.

ENDCLASS.



CLASS ltc_risk_critical DEFINITION INHERITING FROM y_unit_test_base FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_cut REDEFINITION.
Expand Down Expand Up @@ -292,6 +362,8 @@ CLASS ltc_risk_critical IMPLEMENTATION.

ENDCLASS.



CLASS ltc_risk_dangerous DEFINITION INHERITING FROM ltc_risk_critical FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_cut REDEFINITION.
Expand Down Expand Up @@ -333,6 +405,8 @@ CLASS ltc_risk_dangerous IMPLEMENTATION.

ENDCLASS.



CLASS ltc_risk_not_set DEFINITION INHERITING FROM ltc_risk_harmless FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_code_with_issue REDEFINITION.
Expand Down Expand Up @@ -370,6 +444,7 @@ CLASS ltc_risk_not_set IMPLEMENTATION.
ENDCLASS.



CLASS ltc_exec_sql DEFINITION INHERITING FROM y_unit_test_base FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_cut REDEFINITION.
Expand Down Expand Up @@ -440,6 +515,7 @@ CLASS ltc_exec_sql IMPLEMENTATION.
ENDCLASS.



CLASS ltc_itab DEFINITION INHERITING FROM ltc_risk_harmless FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.
PROTECTED SECTION.
METHODS get_code_without_issue REDEFINITION.
Expand Down