Stage 2 summary at 50 accepted trajectories

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Kral
2026-10-05 18:02:52 +02:00
parent 332fb4601d
commit 5bcd1bf9cd
1230 changed files with 77563 additions and 33 deletions

View File

@@ -0,0 +1,25 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Vending machine state'
define view entity {{P}}I_VEND_STATE
as select from {{p}}vmach as machine
left outer join {{p}}vslot as slot on slot.machine_id = machine.machine_id
{
key machine.machine_id as machine_id,
upper( machine.location ) as location,
count( * ) as slot_count,
cast( sum( case when slot.fill_level = 0
then 1
else 0
end ) as abap.int4 ) as empty_slots,
division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) as fill_rate,
case
when sum( slot.fill_level ) = 0 then 'EMPTY'
when division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) < 25 then 'LOW'
else 'OK'
end as status
}
group by
machine.machine_id,
machine.location

View File

@@ -0,0 +1,25 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Vending machine state'
define view entity {{P}}I_VEND_STATE
as select from {{p}}vmach as machine
inner join {{p}}vslot as slot on slot.machine_id = machine.machine_id
{
key machine.machine_id as machine_id,
upper( machine.location ) as location,
count( * ) as slot_count,
cast( sum( case when slot.fill_level = 0
then 2
else 0
end ) as abap.int4 ) as empty_slots,
division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) as fill_rate,
case
when sum( slot.fill_level ) = 0 then 'EMPTY'
when division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) < 25 then 'LOW'
else 'OK'
end as status
}
group by
machine.machine_id,
machine.location

View File

@@ -0,0 +1,25 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Vending machine state'
define view entity {{P}}I_VEND_STATE
as select from {{p}}vmach as machine
inner join {{p}}vslot as slot on slot.machine_id = machine.machine_id
{
key machine.machine_id as machine_id,
upper( machine.location ) as location,
count( * ) as slot_count,
cast( sum( case when slot.fill_level = 0
then 1
else 0
end ) as abap.int4 ) as empty_slots,
division( max( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) as fill_rate,
case
when sum( slot.fill_level ) = 0 then 'EMPTY'
when division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) < 25 then 'LOW'
else 'OK'
end as status
}
group by
machine.machine_id,
machine.location

View File

@@ -0,0 +1,25 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Vending machine state'
define view entity {{P}}I_VEND_STATE
as select from {{p}}vmach as machine
inner join {{p}}vslot as slot on slot.machine_id = machine.machine_id
{
key machine.machine_id as machine_id,
upper( machine.location ) as location,
count( * ) as slot_count,
cast( sum( case when slot.fill_level = 0
then 1
else 0
end ) as abap.int4 ) as empty_slots,
division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) as fill_rate,
case
when sum( slot.fill_level ) <> 0 then 'EMPTY'
when division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) < 25 then 'LOW'
else 'OK'
end as status
}
group by
machine.machine_id,
machine.location

View File

@@ -0,0 +1,25 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Vending machine state'
define view entity {{P}}I_VEND_STATE
as select from {{p}}vmach as machine
inner join {{p}}vslot as slot on slot.machine_id = machine.machine_id
{
key machine.machine_id as machine_id,
upper( machine.location ) as location,
count( * ) as slot_count,
cast( sum( case when slot.fill_level = 0
then 1
else 0
end ) as abap.int4 ) as empty_slots,
division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) as fill_rate,
case
when sum( slot.fill_level ) = 0 then 'EMPTY'
when division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) >= 25 then 'LOW'
else 'OK'
end as status
}
group by
machine.machine_id,
machine.location

View File

@@ -0,0 +1,24 @@
{
"id": "G1080",
"pool": "train",
"object_type": "DDLS",
"category": "B",
"attempts": [
{
"stage": "validate",
"oracle": 85.0,
"null": 0
},
{
"stage": "validate",
"oracle": 100.0,
"null": 0,
"mutation": {
"valid": 5,
"killed": 5,
"ok": true
}
}
],
"accepted": true
}

View File

