Fix coverage with several contract classes; table annotation and file path checks; clean task dir on write

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014aUaQeLnwbb1zTpN7kHeat
This commit is contained in:
Kral
2026-10-03 08:44:35 +02:00
parent fb576b0954
commit 03ab36149e
388 changed files with 28620 additions and 339 deletions

View File

@@ -0,0 +1,107 @@
CLASS {{p}}tool_crib DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_tool_id TYPE c LENGTH 10.
TYPES ty_employee TYPE c LENGTH 20.
TYPES:
BEGIN OF ty_loan,
tool_id TYPE ty_tool_id,
employee TYPE ty_employee,
due_date TYPE d,
END OF ty_loan.
TYPES tt_loans TYPE SORTED TABLE OF ty_loan
WITH NON-UNIQUE KEY due_date tool_id.
METHODS lend
IMPORTING iv_tool_id TYPE ty_tool_id
iv_employee TYPE ty_employee
iv_due_date TYPE d
RETURNING VALUE(rv_accepted) TYPE abap_bool.
METHODS return_tool
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_found) TYPE abap_bool.
METHODS is_on_loan
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_on_loan) TYPE abap_bool.
METHODS open_loans
RETURNING VALUE(rt_loans) TYPE tt_loans.
METHODS overdue_loans
IMPORTING iv_today TYPE d
RETURNING VALUE(rt_loans) TYPE tt_loans.
PRIVATE SECTION.
TYPES tt_loan_store TYPE SORTED TABLE OF ty_loan WITH UNIQUE KEY tool_id.
DATA mt_loans TYPE tt_loan_store.
METHODS normalize_tool_id
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_tool_id) TYPE ty_tool_id.
METHODS normalize_employee
IMPORTING iv_employee TYPE ty_employee
RETURNING VALUE(rv_employee) TYPE ty_employee.
ENDCLASS.
CLASS {{p}}tool_crib IMPLEMENTATION.
METHOD lend.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
DATA(lv_employee) = normalize_employee( iv_employee ).
IF lv_tool_id IS INITIAL AND lv_employee IS INITIAL OR iv_due_date IS INITIAL.
RETURN.
ENDIF.
IF {{p}}tool_master=>is_valid_tool( lv_tool_id ) = abap_false.
RETURN.
ENDIF.
IF is_on_loan( lv_tool_id ) = abap_true.
RETURN.
ENDIF.
DATA(ls_loan) = VALUE ty_loan( tool_id = lv_tool_id
employee = lv_employee
due_date = iv_due_date ).
INSERT ls_loan INTO TABLE mt_loans.
rv_accepted = abap_true.
ENDMETHOD.
METHOD return_tool.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
DELETE TABLE mt_loans WITH TABLE KEY tool_id = lv_tool_id.
rv_found = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
METHOD is_on_loan.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
rv_on_loan = xsdbool( line_exists( mt_loans[ tool_id = lv_tool_id ] ) ).
ENDMETHOD.
METHOD open_loans.
LOOP AT mt_loans INTO DATA(ls_loan).
INSERT ls_loan INTO TABLE rt_loans.
ENDLOOP.
ENDMETHOD.
METHOD overdue_loans.
IF iv_today IS INITIAL.
RETURN.
ENDIF.
LOOP AT mt_loans INTO DATA(ls_loan).
IF ls_loan-due_date < iv_today.
INSERT ls_loan INTO TABLE rt_loans.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD normalize_tool_id.
rv_tool_id = to_upper( replace( val = iv_tool_id sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
METHOD normalize_employee.
rv_employee = to_upper( replace( val = iv_employee sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,107 @@
CLASS {{p}}tool_crib DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_tool_id TYPE c LENGTH 10.
TYPES ty_employee TYPE c LENGTH 20.
TYPES:
BEGIN OF ty_loan,
tool_id TYPE ty_tool_id,
employee TYPE ty_employee,
due_date TYPE d,
END OF ty_loan.
TYPES tt_loans TYPE SORTED TABLE OF ty_loan
WITH NON-UNIQUE KEY due_date tool_id.
METHODS lend
IMPORTING iv_tool_id TYPE ty_tool_id
iv_employee TYPE ty_employee
iv_due_date TYPE d
RETURNING VALUE(rv_accepted) TYPE abap_bool.
METHODS return_tool
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_found) TYPE abap_bool.
METHODS is_on_loan
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_on_loan) TYPE abap_bool.
METHODS open_loans
RETURNING VALUE(rt_loans) TYPE tt_loans.
METHODS overdue_loans
IMPORTING iv_today TYPE d
RETURNING VALUE(rt_loans) TYPE tt_loans.
PRIVATE SECTION.
TYPES tt_loan_store TYPE SORTED TABLE OF ty_loan WITH UNIQUE KEY tool_id.
DATA mt_loans TYPE tt_loan_store.
METHODS normalize_tool_id
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_tool_id) TYPE ty_tool_id.
METHODS normalize_employee
IMPORTING iv_employee TYPE ty_employee
RETURNING VALUE(rv_employee) TYPE ty_employee.
ENDCLASS.
CLASS {{p}}tool_crib IMPLEMENTATION.
METHOD lend.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
DATA(lv_employee) = normalize_employee( iv_employee ).
IF lv_tool_id IS INITIAL OR lv_employee IS INITIAL OR iv_due_date IS INITIAL.
RETURN.
ENDIF.
IF {{p}}tool_master=>is_valid_tool( lv_tool_id ) <> abap_false.
RETURN.
ENDIF.
IF is_on_loan( lv_tool_id ) = abap_true.
RETURN.
ENDIF.
DATA(ls_loan) = VALUE ty_loan( tool_id = lv_tool_id
employee = lv_employee
due_date = iv_due_date ).
INSERT ls_loan INTO TABLE mt_loans.
rv_accepted = abap_true.
ENDMETHOD.
METHOD return_tool.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
DELETE TABLE mt_loans WITH TABLE KEY tool_id = lv_tool_id.
rv_found = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
METHOD is_on_loan.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
rv_on_loan = xsdbool( line_exists( mt_loans[ tool_id = lv_tool_id ] ) ).
ENDMETHOD.
METHOD open_loans.
LOOP AT mt_loans INTO DATA(ls_loan).
INSERT ls_loan INTO TABLE rt_loans.
ENDLOOP.
ENDMETHOD.
METHOD overdue_loans.
IF iv_today IS INITIAL.
RETURN.
ENDIF.
LOOP AT mt_loans INTO DATA(ls_loan).
IF ls_loan-due_date < iv_today.
INSERT ls_loan INTO TABLE rt_loans.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD normalize_tool_id.
rv_tool_id = to_upper( replace( val = iv_tool_id sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
METHOD normalize_employee.
rv_employee = to_upper( replace( val = iv_employee sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,107 @@
CLASS {{p}}tool_crib DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_tool_id TYPE c LENGTH 10.
TYPES ty_employee TYPE c LENGTH 20.
TYPES:
BEGIN OF ty_loan,
tool_id TYPE ty_tool_id,
employee TYPE ty_employee,
due_date TYPE d,
END OF ty_loan.
TYPES tt_loans TYPE SORTED TABLE OF ty_loan
WITH NON-UNIQUE KEY due_date tool_id.
METHODS lend
IMPORTING iv_tool_id TYPE ty_tool_id
iv_employee TYPE ty_employee
iv_due_date TYPE d
RETURNING VALUE(rv_accepted) TYPE abap_bool.
METHODS return_tool
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_found) TYPE abap_bool.
METHODS is_on_loan
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_on_loan) TYPE abap_bool.
METHODS open_loans
RETURNING VALUE(rt_loans) TYPE tt_loans.
METHODS overdue_loans
IMPORTING iv_today TYPE d
RETURNING VALUE(rt_loans) TYPE tt_loans.
PRIVATE SECTION.
TYPES tt_loan_store TYPE SORTED TABLE OF ty_loan WITH UNIQUE KEY tool_id.
DATA mt_loans TYPE tt_loan_store.
METHODS normalize_tool_id
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_tool_id) TYPE ty_tool_id.
METHODS normalize_employee
IMPORTING iv_employee TYPE ty_employee
RETURNING VALUE(rv_employee) TYPE ty_employee.
ENDCLASS.
CLASS {{p}}tool_crib IMPLEMENTATION.
METHOD lend.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
DATA(lv_employee) = normalize_employee( iv_employee ).
IF lv_tool_id IS INITIAL OR lv_employee IS INITIAL OR iv_due_date IS INITIAL.
RETURN.
ENDIF.
IF {{p}}tool_master=>is_valid_tool( lv_tool_id ) = abap_false.
RETURN.
ENDIF.
IF is_on_loan( lv_tool_id ) = abap_false.
RETURN.
ENDIF.
DATA(ls_loan) = VALUE ty_loan( tool_id = lv_tool_id
employee = lv_employee
due_date = iv_due_date ).
INSERT ls_loan INTO TABLE mt_loans.
rv_accepted = abap_true.
ENDMETHOD.
METHOD return_tool.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
DELETE TABLE mt_loans WITH TABLE KEY tool_id = lv_tool_id.
rv_found = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
METHOD is_on_loan.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
rv_on_loan = xsdbool( line_exists( mt_loans[ tool_id = lv_tool_id ] ) ).
ENDMETHOD.
METHOD open_loans.
LOOP AT mt_loans INTO DATA(ls_loan).
INSERT ls_loan INTO TABLE rt_loans.
ENDLOOP.
ENDMETHOD.
METHOD overdue_loans.
IF iv_today IS INITIAL.
RETURN.
ENDIF.
LOOP AT mt_loans INTO DATA(ls_loan).
IF ls_loan-due_date < iv_today.
INSERT ls_loan INTO TABLE rt_loans.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD normalize_tool_id.
rv_tool_id = to_upper( replace( val = iv_tool_id sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
METHOD normalize_employee.
rv_employee = to_upper( replace( val = iv_employee sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,107 @@
CLASS {{p}}tool_crib DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_tool_id TYPE c LENGTH 10.
TYPES ty_employee TYPE c LENGTH 20.
TYPES:
BEGIN OF ty_loan,
tool_id TYPE ty_tool_id,
employee TYPE ty_employee,
due_date TYPE d,
END OF ty_loan.
TYPES tt_loans TYPE SORTED TABLE OF ty_loan
WITH NON-UNIQUE KEY due_date tool_id.
METHODS lend
IMPORTING iv_tool_id TYPE ty_tool_id
iv_employee TYPE ty_employee
iv_due_date TYPE d
RETURNING VALUE(rv_accepted) TYPE abap_bool.
METHODS return_tool
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_found) TYPE abap_bool.
METHODS is_on_loan
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_on_loan) TYPE abap_bool.
METHODS open_loans
RETURNING VALUE(rt_loans) TYPE tt_loans.
METHODS overdue_loans
IMPORTING iv_today TYPE d
RETURNING VALUE(rt_loans) TYPE tt_loans.
PRIVATE SECTION.
TYPES tt_loan_store TYPE SORTED TABLE OF ty_loan WITH UNIQUE KEY tool_id.
DATA mt_loans TYPE tt_loan_store.
METHODS normalize_tool_id
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_tool_id) TYPE ty_tool_id.
METHODS normalize_employee
IMPORTING iv_employee TYPE ty_employee
RETURNING VALUE(rv_employee) TYPE ty_employee.
ENDCLASS.
CLASS {{p}}tool_crib IMPLEMENTATION.
METHOD lend.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
DATA(lv_employee) = normalize_employee( iv_employee ).
IF lv_tool_id IS INITIAL OR lv_employee IS INITIAL OR iv_due_date IS INITIAL.
RETURN.
ENDIF.
IF {{p}}tool_master=>is_valid_tool( lv_tool_id ) = abap_false.
RETURN.
ENDIF.
IF is_on_loan( lv_tool_id ) = abap_true.
RETURN.
ENDIF.
DATA(ls_loan) = VALUE ty_loan( tool_id = lv_tool_id
employee = lv_employee
due_date = iv_due_date ).
INSERT ls_loan INTO TABLE mt_loans.
rv_accepted = abap_false.
ENDMETHOD.
METHOD return_tool.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
DELETE TABLE mt_loans WITH TABLE KEY tool_id = lv_tool_id.
rv_found = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
METHOD is_on_loan.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
rv_on_loan = xsdbool( line_exists( mt_loans[ tool_id = lv_tool_id ] ) ).
ENDMETHOD.
METHOD open_loans.
LOOP AT mt_loans INTO DATA(ls_loan).
INSERT ls_loan INTO TABLE rt_loans.
ENDLOOP.
ENDMETHOD.
METHOD overdue_loans.
IF iv_today IS INITIAL.
RETURN.
ENDIF.
LOOP AT mt_loans INTO DATA(ls_loan).
IF ls_loan-due_date < iv_today.
INSERT ls_loan INTO TABLE rt_loans.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD normalize_tool_id.
rv_tool_id = to_upper( replace( val = iv_tool_id sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
METHOD normalize_employee.
rv_employee = to_upper( replace( val = iv_employee sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,107 @@
CLASS {{p}}tool_crib DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_tool_id TYPE c LENGTH 10.
TYPES ty_employee TYPE c LENGTH 20.
TYPES:
BEGIN OF ty_loan,
tool_id TYPE ty_tool_id,
employee TYPE ty_employee,
due_date TYPE d,
END OF ty_loan.
TYPES tt_loans TYPE SORTED TABLE OF ty_loan
WITH NON-UNIQUE KEY due_date tool_id.
METHODS lend
IMPORTING iv_tool_id TYPE ty_tool_id
iv_employee TYPE ty_employee
iv_due_date TYPE d
RETURNING VALUE(rv_accepted) TYPE abap_bool.
METHODS return_tool
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_found) TYPE abap_bool.
METHODS is_on_loan
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_on_loan) TYPE abap_bool.
METHODS open_loans
RETURNING VALUE(rt_loans) TYPE tt_loans.
METHODS overdue_loans
IMPORTING iv_today TYPE d
RETURNING VALUE(rt_loans) TYPE tt_loans.
PRIVATE SECTION.
TYPES tt_loan_store TYPE SORTED TABLE OF ty_loan WITH UNIQUE KEY tool_id.
DATA mt_loans TYPE tt_loan_store.
METHODS normalize_tool_id
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_tool_id) TYPE ty_tool_id.
METHODS normalize_employee
IMPORTING iv_employee TYPE ty_employee
RETURNING VALUE(rv_employee) TYPE ty_employee.
ENDCLASS.
CLASS {{p}}tool_crib IMPLEMENTATION.
METHOD lend.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
DATA(lv_employee) = normalize_employee( iv_employee ).
IF lv_tool_id IS INITIAL OR lv_employee IS INITIAL OR iv_due_date IS INITIAL.
RETURN.
ENDIF.
IF {{p}}tool_master=>is_valid_tool( lv_tool_id ) = abap_false.
RETURN.
ENDIF.
IF is_on_loan( lv_tool_id ) = abap_true.
RETURN.
ENDIF.
DATA(ls_loan) = VALUE ty_loan( tool_id = lv_tool_id
employee = lv_employee
due_date = iv_due_date ).
INSERT ls_loan INTO TABLE mt_loans.
rv_accepted = abap_true.
ENDMETHOD.
METHOD return_tool.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
DELETE TABLE mt_loans WITH TABLE KEY tool_id = lv_tool_id.
rv_found = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
METHOD is_on_loan.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
rv_on_loan = xsdbool( line_exists( mt_loans[ tool_id = lv_tool_id ] ) ).
ENDMETHOD.
METHOD open_loans.
LOOP AT mt_loans INTO DATA(ls_loan).
INSERT ls_loan INTO TABLE rt_loans.
ENDLOOP.
ENDMETHOD.
METHOD overdue_loans.
IF iv_today IS INITIAL.
RETURN.
ENDIF.
LOOP AT mt_loans INTO DATA(ls_loan).
IF ls_loan-due_date >= iv_today.
INSERT ls_loan INTO TABLE rt_loans.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD normalize_tool_id.
rv_tool_id = to_upper( replace( val = iv_tool_id sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
METHOD normalize_employee.
rv_employee = to_upper( replace( val = iv_employee sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,29 @@
{
"id": "G0117",
"pool": "eval",
"object_type": "CLAS",
"category": "C",
"attempts": [
{
"stage": "validate",
"oracle": 0,
"null": 0
},
{
"stage": "validate",
"oracle": 95.0,
"null": 0
},
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 5,
"killed": 5,
"ok": true
}
}
],
"accepted": true
}

View File

@@ -0,0 +1,157 @@
CLASS {{p}}t11_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
TYPES tt_tool_ids TYPE STANDARD TABLE OF {{p}}tool_crib=>ty_tool_id WITH EMPTY KEY.
CONSTANTS c_drill TYPE {{p}}tool_crib=>ty_tool_id VALUE 'DRILL'.
CONSTANTS c_saw TYPE {{p}}tool_crib=>ty_tool_id VALUE 'SAW'.
CONSTANTS c_grinder TYPE {{p}}tool_crib=>ty_tool_id VALUE 'GRINDER'.
CONSTANTS c_wrench TYPE {{p}}tool_crib=>ty_tool_id VALUE 'WRENCH'.
CONSTANTS c_smith TYPE {{p}}tool_crib=>ty_employee VALUE 'SMITH'.
DATA mo_cut TYPE REF TO {{p}}tool_crib.
METHODS setup.
METHODS tool_ids
IMPORTING it_loans TYPE {{p}}tool_crib=>tt_loans
RETURNING VALUE(rt_ids) TYPE tt_tool_ids.
METHODS first_loan
IMPORTING it_loans TYPE {{p}}tool_crib=>tt_loans
RETURNING VALUE(rs_loan) TYPE {{p}}tool_crib=>ty_loan.
METHODS lend_new_tool_ok FOR TESTING.
METHODS lend_twice_rejected FOR TESTING.
METHODS return_tool_ok FOR TESTING.
METHODS open_loans_due_date_order FOR TESTING.
METHODS open_loans_tool_id_order FOR TESTING.
METHODS overdue_only_before_today FOR TESTING.
METHODS overdue_initial_today_empty FOR TESTING.
METHODS empty_tool_id_rejected FOR TESTING.
METHODS invalid_loan_rejected FOR TESTING.
METHODS unknown_tool_rejected FOR TESTING.
METHODS lower_case_and_spaces FOR TESTING.
ENDCLASS.
CLASS {{p}}t11_hidden IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}tool_crib( ).
ENDMETHOD.
METHOD tool_ids.
LOOP AT it_loans INTO DATA(ls_loan).
INSERT ls_loan-tool_id INTO TABLE rt_ids.
ENDLOOP.
ENDMETHOD.
METHOD first_loan.
LOOP AT it_loans INTO rs_loan.
EXIT.
ENDLOOP.
ENDMETHOD.
METHOD lend_new_tool_ok.
cl_abap_unit_assert=>assert_true( act = mo_cut->lend( iv_tool_id = c_drill
iv_employee = c_smith
iv_due_date = '20250110' ) ).
cl_abap_unit_assert=>assert_true( act = mo_cut->is_on_loan( c_drill ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->is_on_loan( c_saw ) ).
ENDMETHOD.
METHOD lend_twice_rejected.
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250110' ).
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = c_drill
iv_employee = 'JONES'
iv_due_date = '20250210' ) ).
DATA(lt_loans) = mo_cut->open_loans( ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_loans ) ).
DATA(ls_loan) = first_loan( lt_loans ).
cl_abap_unit_assert=>assert_equals( exp = c_smith act = ls_loan-employee ).
ENDMETHOD.
METHOD return_tool_ok.
cl_abap_unit_assert=>assert_false( act = mo_cut->return_tool( c_saw ) ).
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250110' ).
cl_abap_unit_assert=>assert_true( act = mo_cut->return_tool( c_drill ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->is_on_loan( c_drill ) ).
DATA(lt_loans) = mo_cut->open_loans( ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_loans ) ).
ENDMETHOD.
METHOD open_loans_due_date_order.
mo_cut->lend( iv_tool_id = c_saw iv_employee = c_smith iv_due_date = '20250310' ).
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250110' ).
mo_cut->lend( iv_tool_id = c_grinder iv_employee = c_smith iv_due_date = '20250210' ).
DATA(lt_loans) = mo_cut->open_loans( ).
DATA(lt_ids) = tool_ids( lt_loans ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lines( lt_ids ) ).
cl_abap_unit_assert=>assert_equals( exp = c_drill act = lt_ids[ 1 ] ).
cl_abap_unit_assert=>assert_equals( exp = c_grinder act = lt_ids[ 2 ] ).
cl_abap_unit_assert=>assert_equals( exp = c_saw act = lt_ids[ 3 ] ).
ENDMETHOD.
METHOD open_loans_tool_id_order.
mo_cut->lend( iv_tool_id = c_wrench iv_employee = c_smith iv_due_date = '20250110' ).
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250110' ).
DATA(lt_loans) = mo_cut->open_loans( ).
DATA(lt_ids) = tool_ids( lt_loans ).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lines( lt_ids ) ).
cl_abap_unit_assert=>assert_equals( exp = c_drill act = lt_ids[ 1 ] ).
cl_abap_unit_assert=>assert_equals( exp = c_wrench act = lt_ids[ 2 ] ).
ENDMETHOD.
METHOD overdue_only_before_today.
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250109' ).
mo_cut->lend( iv_tool_id = c_saw iv_employee = c_smith iv_due_date = '20250110' ).
mo_cut->lend( iv_tool_id = c_grinder iv_employee = c_smith iv_due_date = '20250111' ).
DATA(lt_loans) = mo_cut->overdue_loans( '20250110' ).
DATA(lt_ids) = tool_ids( lt_loans ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_ids ) ).
cl_abap_unit_assert=>assert_equals( exp = c_drill act = lt_ids[ 1 ] ).
ENDMETHOD.
METHOD overdue_initial_today_empty.
DATA lv_today TYPE d.
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250109' ).
DATA(lt_loans) = mo_cut->overdue_loans( lv_today ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_loans ) ).
ENDMETHOD.
METHOD empty_tool_id_rejected.
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = ' '
iv_employee = c_smith
iv_due_date = '20250110' ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->is_on_loan( ' ' ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->return_tool( ' ' ) ).
DATA(lt_loans) = mo_cut->open_loans( ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lines( lt_loans ) ).
ENDMETHOD.
METHOD invalid_loan_rejected.
DATA lv_initial_date TYPE d.
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = c_drill
iv_employee = ' '
iv_due_date = '20250110' ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = c_drill
iv_employee = c_smith
iv_due_date = lv_initial_date ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->is_on_loan( c_drill ) ).
ENDMETHOD.
METHOD unknown_tool_rejected.
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = 'HAMMER'
iv_employee = c_smith
iv_due_date = '20250110' ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->is_on_loan( 'HAMMER' ) ).
ENDMETHOD.
METHOD lower_case_and_spaces.
cl_abap_unit_assert=>assert_true( act = mo_cut->lend( iv_tool_id = 'd r i l l'
iv_employee = 'smith'
iv_due_date = '20250110' ) ).
cl_abap_unit_assert=>assert_true( act = mo_cut->is_on_loan( c_drill ) ).
DATA(lt_loans) = mo_cut->open_loans( ).
DATA(ls_loan) = first_loan( lt_loans ).
cl_abap_unit_assert=>assert_equals( exp = c_drill act = ls_loan-tool_id ).
cl_abap_unit_assert=>assert_equals( exp = c_smith act = ls_loan-employee ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,68 @@
{
"task": "G0117",
"mutants": [
{
"object": "{{P}}TOOL_CRIB",
"mutant": "line 49: OR -> AND (logic)",
"status": "killed",
"hidden": "10/11",
"failed_tests": [
"INVALID_LOAN_REJECTED"
]
},
{
"object": "{{P}}TOOL_CRIB",
"mutant": "line 52: = -> <> (eq)",
"status": "killed",
"hidden": "3/11",
"failed_tests": [
"LEND_NEW_TOOL_OK",
"LEND_TWICE_REJECTED",
"LOWER_CASE_AND_SPACES",
"OPEN_LOANS_DUE_DATE_ORDER",
"OPEN_LOANS_TOOL_ID_ORDER",
"OVERDUE_ONLY_BEFORE_TODAY",
"RETURN_TOOL_OK",
"UNKNOWN_TOOL_REJECTED"
]
},
{
"object": "{{P}}TOOL_CRIB",
"mutant": "line 55: abap_true -> abap_false (bool)",
"status": "killed",
"hidden": "4/11",
"failed_tests": [
"LEND_NEW_TOOL_OK",
"LEND_TWICE_REJECTED",
"LOWER_CASE_AND_SPACES",
"OPEN_LOANS_DUE_DATE_ORDER",
"OPEN_LOANS_TOOL_ID_ORDER",
"OVERDUE_ONLY_BEFORE_TODAY",
"RETURN_TOOL_OK"
]
},
{
"object": "{{P}}TOOL_CRIB",
"mutant": "line 63: abap_true -> abap_false (bool)",
"status": "killed",
"hidden": "9/11",
"failed_tests": [
"LEND_NEW_TOOL_OK",
"LOWER_CASE_AND_SPACES"
]
},
{
"object": "{{P}}TOOL_CRIB",
"mutant": "line 94: < -> >= (rel)",
"status": "killed",
"hidden": "10/11",
"failed_tests": [
"OVERDUE_ONLY_BEFORE_TODAY"
]
}
],
"valid": 5,
"killed": 5,
"kill_rate": 1.0,
"ok": true
}

View File

@@ -0,0 +1,107 @@
CLASS {{p}}tool_crib DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_tool_id TYPE c LENGTH 10.
TYPES ty_employee TYPE c LENGTH 20.
TYPES:
BEGIN OF ty_loan,
tool_id TYPE ty_tool_id,
employee TYPE ty_employee,
due_date TYPE d,
END OF ty_loan.
TYPES tt_loans TYPE SORTED TABLE OF ty_loan
WITH NON-UNIQUE KEY due_date tool_id.
METHODS lend
IMPORTING iv_tool_id TYPE ty_tool_id
iv_employee TYPE ty_employee
iv_due_date TYPE d
RETURNING VALUE(rv_accepted) TYPE abap_bool.
METHODS return_tool
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_found) TYPE abap_bool.
METHODS is_on_loan
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_on_loan) TYPE abap_bool.
METHODS open_loans
RETURNING VALUE(rt_loans) TYPE tt_loans.
METHODS overdue_loans
IMPORTING iv_today TYPE d
RETURNING VALUE(rt_loans) TYPE tt_loans.
PRIVATE SECTION.
TYPES tt_loan_store TYPE SORTED TABLE OF ty_loan WITH UNIQUE KEY tool_id.
DATA mt_loans TYPE tt_loan_store.
METHODS normalize_tool_id
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_tool_id) TYPE ty_tool_id.
METHODS normalize_employee
IMPORTING iv_employee TYPE ty_employee
RETURNING VALUE(rv_employee) TYPE ty_employee.
ENDCLASS.
CLASS {{p}}tool_crib IMPLEMENTATION.
METHOD lend.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
DATA(lv_employee) = normalize_employee( iv_employee ).
IF lv_tool_id IS INITIAL OR lv_employee IS INITIAL OR iv_due_date IS INITIAL.
RETURN.
ENDIF.
IF {{p}}tool_master=>is_valid_tool( lv_tool_id ) = abap_false.
RETURN.
ENDIF.
IF is_on_loan( lv_tool_id ) = abap_true.
RETURN.
ENDIF.
DATA(ls_loan) = VALUE ty_loan( tool_id = lv_tool_id
employee = lv_employee
due_date = iv_due_date ).
INSERT ls_loan INTO TABLE mt_loans.
rv_accepted = abap_true.
ENDMETHOD.
METHOD return_tool.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
DELETE TABLE mt_loans WITH TABLE KEY tool_id = lv_tool_id.
rv_found = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
METHOD is_on_loan.
DATA(lv_tool_id) = normalize_tool_id( iv_tool_id ).
IF lv_tool_id IS INITIAL.
RETURN.
ENDIF.
rv_on_loan = xsdbool( line_exists( mt_loans[ tool_id = lv_tool_id ] ) ).
ENDMETHOD.
METHOD open_loans.
LOOP AT mt_loans INTO DATA(ls_loan).
INSERT ls_loan INTO TABLE rt_loans.
ENDLOOP.
ENDMETHOD.
METHOD overdue_loans.
IF iv_today IS INITIAL.
RETURN.
ENDIF.
LOOP AT mt_loans INTO DATA(ls_loan).
IF ls_loan-due_date < iv_today.
INSERT ls_loan INTO TABLE rt_loans.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD normalize_tool_id.
rv_tool_id = to_upper( replace( val = iv_tool_id sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
METHOD normalize_employee.
rv_employee = to_upper( replace( val = iv_employee sub = ` ` with = `` occ = 0 ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,90 @@
CLASS ltc_tool_crib DEFINITION FINAL FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
TYPES tt_tool_ids TYPE STANDARD TABLE OF {{p}}tool_crib=>ty_tool_id WITH EMPTY KEY.
CONSTANTS c_drill TYPE {{p}}tool_crib=>ty_tool_id VALUE 'DRILL'.
CONSTANTS c_saw TYPE {{p}}tool_crib=>ty_tool_id VALUE 'SAW'.
CONSTANTS c_smith TYPE {{p}}tool_crib=>ty_employee VALUE 'SMITH'.
DATA mo_cut TYPE REF TO {{p}}tool_crib.
METHODS setup.
METHODS lend_records_loan FOR TESTING.
METHODS lend_twice_rejected FOR TESTING.
METHODS lend_unknown_tool FOR TESTING.
METHODS return_removes_loan FOR TESTING.
METHODS open_loans_are_sorted FOR TESTING.
METHODS overdue_loans_are_filtered FOR TESTING.
METHODS empty_input_rejected FOR TESTING.
METHODS input_is_normalized FOR TESTING.
ENDCLASS.
CLASS ltc_tool_crib IMPLEMENTATION.
METHOD setup.
mo_cut = NEW {{p}}tool_crib( ).
ENDMETHOD.
METHOD lend_records_loan.
cl_abap_unit_assert=>assert_true( act = mo_cut->lend( iv_tool_id = c_drill
iv_employee = c_smith
iv_due_date = '20250110' ) ).
cl_abap_unit_assert=>assert_true( act = mo_cut->is_on_loan( c_drill ) ).
ENDMETHOD.
METHOD lend_twice_rejected.
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250110' ).
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = c_drill
iv_employee = c_smith
iv_due_date = '20250111' ) ).
ENDMETHOD.
METHOD lend_unknown_tool.
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = 'HAMMER'
iv_employee = c_smith
iv_due_date = '20250110' ) ).
ENDMETHOD.
METHOD return_removes_loan.
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250110' ).
cl_abap_unit_assert=>assert_true( act = mo_cut->return_tool( c_drill ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->is_on_loan( c_drill ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->return_tool( c_drill ) ).
ENDMETHOD.
METHOD open_loans_are_sorted.
mo_cut->lend( iv_tool_id = c_saw iv_employee = c_smith iv_due_date = '20250310' ).
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250110' ).
DATA(lt_loans) = mo_cut->open_loans( ).
DATA(lt_ids) = VALUE tt_tool_ids( ).
LOOP AT lt_loans INTO DATA(ls_loan).
INSERT ls_loan-tool_id INTO TABLE lt_ids.
ENDLOOP.
cl_abap_unit_assert=>assert_equals( exp = c_drill act = lt_ids[ 1 ] ).
cl_abap_unit_assert=>assert_equals( exp = c_saw act = lt_ids[ 2 ] ).
ENDMETHOD.
METHOD overdue_loans_are_filtered.
mo_cut->lend( iv_tool_id = c_drill iv_employee = c_smith iv_due_date = '20250109' ).
mo_cut->lend( iv_tool_id = c_saw iv_employee = c_smith iv_due_date = '20250110' ).
DATA(lt_loans) = mo_cut->overdue_loans( '20250110' ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_loans ) ).
ENDMETHOD.
METHOD empty_input_rejected.
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = ' '
iv_employee = c_smith
iv_due_date = '20250110' ) ).
cl_abap_unit_assert=>assert_false( act = mo_cut->lend( iv_tool_id = c_drill
iv_employee = ' '
iv_due_date = '20250110' ) ).
ENDMETHOD.
METHOD input_is_normalized.
cl_abap_unit_assert=>assert_true( act = mo_cut->lend( iv_tool_id = 'drill'
iv_employee = 'smith'
iv_due_date = '20250110' ) ).
cl_abap_unit_assert=>assert_true( act = mo_cut->is_on_loan( c_drill ) ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,20 @@
CLASS {{p}}tool_master DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_tool_id TYPE c LENGTH 10.
CLASS-METHODS is_valid_tool
IMPORTING iv_tool_id TYPE ty_tool_id
RETURNING VALUE(rv_valid) TYPE abap_bool.
ENDCLASS.
CLASS {{p}}tool_master IMPLEMENTATION.
METHOD is_valid_tool.
DATA(lv_tool_id) = to_upper( replace( val = iv_tool_id sub = ` ` with = `` occ = 0 ) ).
CASE lv_tool_id.
WHEN 'DRILL' OR 'SAW' OR 'GRINDER' OR 'WRENCH' OR 'SANDER' OR 'RIVETER'.
rv_valid = abap_true.
WHEN OTHERS.
rv_valid = abap_false.
ENDCASE.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,93 @@
# 1. Goal
A tool crib lends workshop tools to employees. A shop-floor terminal calls one
class to record the loans and the returns and to show the open loans. The class
keeps the loans in memory.
# 2. Open questions
None.
# 3. Context
- All objects are in package $TMP. No transport is necessary.
- The class {{P}}TOOL_MASTER exists in package $TMP. It is active. It has the
public type TY_TOOL_ID (character-like, length 10) and the static method
IS_VALID_TOOL. IS_VALID_TOOL has the importing parameter IV_TOOL_ID
(TY_TOOL_ID) and the returning parameter RV_VALID (abap_bool). The method
ignores spaces and letter case. It returns abap_true only for the tools that
the crib has in stock.
- The terminal creates one instance of the new class for each shift. There is
no database table. All loans live in the instance.
# 4. Contract
Create the class {{P}}TOOL_CRIB in package $TMP.
The class is public and final. An instance is created without parameters.
Public types:
- TY_TOOL_ID: character-like, length 10.
- TY_EMPLOYEE: character-like, length 20.
- TY_LOAN: structure with the components TOOL_ID (TY_TOOL_ID), EMPLOYEE
(TY_EMPLOYEE) and DUE_DATE (type D).
- TT_LOANS: table type with the row type TY_LOAN.
Public methods:
- LEND, importing IV_TOOL_ID (TY_TOOL_ID), IV_EMPLOYEE (TY_EMPLOYEE) and
IV_DUE_DATE (D), returning RV_ACCEPTED (abap_bool).
- RETURN_TOOL, importing IV_TOOL_ID (TY_TOOL_ID), returning RV_FOUND
(abap_bool).
- IS_ON_LOAN, importing IV_TOOL_ID (TY_TOOL_ID), returning RV_ON_LOAN
(abap_bool).
- OPEN_LOANS, returning RT_LOANS (TT_LOANS).
- OVERDUE_LOANS, importing IV_TODAY (D), returning RT_LOANS (TT_LOANS).
Do not add other public components.
# 5. Business rules
Normalization:
1. The normalized tool ID is the tool ID without spaces and in upper case.
2. The normalized employee is the employee without spaces and in upper case.
LEND applies these steps in this sequence. It stops at the first step that
rejects the loan.
3. If the normalized tool ID is empty, reject.
4. If the normalized employee is empty, reject.
5. If the due date is initial, reject.
6. If {{P}}TOOL_MASTER=>IS_VALID_TOOL returns abap_false for the normalized tool
ID, reject.
7. If the normalized tool ID is already on loan, reject.
8. Else record the loan with the normalized tool ID, the normalized employee
and the due date. Accept the loan.
Reject means: return abap_false and do not change the loans.
9. RETURN_TOOL: if the normalized tool ID is on loan, delete the loan and
return abap_true. Else return abap_false. An empty normalized tool ID
returns abap_false.
10. IS_ON_LOAN: return abap_true if the normalized tool ID is on loan. Else
return abap_false. An empty normalized tool ID returns abap_false.
11. OPEN_LOANS returns one row for each open loan. The rows are ordered by
DUE_DATE in ascending order. Rows with the same DUE_DATE are ordered by
TOOL_ID in ascending order.
12. OVERDUE_LOANS returns the open loans with a DUE_DATE before IV_TODAY. If
IV_TODAY is initial, the result is empty. The rows have the same order as
in OPEN_LOANS.
13. A due date in the past is permitted at LEND. Such a loan appears in
OVERDUE_LOANS.
14. A new instance has no loans.
# 6. Constraints
- Release target: SAP_BASIS 8.16.
- Coding standards: Clean ABAP. Methods below 40 statements. No global
variables. No comment that restates the code.
- Out of scope: do not change {{P}}TOOL_MASTER.
# 7. Acceptance
- The class is active and has no syntax error.
- The hidden tests pass.
- Write your own ABAP Unit tests for the class.

View File

@@ -0,0 +1,51 @@
{
"id": "G0117",
"category": "C",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [
{
"type": "CLAS",
"name": "{{P}}TOOL_MASTER",
"file": "seed/tool_master.clas.abap",
"description": "Tool master with the tool IDs that the crib has in stock"
}
],
"contract": [
{
"type": "CLAS",
"name": "{{P}}TOOL_CRIB"
}
],
"out_of_scope": [
"{{P}}TOOL_MASTER"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T11_HIDDEN",
"file": "hidden/t11_hidden.clas.abap",
"description": "Hidden tests for the tool crib loan book"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}TOOL_CRIB",
"file": "reference/tool_crib.clas.abap",
"description": "Tool crib loan book",
"testclasses_file": "reference/tool_crib.testclasses.abap"
}
],
"craft_checks": [
"method_length",
"internal_table_key",
"table_access_path"
]
}