parallel serialization #1714 (#2129)

* parallel serialization #1714

* use latest abaplint

* Update abaplint.json

* add function group

* fallback to sequential

* fix error when running in background mode
This commit is contained in:
Lars Hvam 2018-11-23 12:16:47 +01:00 committed by GitHub
parent 6e9f6b8a45
commit 69cd1f5d19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 657 additions and 50 deletions

View File

@ -62,6 +62,10 @@
"cloud_types": {
"enabled": true
},
"method_length": {
"enabled": true,
"statements": 180
},
"mix_returning": {
"enabled": true
},
@ -71,7 +75,10 @@
"importing": "^I._.*$",
"returning": "^R._.*$",
"changing": "^C._.*$",
"exporting": "^E._.*$"
"exporting": "^E._.*$",
"ignoreNames": [
"P_TASK"
]
},
"inline_data_old_versions": {
"enabled": true
@ -90,3 +97,4 @@
}
}
}

View File

@ -11,6 +11,6 @@
},
"devDependencies": {
"abapmerge": "^0.11.0",
"abaplint": "^1.0.1"
"abaplint": "^1.3.5"
}
}

View File

@ -0,0 +1,3 @@
FUNCTION-POOL ZABAPGIT_PARALLEL. "MESSAGE-ID ..
* INCLUDE LZABAPGIT_PARALLELD... " Local class definition

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<PROGDIR>
<NAME>LZABAPGIT_PARALLELTOP</NAME>
<STATE>A</STATE>
<VARCL>X</VARCL>
<DBAPL>S</DBAPL>
<DBNA>D$</DBNA>
<SUBC>I</SUBC>
<APPL>S</APPL>
<FIXPT>X</FIXPT>
<LDBNAME>D$S</LDBNAME>
<UCCHECK>X</UCCHECK>
</PROGDIR>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,15 @@
*******************************************************************
* System-defined Include-files. *
*******************************************************************
INCLUDE LZABAPGIT_PARALLELTOP. " Global Declarations
INCLUDE LZABAPGIT_PARALLELUXX. " Function Modules
*******************************************************************
* User-defined Include-files (if necessary). *
*******************************************************************
* INCLUDE LZABAPGIT_PARALLELF... " Subroutines
* INCLUDE LZABAPGIT_PARALLELO... " PBO-Modules
* INCLUDE LZABAPGIT_PARALLELI... " PAI-Modules
* INCLUDE LZABAPGIT_PARALLELE... " Events
* INCLUDE LZABAPGIT_PARALLELP... " Local class implement.
* INCLUDE LZABAPGIT_PARALLELT99. " ABAP Unit tests

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<PROGDIR>
<NAME>SAPLZABAPGIT_PARALLEL</NAME>
<STATE>A</STATE>
<VARCL>X</VARCL>
<DBAPL>S</DBAPL>
<DBNA>D$</DBNA>
<SUBC>F</SUBC>
<APPL>S</APPL>
<RLOAD>E</RLOAD>
<FIXPT>X</FIXPT>
<LDBNAME>D$S</LDBNAME>
<UCCHECK>X</UCCHECK>
</PROGDIR>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_FUGR" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<AREAT>abapGit - Parallel Processing</AREAT>
<INCLUDES>
<SOBJ_NAME>LZABAPGIT_PARALLELTOP</SOBJ_NAME>
<SOBJ_NAME>SAPLZABAPGIT_PARALLEL</SOBJ_NAME>
</INCLUDES>
<FUNCTIONS>
<item>
<FUNCNAME>Z_ABAPGIT_SERIALIZE_PARALLEL</FUNCNAME>
<REMOTE_CALL>R</REMOTE_CALL>
<SHORT_TEXT>Serialize object</SHORT_TEXT>
<IMPORT>
<RSIMP>
<PARAMETER>IV_OBJ_TYPE</PARAMETER>
<TYP>TADIR-OBJECT</TYP>
</RSIMP>
<RSIMP>
<PARAMETER>IV_OBJ_NAME</PARAMETER>
<TYP>TADIR-OBJ_NAME</TYP>
</RSIMP>
<RSIMP>
<PARAMETER>IV_DEVCLASS</PARAMETER>
<TYP>TADIR-DEVCLASS</TYP>
</RSIMP>
<RSIMP>
<PARAMETER>IV_LANGUAGE</PARAMETER>
<TYP>SY-LANGU</TYP>
</RSIMP>
<RSIMP>
<PARAMETER>IV_PATH</PARAMETER>
<TYP>STRING</TYP>
</RSIMP>
</IMPORT>
<EXPORT>
<RSEXP>
<PARAMETER>EV_RESULT</PARAMETER>
<TYP>XSTRING</TYP>
</RSEXP>
<RSEXP>
<PARAMETER>EV_PATH</PARAMETER>
<TYP>STRING</TYP>
</RSEXP>
</EXPORT>
<EXCEPTION>
<RSEXC>
<EXCEPTION>ERROR</EXCEPTION>
</RSEXC>
</EXCEPTION>
<DOCUMENTATION>
<RSFDO>
<PARAMETER>IV_OBJ_TYPE</PARAMETER>
<KIND>P</KIND>
<STEXT>Object Type</STEXT>
<INDEX> 001</INDEX>
</RSFDO>
<RSFDO>
<PARAMETER>IV_OBJ_NAME</PARAMETER>
<KIND>P</KIND>
<STEXT>Object Name in Object Directory</STEXT>
<INDEX> 002</INDEX>
</RSFDO>
<RSFDO>
<PARAMETER>IV_DEVCLASS</PARAMETER>
<KIND>P</KIND>
<STEXT>Package</STEXT>
<INDEX> 003</INDEX>
</RSFDO>
<RSFDO>
<PARAMETER>IV_LANGUAGE</PARAMETER>
<KIND>P</KIND>
<STEXT>ABAP System Field: Language Key of Text Environment</STEXT>
<INDEX> 004</INDEX>
</RSFDO>
<RSFDO>
<PARAMETER>IV_PATH</PARAMETER>
<KIND>P</KIND>
<INDEX> 005</INDEX>
</RSFDO>
<RSFDO>
<PARAMETER>EV_RESULT</PARAMETER>
<KIND>P</KIND>
<INDEX> 006</INDEX>
</RSFDO>
<RSFDO>
<PARAMETER>EV_PATH</PARAMETER>
<KIND>P</KIND>
<INDEX> 007</INDEX>
</RSFDO>
<RSFDO>
<PARAMETER>ERROR</PARAMETER>
<KIND>X</KIND>
<INDEX> 008</INDEX>
</RSFDO>
</DOCUMENTATION>
</item>
</FUNCTIONS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,44 @@
FUNCTION z_abapgit_serialize_parallel.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(IV_OBJ_TYPE) TYPE TADIR-OBJECT
*" VALUE(IV_OBJ_NAME) TYPE TADIR-OBJ_NAME
*" VALUE(IV_DEVCLASS) TYPE TADIR-DEVCLASS
*" VALUE(IV_LANGUAGE) TYPE SY-LANGU
*" VALUE(IV_PATH) TYPE STRING
*" EXPORTING
*" VALUE(EV_RESULT) TYPE XSTRING
*" VALUE(EV_PATH) TYPE STRING
*" EXCEPTIONS
*" ERROR
*"----------------------------------------------------------------------
DATA: ls_item TYPE zif_abapgit_definitions=>ty_item,
lx_error TYPE REF TO zcx_abapgit_exception,
lv_text TYPE c LENGTH 200,
lt_files TYPE zcl_abapgit_objects=>ty_serialization.
TRY.
ls_item-obj_type = iv_obj_type.
ls_item-obj_name = iv_obj_name.
ls_item-devclass = iv_devclass.
lt_files = zcl_abapgit_objects=>serialize(
is_item = ls_item
iv_language = iv_language ).
EXPORT data = lt_files TO DATA BUFFER ev_result.
ev_path = iv_path.
CATCH zcx_abapgit_exception INTO lx_error.
lv_text = lx_error->get_text( ).
MESSAGE s000(oo) RAISING error WITH
lv_text+0(50)
lv_text+50(50)
lv_text+100(50)
lv_text+150(50).
ENDTRY.
ENDFUNCTION.