@@ -0,0 +1,109 @@
CLASS {{p}}t16_hidden DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA go_env TYPE REF TO if_cds_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS setup.
METHODS slot_counts FOR TESTING.
METHODS empty_slots FOR TESTING.
METHODS fill_rate_decimals FOR TESTING.
METHODS fill_rate_half FOR TESTING.
METHODS status_empty FOR TESTING.
METHODS status_low FOR TESTING.
METHODS status_ok FOR TESTING.
METHODS status_at_limit FOR TESTING.
METHODS machine_without_slots FOR TESTING.
METHODS location_upper FOR TESTING.
ENDCLASS.
CLASS {{p}}t16_hidden IMPLEMENTATION.
METHOD class_setup.
go_env = cl_cds_test_environment=>create( i_for_entity = '{{P}}I_VEND_STATE' ).
ENDMETHOD.
METHOD class_teardown.
go_env->destroy( ).
ENDMETHOD.
METHOD setup.
DATA lt_mach TYPE STANDARD TABLE OF {{p}}vmach WITH EMPTY KEY.
DATA lt_slot TYPE STANDARD TABLE OF {{p}}vslot WITH EMPTY KEY.
go_env->clear_doubles( ).
lt_mach = VALUE #( ( machine_id = 'M1' location = 'Hall A' )
( machine_id = 'M2' location = 'Bay 2' )
( machine_id = 'M3' location = 'Depot C' )
( machine_id = 'M4' location = 'Kiosk D' )
( machine_id = 'M5' location = 'Gate E' )
( machine_id = 'M6' location = 'Pier F' ) ).
lt_slot = VALUE #( ( machine_id = 'M1' slot_no = 1 product = 'COLA' fill_level = 3 max_units = 10 )
( machine_id = 'M1' slot_no = 2 product = 'WATER' fill_level = 0 max_units = 10 )
( machine_id = 'M2' slot_no = 1 product = 'CHIPS' fill_level = 0 max_units = 5 )
( machine_id = 'M2' slot_no = 2 product = 'NUTS' fill_level = 0 max_units = 5 )
( machine_id = 'M3' slot_no = 1 product = 'COLA' fill_level = 5 max_units = 10 )
( machine_id = 'M3' slot_no = 2 product = 'JUICE' fill_level = 5 max_units = 10 )
( machine_id = 'M5' slot_no = 1 product = 'TEA' fill_level = 5 max_units = 20 )
( machine_id = 'M6' slot_no = 1 product = 'MILK' fill_level = 1 max_units = 8 ) ).
go_env->insert_test_data( lt_mach ).
go_env->insert_test_data( lt_slot ).
ENDMETHOD.
METHOD slot_counts.
SELECT SINGLE slot_count FROM {{p}}i_vend_state WHERE machine_id = 'M1' INTO @DATA(lv_two).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lv_two ).
SELECT SINGLE slot_count FROM {{p}}i_vend_state WHERE machine_id = 'M5' INTO @DATA(lv_one).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_one ).
ENDMETHOD.
METHOD empty_slots.
SELECT SINGLE empty_slots FROM {{p}}i_vend_state WHERE machine_id = 'M1' INTO @DATA(lv_one).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lv_one ).
SELECT SINGLE empty_slots FROM {{p}}i_vend_state WHERE machine_id = 'M2' INTO @DATA(lv_two).
cl_abap_unit_assert=>assert_equals( exp = 2 act = lv_two ).
SELECT SINGLE empty_slots FROM {{p}}i_vend_state WHERE machine_id = 'M3' INTO @DATA(lv_none).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lv_none ).
ENDMETHOD.
METHOD fill_rate_decimals.
SELECT SINGLE fill_rate FROM {{p}}i_vend_state WHERE machine_id = 'M6' INTO @DATA(lv_rate).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '12.5' )
act = CONV decfloat34( lv_rate ) ).
ENDMETHOD.
METHOD fill_rate_half.
SELECT SINGLE fill_rate FROM {{p}}i_vend_state WHERE machine_id = 'M3' INTO @DATA(lv_rate).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '50.0' )
act = CONV decfloat34( lv_rate ) ).
ENDMETHOD.
METHOD status_empty.
SELECT SINGLE status FROM {{p}}i_vend_state WHERE machine_id = 'M2' INTO @DATA(lv_status).
cl_abap_unit_assert=>assert_equals( exp = 'EMPTY' act = lv_status ).
ENDMETHOD.
METHOD status_low.
SELECT SINGLE status FROM {{p}}i_vend_state WHERE machine_id = 'M1' INTO @DATA(lv_status).
cl_abap_unit_assert=>assert_equals( exp = 'LOW' act = lv_status ).
ENDMETHOD.
METHOD status_ok.
SELECT SINGLE status FROM {{p}}i_vend_state WHERE machine_id = 'M3' INTO @DATA(lv_status).
cl_abap_unit_assert=>assert_equals( exp = 'OK' act = lv_status ).
ENDMETHOD.
METHOD status_at_limit.
SELECT SINGLE status FROM {{p}}i_vend_state WHERE machine_id = 'M5' INTO @DATA(lv_status).
cl_abap_unit_assert=>assert_equals( exp = 'OK' act = lv_status ).
ENDMETHOD.
METHOD machine_without_slots.
SELECT COUNT(*) FROM {{p}}i_vend_state INTO @DATA(lv_rows).
cl_abap_unit_assert=>assert_equals( exp = 5 act = lv_rows ).
ENDMETHOD.
METHOD location_upper.
SELECT SINGLE location FROM {{p}}i_vend_state WHERE machine_id = 'M1' INTO @DATA(lv_location).
cl_abap_unit_assert=>assert_equals( exp = 'HALL A' act = lv_location ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,59 @@
{
"task": "G1080",
"mutants": [
{
"object": "{{P}}I_VEND_STATE",
"mutant": "line 5: inner join -> left outer join (join)",
"status": "killed",
"hidden": "9/10",
"failed_tests": [
"MACHINE_WITHOUT_SLOTS"
]
},
{
"object": "{{P}}I_VEND_STATE",
"mutant": "line 11: 1 -> 2 (const)",
"status": "killed",
"hidden": "9/10",
"failed_tests": [
"EMPTY_SLOTS"
]
},
{
"object": "{{P}}I_VEND_STATE",
"mutant": "line 14: sum( -> max( (agg)",
"status": "killed",
"hidden": "9/10",
"failed_tests": [
"FILL_RATE_HALF"
]
},
{
"object": "{{P}}I_VEND_STATE",
"mutant": "line 17: = -> <> (eq)",
"status": "killed",
"hidden": "6/10",
"failed_tests": [
"STATUS_AT_LIMIT",
"STATUS_EMPTY",
"STATUS_LOW",
"STATUS_OK"
]
},
{
"object": "{{P}}I_VEND_STATE",
"mutant": "line 19: < -> >= (rel)",
"status": "killed",
"hidden": "7/10",
"failed_tests": [
"STATUS_AT_LIMIT",
"STATUS_LOW",
"STATUS_OK"
]
}
],
"valid": 5,
"killed": 5,
"kill_rate": 1.0,
"ok": true
}

View File

@@ -0,0 +1,25 @@
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Vending machine state'
define view entity {{P}}I_VEND_STATE
as select from {{p}}vmach as machine
inner join {{p}}vslot as slot on slot.machine_id = machine.machine_id
{
key machine.machine_id as machine_id,
upper( machine.location ) as location,
count( * ) as slot_count,
cast( sum( case when slot.fill_level = 0
then 1
else 0
end ) as abap.int4 ) as empty_slots,
division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) as fill_rate,
case
when sum( slot.fill_level ) = 0 then 'EMPTY'
when division( sum( slot.fill_level ) * 100,
sum( slot.max_units ), 1 ) < 25 then 'LOW'
else 'OK'
end as status
}
group by
machine.machine_id,
machine.location

