Hard batch G0022-G0026: 5/5 accepted; budget floor, CDS checks, mutation check

- generator: budget floor (2x oracle activations, 3x calls), static checks for CDS
  $parameters and UNION annotation
- harness/mutation.py: deterministic mutants of the reference; hidden tests must fail
- G0022 revalidated with harness fixes: oracle 100, null 0
- results in docs/faz1-tasarim.md 11f

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kral
2026-10-03 05:16:30 +02:00
parent 3570d7ef9b
commit 32f03fcad4
53 changed files with 2931 additions and 14 deletions

View File

@@ -0,0 +1,158 @@
CLASS {{p}}cl_rent DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_class TYPE string.
TYPES ty_money TYPE decfloat34.
TYPES ty_err_code TYPE c LENGTH 1.
CONSTANTS: BEGIN OF c_err,
ok TYPE ty_err_code VALUE ' ',
duration TYPE ty_err_code VALUE 'D',
distance TYPE ty_err_code VALUE 'K',
bad_class TYPE ty_err_code VALUE 'C',
END OF c_err.
TYPES: BEGIN OF ty_request,
vehicle_class TYPE ty_class,
minutes TYPE i,
km TYPE i,
member TYPE abap_bool,
weekend TYPE abap_bool,
END OF ty_request.
TYPES: BEGIN OF ty_result,
err_code TYPE ty_err_code,
time_fee TYPE ty_money,
distance_fee TYPE ty_money,
surcharge TYPE ty_money,
discount TYPE ty_money,
total TYPE ty_money,
END OF ty_result.
CLASS-METHODS calculate
IMPORTING is_request TYPE ty_request
RETURNING VALUE(rs_result) TYPE ty_result.
PRIVATE SECTION.
CONSTANTS: BEGIN OF c_block_price,
small TYPE ty_money VALUE '3.00',
medium TYPE ty_money VALUE '5.00',
large TYPE ty_money VALUE '8.00',
END OF c_block_price.
CONSTANTS c_block_minutes TYPE i VALUE 15.
CONSTANTS c_free_km TYPE i VALUE 10.
CONSTANTS c_km_price TYPE ty_money VALUE '0.25'.
CONSTANTS c_weekend_share TYPE ty_money VALUE '0.25'.
CONSTANTS c_member_share TYPE ty_money VALUE '0.15'.
CONSTANTS c_min_total TYPE ty_money VALUE '5.00'.
CONSTANTS c_decimals TYPE i VALUE 2.
CLASS-METHODS validate
IMPORTING is_request TYPE ty_request
RETURNING VALUE(rv_err_code) TYPE ty_err_code.
CLASS-METHODS time_fee
IMPORTING is_request TYPE ty_request
RETURNING VALUE(rv_fee) TYPE ty_money.
CLASS-METHODS distance_fee
IMPORTING is_request TYPE ty_request
RETURNING VALUE(rv_fee) TYPE ty_money.
CLASS-METHODS block_price
IMPORTING is_request TYPE ty_request
RETURNING VALUE(rv_price) TYPE ty_money.
CLASS-METHODS block_count
IMPORTING iv_minutes TYPE i
RETURNING VALUE(rv_blocks) TYPE i.
CLASS-METHODS round_money
IMPORTING iv_value TYPE ty_money
RETURNING VALUE(rv_value) TYPE ty_money.
ENDCLASS.
CLASS {{p}}cl_rent IMPLEMENTATION.
METHOD calculate.
rs_result-err_code = validate( is_request ).
IF rs_result-err_code <> c_err-ok.
RETURN.
ENDIF.
rs_result-time_fee = time_fee( is_request ).
rs_result-distance_fee = distance_fee( is_request ).
IF is_request-weekend = abap_true.
rs_result-surcharge = round_money( rs_result-time_fee * c_weekend_share ).
ELSE.
rs_result-surcharge = 0.
ENDIF.
DATA(lv_gross) = rs_result-time_fee + rs_result-distance_fee + rs_result-surcharge.
IF is_request-member = abap_true.
rs_result-discount = round_money( lv_gross * c_member_share ).
ELSE.
rs_result-discount = 0.
ENDIF.
rs_result-total = round_money( lv_gross - rs_result-discount ).
IF rs_result-total < c_min_total.
rs_result-total = c_min_total.
ENDIF.
ENDMETHOD.
METHOD validate.
IF is_request-minutes < 1.
rv_err_code = c_err-duration.
ELSEIF is_request-km < 0.
rv_err_code = c_err-distance.
ELSEIF is_request-vehicle_class <> 'S'
AND is_request-vehicle_class <> 'M'
AND is_request-vehicle_class <> 'L'.
rv_err_code = c_err-bad_class.
ELSE.
rv_err_code = c_err-ok.
ENDIF.
ENDMETHOD.
METHOD time_fee.
rv_fee = block_count( is_request-minutes ) * block_price( is_request ).
ENDMETHOD.
METHOD distance_fee.
DATA(lv_chargeable_km) = is_request-km - c_free_km.
IF lv_chargeable_km > 0.
rv_fee = lv_chargeable_km * c_km_price.
ELSE.
rv_fee = 0.
ENDIF.
ENDMETHOD.
METHOD block_price.
CASE is_request-vehicle_class.
WHEN 'S'.
rv_price = c_block_price-small.
WHEN 'M'.
rv_price = c_block_price-medium.
WHEN 'L'.
rv_price = c_block_price-large.
WHEN OTHERS.
rv_price = 0.
ENDCASE.
ENDMETHOD.
METHOD block_count.
rv_blocks = ( iv_minutes + c_block_minutes - 1 ) DIV c_block_minutes.
ENDMETHOD.
METHOD round_money.
rv_value = round( val = iv_value
dec = c_decimals
mode = cl_abap_math=>round_half_up ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,87 @@
CLASS {{p}}lcl_rent_test DEFINITION FOR TESTING
DURATION SHORT RISK LEVEL HARMLESS FINAL.
PRIVATE SECTION.
METHODS price_for
IMPORTING iv_class TYPE string
iv_minutes TYPE i
iv_km TYPE i
iv_member TYPE abap_bool DEFAULT abap_false
iv_weekend TYPE abap_bool DEFAULT abap_false
RETURNING VALUE(rs_result) TYPE {{p}}cl_rent=>ty_result.
METHODS time_fee_blocks FOR TESTING.
METHODS distance_fee_free_km FOR TESTING.
METHODS weekend_surcharge FOR TESTING.
METHODS member_discount FOR TESTING.
METHODS minimum_total FOR TESTING.
METHODS invalid_input FOR TESTING.
ENDCLASS.
CLASS {{p}}lcl_rent_test IMPLEMENTATION.
METHOD price_for.
DATA(ls_request) = VALUE {{p}}cl_rent=>ty_request(
vehicle_class = iv_class
minutes = iv_minutes
km = iv_km
member = iv_member
weekend = iv_weekend ).
rs_result = {{p}}cl_rent=>calculate( ls_request ).
ENDMETHOD.
METHOD time_fee_blocks.
DATA(ls_15) = price_for( iv_class = `S` iv_minutes = 15 iv_km = 0 ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 3 ) act = ls_15-time_fee ).
DATA(ls_16) = price_for( iv_class = `S` iv_minutes = 16 iv_km = 0 ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 6 ) act = ls_16-time_fee ).
DATA(ls_61) = price_for( iv_class = `L` iv_minutes = 61 iv_km = 0 ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 40 ) act = ls_61-time_fee ).
ENDMETHOD.
METHOD distance_fee_free_km.
DATA(ls_free) = price_for( iv_class = `L` iv_minutes = 60 iv_km = 10 ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 0 ) act = ls_free-distance_fee ).
DATA(ls_paid) = price_for( iv_class = `L` iv_minutes = 60 iv_km = 14 ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 1 ) act = ls_paid-distance_fee ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 33 ) act = ls_paid-total ).
ENDMETHOD.
METHOD weekend_surcharge.
DATA(ls) = price_for( iv_class = `M` iv_minutes = 30 iv_km = 0 iv_weekend = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '2.50' ) act = ls-surcharge ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '12.50' ) act = ls-total ).
ENDMETHOD.
METHOD member_discount.
DATA(ls_half) = price_for( iv_class = `M` iv_minutes = 15 iv_km = 11
iv_weekend = abap_true iv_member = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '0.98' ) act = ls_half-discount ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '5.52' ) act = ls_half-total ).
DATA(ls_up) = price_for( iv_class = `S` iv_minutes = 15 iv_km = 28 iv_member = abap_true ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '1.13' ) act = ls_up-discount ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '6.37' ) act = ls_up-total ).
ENDMETHOD.
METHOD minimum_total.
DATA(ls) = price_for( iv_class = `S` iv_minutes = 15 iv_km = 0 ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 3 ) act = ls-time_fee ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 5 ) act = ls-total ).
ENDMETHOD.
METHOD invalid_input.
cl_abap_unit_assert=>assert_equals(
exp = {{p}}cl_rent=>c_err-duration
act = price_for( iv_class = `S` iv_minutes = 0 iv_km = 0 )-err_code ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}cl_rent=>c_err-distance
act = price_for( iv_class = `S` iv_minutes = 15 iv_km = -1 )-err_code ).
cl_abap_unit_assert=>assert_equals(
exp = {{p}}cl_rent=>c_err-bad_class
act = price_for( iv_class = `X` iv_minutes = 15 iv_km = 0 )-err_code ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,30 @@
CLASS {{p}}cx_rent_invalid DEFINITION
PUBLIC
INHERITING FROM cx_static_check
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
METHODS constructor
IMPORTING textid LIKE textid OPTIONAL
previous LIKE previous OPTIONAL
iv_reason TYPE string OPTIONAL.
METHODS get_reason
RETURNING VALUE(rv_reason) TYPE string.
PRIVATE SECTION.
DATA mv_reason TYPE string.
ENDCLASS.
CLASS {{p}}cx_rent_invalid IMPLEMENTATION.
METHOD constructor.
super->constructor( textid = textid previous = previous ).
mv_reason = iv_reason.
ENDMETHOD.
METHOD get_reason.
rv_reason = mv_reason.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,43 @@
FUNCTION {{p}}rent_price
IMPORTING
iv_vehicle_class TYPE string
iv_minutes TYPE i
iv_km TYPE i
iv_member TYPE abap_bool
iv_weekend TYPE abap_bool
EXPORTING
ev_time_fee TYPE decfloat34
ev_distance_fee TYPE decfloat34
ev_surcharge TYPE decfloat34
ev_discount TYPE decfloat34
ev_total TYPE decfloat34
EXCEPTIONS
invalid_duration
invalid_distance
invalid_class.
DATA ls_request TYPE {{p}}cl_rent=>ty_request.
ls_request-vehicle_class = iv_vehicle_class.
ls_request-minutes = iv_minutes.
ls_request-km = iv_km.
ls_request-member = iv_member.
ls_request-weekend = iv_weekend.
DATA(ls_result) = {{p}}cl_rent=>calculate( ls_request ).
CASE ls_result-err_code.
WHEN {{p}}cl_rent=>c_err-duration.
RAISE invalid_duration.
WHEN {{p}}cl_rent=>c_err-distance.
RAISE invalid_distance.
WHEN {{p}}cl_rent=>c_err-bad_class.
RAISE invalid_class.
WHEN OTHERS.
ev_time_fee = ls_result-time_fee.
ev_distance_fee = ls_result-distance_fee.
ev_surcharge = ls_result-surcharge.
ev_discount = ls_result-discount.
ev_total = ls_result-total.
ENDCASE.
ENDFUNCTION.

View File

@@ -0,0 +1,90 @@
CLASS {{p}}t14_test DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
TYPES: BEGIN OF ty_result,
time_fee TYPE decfloat34,
distance_fee TYPE decfloat34,
surcharge TYPE decfloat34,
discount TYPE decfloat34,
total TYPE decfloat34,
END OF ty_result.
METHODS price
IMPORTING iv_class TYPE string
iv_minutes TYPE i
iv_km TYPE i
iv_member TYPE abap_bool DEFAULT abap_false
iv_weekend TYPE abap_bool DEFAULT abap_false
EXPORTING es_result TYPE ty_result
ev_subrc TYPE sysubrc.
METHODS time_fee_blocks FOR TESTING.
METHODS distance_fee_free_km FOR TESTING.
METHODS weekend_surcharge FOR TESTING.
METHODS member_discount FOR TESTING.
METHODS minimum_total FOR TESTING.
METHODS invalid_duration FOR TESTING.
ENDCLASS.
CLASS {{p}}t14_test IMPLEMENTATION.
METHOD price.
CLEAR es_result.
CALL FUNCTION '{{P}}RENT_PRICE'
EXPORTING
iv_vehicle_class = iv_class
iv_minutes = iv_minutes
iv_km = iv_km
iv_member = iv_member
iv_weekend = iv_weekend
IMPORTING
ev_time_fee = es_result-time_fee
ev_distance_fee = es_result-distance_fee
ev_surcharge = es_result-surcharge
ev_discount = es_result-discount
ev_total = es_result-total
EXCEPTIONS
invalid_duration = 1
invalid_distance = 2
invalid_class = 3
OTHERS = 4.
ev_subrc = sy-subrc.
ENDMETHOD.
METHOD time_fee_blocks.
price( EXPORTING iv_class = `S` iv_minutes = 16 iv_km = 0
IMPORTING es_result = DATA(ls) ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 6 ) act = ls-time_fee ).
ENDMETHOD.
METHOD distance_fee_free_km.
price( EXPORTING iv_class = `L` iv_minutes = 60 iv_km = 14
IMPORTING es_result = DATA(ls) ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 1 ) act = ls-distance_fee ).
ENDMETHOD.
METHOD weekend_surcharge.
price( EXPORTING iv_class = `M` iv_minutes = 30 iv_km = 0 iv_weekend = abap_true
IMPORTING es_result = DATA(ls) ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '2.50' ) act = ls-surcharge ).
ENDMETHOD.
METHOD member_discount.
price( EXPORTING iv_class = `S` iv_minutes = 15 iv_km = 28 iv_member = abap_true
IMPORTING es_result = DATA(ls) ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '1.13' ) act = ls-discount ).
ENDMETHOD.
METHOD minimum_total.
price( EXPORTING iv_class = `S` iv_minutes = 15 iv_km = 0
IMPORTING es_result = DATA(ls) ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 5 ) act = ls-total ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( 3 ) act = ls-time_fee ).
ENDMETHOD.
METHOD invalid_duration.
price( EXPORTING iv_class = `S` iv_minutes = 0 iv_km = 0
IMPORTING ev_subrc = DATA(lv_subrc) ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_subrc ).
ENDMETHOD.
ENDCLASS.