View File

@ -179,7 +179,7 @@ ENDCLASS.
CLASS zcl_abapgit_repo IMPLEMENTATION.
CLASS ZCL_ABAPGIT_REPO IMPLEMENTATION.
METHOD apply_filter.
@ -232,6 +232,17 @@ CLASS zcl_abapgit_repo IMPLEMENTATION.
ENDMETHOD.
METHOD conversion_exit_isola_output.
CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
EXPORTING
input = iv_spras
IMPORTING
output = rv_spras.
ENDMETHOD.
METHOD delete.
zcl_abapgit_persist_factory=>get_repo( )->delete( ms_data-key ).
@ -344,15 +355,11 @@ CLASS zcl_abapgit_repo IMPLEMENTATION.
METHOD get_files_local.
DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt,
lo_progress TYPE REF TO zcl_abapgit_progress,
lo_serialize TYPE REF TO zcl_abapgit_serialize,
lt_cache TYPE ty_cache_tt,
lt_found LIKE rt_files,
lx_error TYPE REF TO zcx_abapgit_exception,
ls_fils_item TYPE zcl_abapgit_objects=>ty_serialization.
lt_found LIKE rt_files.
FIELD-SYMBOLS: <ls_file> LIKE LINE OF ls_fils_item-files,
<ls_return> LIKE LINE OF rt_files,
<ls_tadir> LIKE LINE OF lt_tadir.
FIELD-SYMBOLS: <ls_return> LIKE LINE OF rt_files.
" Serialization happened before and no refresh request
@ -382,36 +389,13 @@ CLASS zcl_abapgit_repo IMPLEMENTATION.
CHANGING ct_tadir = lt_tadir ).
APPEND LINES OF lt_found TO rt_files.
CREATE OBJECT lo_progress
EXPORTING
iv_total = lines( lt_tadir ).
CREATE OBJECT lo_serialize.
LOOP AT lt_tadir ASSIGNING <ls_tadir>.
lo_progress->show(
iv_current = sy-tabix
iv_text = |Serialize { <ls_tadir>-obj_name }| ) ##NO_TEXT.
ls_fils_item-item-obj_type = <ls_tadir>-object.
ls_fils_item-item-obj_name = <ls_tadir>-obj_name.
ls_fils_item-item-devclass = <ls_tadir>-devclass.
TRY.
ls_fils_item = zcl_abapgit_objects=>serialize(
is_item = ls_fils_item-item
iv_language = get_dot_abapgit( )->get_master_language( ) ).
CATCH zcx_abapgit_exception INTO lx_error.
io_log->add_error( lx_error->get_text( ) ).
ENDTRY.
LOOP AT ls_fils_item-files ASSIGNING <ls_file>.
<ls_file>-path = <ls_tadir>-path.
APPEND INITIAL LINE TO rt_files ASSIGNING <ls_return>.
<ls_return>-file = <ls_file>.
<ls_return>-item = ls_fils_item-item.
ENDLOOP.
ENDLOOP.
lt_found = lo_serialize->serialize(
it_tadir = lt_tadir
iv_language = get_dot_abapgit( )->get_master_language( )
io_log = io_log ).
APPEND LINES OF lt_found TO rt_files.
GET TIME STAMP FIELD mv_last_serialization.
mt_local = rt_files.
@ -795,15 +779,4 @@ CLASS zcl_abapgit_repo IMPLEMENTATION.
set( it_checksums = lt_checksums ).
ENDMETHOD.
METHOD conversion_exit_isola_output.
CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
EXPORTING
input = iv_spras
IMPORTING
output = rv_spras.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,270 @@
CLASS zcl_abapgit_serialize DEFINITION
PUBLIC
CREATE PUBLIC .
PUBLIC SECTION.
METHODS on_end_of_task
IMPORTING
!p_task TYPE clike .
METHODS serialize
IMPORTING
!it_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt
!iv_language TYPE langu DEFAULT sy-langu
!io_log TYPE REF TO zcl_abapgit_log OPTIONAL
!iv_force_sequential TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(rt_files) TYPE zif_abapgit_definitions=>ty_files_item_tt
RAISING
zcx_abapgit_exception .
PROTECTED SECTION.
CLASS-DATA gv_max TYPE i .
DATA mt_files TYPE zif_abapgit_definitions=>ty_files_item_tt .
DATA mv_free TYPE i .
DATA mo_log TYPE REF TO zcl_abapgit_log .
METHODS add_to_return
IMPORTING
!iv_path TYPE string
!is_fils_item TYPE zcl_abapgit_objects=>ty_serialization .
METHODS run_parallel
IMPORTING
!iv_group TYPE rzlli_apcl
!is_tadir TYPE zif_abapgit_definitions=>ty_tadir
!iv_language TYPE langu
!iv_task TYPE sychar32
RAISING
zcx_abapgit_exception .
METHODS run_sequential
IMPORTING
!is_tadir TYPE zif_abapgit_definitions=>ty_tadir
!iv_language TYPE langu
RAISING
zcx_abapgit_exception .
METHODS determine_max_threads
IMPORTING
!iv_force_sequential TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(rv_threads) TYPE i
RAISING
zcx_abapgit_exception .
PRIVATE SECTION.
ENDCLASS.
CLASS ZCL_ABAPGIT_SERIALIZE IMPLEMENTATION.
METHOD add_to_return.
FIELD-SYMBOLS: <ls_file> LIKE LINE OF is_fils_item-files,
<ls_return> LIKE LINE OF mt_files.
LOOP AT is_fils_item-files ASSIGNING <ls_file>.
APPEND INITIAL LINE TO mt_files ASSIGNING <ls_return>.
<ls_return>-file = <ls_file>.
<ls_return>-file-path = iv_path.
<ls_return>-item = is_fils_item-item.
ENDLOOP.
ENDMETHOD.
METHOD determine_max_threads.
IF iv_force_sequential = abap_true.
rv_threads = 1.
RETURN.
ENDIF.
IF gv_max >= 1.
* SPBT_INITIALIZE gives error PBT_ENV_ALREADY_INITIALIZED if called
* multiple times in same session
rv_threads = gv_max.
RETURN.
ENDIF.
CALL FUNCTION 'FUNCTION_EXISTS'
EXPORTING
funcname = 'Z_ABAPGIT_SERIALIZE_PARALLEL'
EXCEPTIONS
function_not_exist = 1
OTHERS = 2.
IF sy-subrc <> 0.
gv_max = 1.
RETURN.
ENDIF.
* todo, add possibility to set group name in user exit
CALL FUNCTION 'SPBT_INITIALIZE'
EXPORTING
group_name = 'parallel_generators'
IMPORTING
free_pbt_wps = gv_max
EXCEPTIONS
invalid_group_name = 1
internal_error = 2
pbt_env_already_initialized = 3
currently_no_resources_avail = 4
no_pbt_resources_found = 5
cant_init_different_pbt_groups = 6
OTHERS = 7.
IF sy-subrc <> 0.
* fallback to running sequentially. If SPBT_INITIALIZE fails, check transactions
* RZ12, SM50, SM21, SARFC
gv_max = 1.
ENDIF.
IF gv_max > 1.
gv_max = gv_max - 1.
ENDIF.
ASSERT gv_max >= 1.
rv_threads = gv_max.
ENDMETHOD.
METHOD on_end_of_task.
DATA: lv_result TYPE xstring,
lv_path TYPE string,
ls_fils_item TYPE zcl_abapgit_objects=>ty_serialization.
RECEIVE RESULTS FROM FUNCTION 'Z_ABAPGIT_SERIALIZE_PARALLEL'
IMPORTING
ev_result = lv_result
ev_path = lv_path
EXCEPTIONS
error = 1
OTHERS = 2.
IF sy-subrc <> 0.
IF NOT mo_log IS INITIAL.
mo_log->add_error( |{ sy-msgv1 }{ sy-msgv2 }{ sy-msgv3 }{ sy-msgv3 }| ).
ENDIF.
ELSE.
IMPORT data = ls_fils_item FROM DATA BUFFER lv_result. "#EC CI_SUBRC
ASSERT sy-subrc = 0.
add_to_return( is_fils_item = ls_fils_item
iv_path = lv_path ).
ENDIF.
mv_free = mv_free + 1.
ENDMETHOD.
METHOD run_parallel.
DATA: lv_msg TYPE c LENGTH 100,
lv_free LIKE mv_free.
ASSERT mv_free > 0.
DO.
CALL FUNCTION 'Z_ABAPGIT_SERIALIZE_PARALLEL'
STARTING NEW TASK iv_task
DESTINATION IN GROUP iv_group
CALLING on_end_of_task ON END OF TASK
EXPORTING
iv_obj_type = is_tadir-object
iv_obj_name = is_tadir-obj_name
iv_devclass = is_tadir-devclass
iv_language = iv_language
iv_path = is_tadir-path
EXCEPTIONS
system_failure = 1 MESSAGE lv_msg
communication_failure = 2 MESSAGE lv_msg
resource_failure = 3
OTHERS = 4.
IF sy-subrc = 3.
lv_free = mv_free.
WAIT UNTIL mv_free <> lv_free UP TO 1 SECONDS.
CONTINUE.
ELSEIF sy-subrc <> 0.
ASSERT lv_msg = '' AND 0 = 1.
ENDIF.
EXIT.
ENDDO.
mv_free = mv_free - 1.
ENDMETHOD.
METHOD run_sequential.
DATA: lx_error TYPE REF TO zcx_abapgit_exception,
ls_fils_item TYPE zcl_abapgit_objects=>ty_serialization.
ls_fils_item-item-obj_type = is_tadir-object.
ls_fils_item-item-obj_name = is_tadir-obj_name.
ls_fils_item-item-devclass = is_tadir-devclass.
TRY.
ls_fils_item = zcl_abapgit_objects=>serialize(
is_item = ls_fils_item-item
iv_language = iv_language ).
add_to_return( is_fils_item = ls_fils_item
iv_path = is_tadir-path ).
CATCH zcx_abapgit_exception INTO lx_error.
IF NOT mo_log IS INITIAL.
mo_log->add_error( lx_error->get_text( ) ).
ENDIF.
ENDTRY.
ENDMETHOD.
METHOD serialize.
DATA: lv_max TYPE i,
lo_progress TYPE REF TO zcl_abapgit_progress.
FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF it_tadir.
CLEAR mt_files.
lv_max = determine_max_threads( iv_force_sequential ).
mv_free = lv_max.
mo_log = io_log.
CREATE OBJECT lo_progress
EXPORTING
iv_total = lines( it_tadir ).
LOOP AT it_tadir ASSIGNING <ls_tadir>.
lo_progress->show(
iv_current = sy-tabix
iv_text = |Serialize { <ls_tadir>-obj_name }, { lv_max } threads| ) ##NO_TEXT.
IF lv_max = 1.
run_sequential(
is_tadir = <ls_tadir>
iv_language = iv_language ).
ELSE.
run_parallel(
iv_group = 'parallel_generators' " todo
is_tadir = <ls_tadir>
iv_task = |{ sy-tabix }|
iv_language = iv_language ).
WAIT UNTIL mv_free > 0 UP TO 10 SECONDS.
ENDIF.
ENDLOOP.
WAIT UNTIL mv_free = lv_max UP TO 10 SECONDS.
rt_files = mt_files.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,134 @@
CLASS ltcl_determine_max_threads DEFINITION DEFERRED.
CLASS zcl_abapgit_serialize DEFINITION LOCAL FRIENDS ltcl_determine_max_threads.
CLASS ltcl_determine_max_threads DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
PRIVATE SECTION.
DATA:
mo_cut TYPE REF TO zcl_abapgit_serialize.
METHODS:
setup,
determine_max_threads FOR TESTING RAISING zcx_abapgit_exception,
force FOR TESTING RAISING zcx_abapgit_exception.
ENDCLASS.
CLASS ltcl_determine_max_threads IMPLEMENTATION.
METHOD setup.
CREATE OBJECT mo_cut.
ENDMETHOD.
METHOD determine_max_threads.
DATA: lv_threads TYPE i.
lv_threads = mo_cut->determine_max_threads( ).
cl_abap_unit_assert=>assert_differs(
act = lv_threads
exp = 0 ).
ENDMETHOD.
METHOD force.
DATA: lv_threads TYPE i.
lv_threads = mo_cut->determine_max_threads( abap_true ).
cl_abap_unit_assert=>assert_equals(
act = lv_threads
exp = 1 ).
ENDMETHOD.
ENDCLASS.
CLASS ltcl_serialize DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
PRIVATE SECTION.
DATA:
mo_cut TYPE REF TO zcl_abapgit_serialize.
METHODS:
setup,
test FOR TESTING RAISING zcx_abapgit_exception,
unsupported FOR TESTING RAISING zcx_abapgit_exception.
ENDCLASS.
CLASS ltcl_serialize IMPLEMENTATION.
METHOD setup.
CREATE OBJECT mo_cut.
ENDMETHOD.
METHOD test.
DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt,
lt_sequential TYPE zif_abapgit_definitions=>ty_files_item_tt,
lt_parallel TYPE zif_abapgit_definitions=>ty_files_item_tt.
FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF lt_tadir.
APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
<ls_tadir>-object = 'PROG'.
<ls_tadir>-obj_name = 'RSABAPPROGRAM'.
<ls_tadir>-devclass = 'PACKAGE'.
<ls_tadir>-path = 'foobar'.
lt_sequential = mo_cut->serialize(
it_tadir = lt_tadir
iv_force_sequential = abap_true ).
lt_parallel = mo_cut->serialize(
it_tadir = lt_tadir
iv_force_sequential = abap_false ).
cl_abap_unit_assert=>assert_equals(
act = lt_sequential
exp = lt_parallel ).
ENDMETHOD.
METHOD unsupported.
DATA: lt_tadir TYPE zif_abapgit_definitions=>ty_tadir_tt,
lo_log1 TYPE REF TO zcl_abapgit_log,
lo_log2 TYPE REF TO zcl_abapgit_log.
FIELD-SYMBOLS: <ls_tadir> LIKE LINE OF lt_tadir.
APPEND INITIAL LINE TO lt_tadir ASSIGNING <ls_tadir>.
<ls_tadir>-object = 'ABCD'.
<ls_tadir>-obj_name = 'OBJECT'.
CREATE OBJECT lo_log1.
mo_cut->serialize(
it_tadir = lt_tadir
io_log = lo_log1
iv_force_sequential = abap_true ).
CREATE OBJECT lo_log2.
mo_cut->serialize(
it_tadir = lt_tadir
io_log = lo_log2
iv_force_sequential = abap_false ).
cl_abap_unit_assert=>assert_char_cp(
act = lo_log1->to_html( )->render( )
exp = '*Object type ignored, not supported*' ).
cl_abap_unit_assert=>assert_equals(
act = lo_log1->to_html( )->render( )
exp = lo_log2->to_html( )->render( ) ).
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_ABAPGIT_SERIALIZE</CLSNAME>
<VERSION>1</VERSION>
<LANGU>E</LANGU>
<DESCRIPT>Serialize objects in parallel</DESCRIPT>
<EXPOSURE>2</EXPOSURE>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>