View File

@@ -0,0 +1,56 @@
CLASS {{p}}t16_test DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA go_env TYPE REF TO if_cds_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS setup.
METHODS low_machine FOR TESTING.
METHODS empty_machine FOR TESTING.
ENDCLASS.
CLASS {{p}}t16_test IMPLEMENTATION.
METHOD class_setup.
go_env = cl_cds_test_environment=>create( i_for_entity = '{{P}}I_VEND_STATE' ).
ENDMETHOD.
METHOD class_teardown.
go_env->destroy( ).
ENDMETHOD.
METHOD setup.
go_env->clear_doubles( ).
ENDMETHOD.
METHOD low_machine.
DATA lt_mach TYPE STANDARD TABLE OF {{p}}vmach WITH EMPTY KEY.
DATA lt_slot TYPE STANDARD TABLE OF {{p}}vslot WITH EMPTY KEY.
lt_mach = VALUE #( ( machine_id = 'A' location = 'Hall' ) ).
lt_slot = VALUE #( ( machine_id = 'A' slot_no = 1 product = 'COLA' fill_level = 1 max_units = 4 )
( machine_id = 'A' slot_no = 2 product = 'TEA' fill_level = 0 max_units = 4 ) ).
go_env->insert_test_data( lt_mach ).
go_env->insert_test_data( lt_slot ).
SELECT SINGLE slot_count, empty_slots, fill_rate, status FROM {{p}}i_vend_state
WHERE machine_id = 'A' INTO @DATA(ls_row).
cl_abap_unit_assert=>assert_equals( exp = 2 act = ls_row-slot_count ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = ls_row-empty_slots ).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '12.5' )
act = CONV decfloat34( ls_row-fill_rate ) ).
cl_abap_unit_assert=>assert_equals( exp = 'LOW' act = ls_row-status ).
ENDMETHOD.
METHOD empty_machine.
DATA lt_mach TYPE STANDARD TABLE OF {{p}}vmach WITH EMPTY KEY.
DATA lt_slot TYPE STANDARD TABLE OF {{p}}vslot WITH EMPTY KEY.
lt_mach = VALUE #( ( machine_id = 'B' location = 'Gate' ) ).
lt_slot = VALUE #( ( machine_id = 'B' slot_no = 1 product = 'NUTS' fill_level = 0 max_units = 6 ) ).
go_env->insert_test_data( lt_mach ).
go_env->insert_test_data( lt_slot ).
SELECT SINGLE fill_rate, status FROM {{p}}i_vend_state
WHERE machine_id = 'B' INTO @DATA(ls_row).
cl_abap_unit_assert=>assert_equals( exp = CONV decfloat34( '0.0' )
act = CONV decfloat34( ls_row-fill_rate ) ).
cl_abap_unit_assert=>assert_equals( exp = 'EMPTY' act = ls_row-status ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,10 @@
@EndUserText.label : 'Vending machine'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table {{p}}vmach {
key client : abap.clnt not null;
key machine_id : abap.char(10) not null;
location : abap.char(20);
}

View File

@@ -0,0 +1,13 @@
@EndUserText.label : 'Vending machine slot'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table {{p}}vslot {
key client : abap.clnt not null;
key machine_id : abap.char(10) not null;
key slot_no : abap.int4 not null;
product : abap.char(10);
fill_level : abap.int4;
max_units : abap.int4;
}

View File

@@ -0,0 +1,44 @@
# 1. Goal
Show the state of each vending machine. A dashboard and an OData service read the
state, so the calculation must be in the database, in a CDS view.
# 2. Open questions
None.
# 3. Context
- Table {{P}}VMACH (vending machine), package $TMP. Key: MACHINE_ID (CHAR 10).
Field: LOCATION (CHAR 20).
- Table {{P}}VSLOT (vending machine slot), package $TMP.
Key: MACHINE_ID (CHAR 10), SLOT_NO (INT4).
Fields: PRODUCT (CHAR 10), FILL_LEVEL (INT4, units that remain in the slot),
MAX_UNITS (INT4, capacity of the slot in units).
# 4. Contract
- Create the CDS view entity {{P}}I_VEND_STATE in package $TMP.
- Elements, with these names and types:
MACHINE_ID (key, CHAR 10), LOCATION (CHAR 20), SLOT_COUNT (INT4),
EMPTY_SLOTS (INT4), FILL_RATE (DEC 5,1), STATUS (CHAR 5).
- No authorization check (#NOT_REQUIRED).
# 5. Business rules
1. Show one row for each machine that has at least one slot. Do not show a
machine without slots.
2. SLOT_COUNT is the number of slots of the machine.
3. EMPTY_SLOTS is the number of slots of the machine with a fill level of zero.
4. FILL_RATE is the total fill level of the machine as a percentage of the total
capacity of the machine. FILL_RATE has one decimal place. Example: a total
fill level of 3 units and a total capacity of 20 units give 15.0.
5. LOCATION is the location of the machine in upper case letters.
6. STATUS is 'EMPTY' if the total fill level of the machine is zero. STATUS is
'LOW' if the total fill level is not zero and FILL_RATE is less than 25.0.
STATUS is 'OK' in all other cases.
# 6. Constraints
- Release target: SAP_BASIS 816 (ABAP Platform 2025).
- Coding standards: Clean ABAP. Keep methods below 40 statements.
- Out of scope: do not change {{P}}VMACH and {{P}}VSLOT.
# 7. Acceptance
- The view is active and has no syntax error.
- The hidden tests pass.
- Write ABAP Unit tests with CL_CDS_TEST_ENVIRONMENT in a global test class.

View File

@@ -0,0 +1,67 @@
{
"id": "G1080",
"category": "B",
"object_type": "DDLS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [
{
"type": "TABL",
"name": "{{P}}VMACH",
"file": "seed/vmach.tabl.asabap",
"description": "Vending machine"
},
{
"type": "TABL",
"name": "{{P}}VSLOT",
"file": "seed/vslot.tabl.asabap",
"description": "Vending machine slot"
}
],
"contract": [
{
"type": "DDLS",
"name": "{{P}}I_VEND_STATE",
"fields": [
"MACHINE_ID",
"LOCATION",
"SLOT_COUNT",
"EMPTY_SLOTS",
"FILL_RATE",
"STATUS"
]
}
],
"out_of_scope": [
"{{P}}VMACH",
"{{P}}VSLOT"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T16_HIDDEN",
"file": "hidden/t16_hidden.clas.abap",
"description": "T16 hidden tests"
}
],
"reference": [
{
"type": "DDLS",
"name": "{{P}}I_VEND_STATE",
"file": "reference/i_vend_state.ddls.asddls",
"description": "Vending machine state"
},
{
"type": "CLAS",
"name": "{{P}}T16_TEST",
"file": "reference/t16_test.clas.abap",
"description": "T16 own tests"
}
],
"craft_checks": []
}