From 69cd1f5d19479b66b4c6f28d2552935ba4ec800c Mon Sep 17 00:00:00 2001 From: Lars Hvam Date: Fri, 23 Nov 2018 12:16:47 +0100 Subject: [PATCH] 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 --- abaplint.json | 10 +- package.json | 2 +- ...t_parallel.fugr.lzabapgit_paralleltop.abap | 3 + ...it_parallel.fugr.lzabapgit_paralleltop.xml | 19 ++ ...t_parallel.fugr.saplzabapgit_parallel.abap | 15 + ...it_parallel.fugr.saplzabapgit_parallel.xml | 20 ++ src/zabapgit_parallel.fugr.xml | 102 +++++++ ...lel.fugr.z_abapgit_serialize_parallel.abap | 44 +++ src/zcl_abapgit_repo.clas.abap | 69 ++--- src/zcl_abapgit_serialize.clas.abap | 270 ++++++++++++++++++ ...cl_abapgit_serialize.clas.testclasses.abap | 134 +++++++++ src/zcl_abapgit_serialize.clas.xml | 19 ++ 12 files changed, 657 insertions(+), 50 deletions(-) create mode 100644 src/zabapgit_parallel.fugr.lzabapgit_paralleltop.abap create mode 100644 src/zabapgit_parallel.fugr.lzabapgit_paralleltop.xml create mode 100644 src/zabapgit_parallel.fugr.saplzabapgit_parallel.abap create mode 100644 src/zabapgit_parallel.fugr.saplzabapgit_parallel.xml create mode 100644 src/zabapgit_parallel.fugr.xml create mode 100644 src/zabapgit_parallel.fugr.z_abapgit_serialize_parallel.abap create mode 100644 src/zcl_abapgit_serialize.clas.abap create mode 100644 src/zcl_abapgit_serialize.clas.testclasses.abap create mode 100644 src/zcl_abapgit_serialize.clas.xml diff --git a/abaplint.json b/abaplint.json index 8e8c09b95..75b830f51 100644 --- a/abaplint.json +++ b/abaplint.json @@ -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 @@ } } } + diff --git a/package.json b/package.json index b8c5b2508..9661a3c49 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,6 @@ }, "devDependencies": { "abapmerge": "^0.11.0", - "abaplint": "^1.0.1" + "abaplint": "^1.3.5" } } diff --git a/src/zabapgit_parallel.fugr.lzabapgit_paralleltop.abap b/src/zabapgit_parallel.fugr.lzabapgit_paralleltop.abap new file mode 100644 index 000000000..3655b16c8 --- /dev/null +++ b/src/zabapgit_parallel.fugr.lzabapgit_paralleltop.abap @@ -0,0 +1,3 @@ +FUNCTION-POOL ZABAPGIT_PARALLEL. "MESSAGE-ID .. + +* INCLUDE LZABAPGIT_PARALLELD... " Local class definition diff --git a/src/zabapgit_parallel.fugr.lzabapgit_paralleltop.xml b/src/zabapgit_parallel.fugr.lzabapgit_paralleltop.xml new file mode 100644 index 000000000..764ddbc4f --- /dev/null +++ b/src/zabapgit_parallel.fugr.lzabapgit_paralleltop.xml @@ -0,0 +1,19 @@ + + + + + + LZABAPGIT_PARALLELTOP + A + X + S + D$ + I + S + X + D$S + X + + + + diff --git a/src/zabapgit_parallel.fugr.saplzabapgit_parallel.abap b/src/zabapgit_parallel.fugr.saplzabapgit_parallel.abap new file mode 100644 index 000000000..068e16fb9 --- /dev/null +++ b/src/zabapgit_parallel.fugr.saplzabapgit_parallel.abap @@ -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 diff --git a/src/zabapgit_parallel.fugr.saplzabapgit_parallel.xml b/src/zabapgit_parallel.fugr.saplzabapgit_parallel.xml new file mode 100644 index 000000000..099f9e15f --- /dev/null +++ b/src/zabapgit_parallel.fugr.saplzabapgit_parallel.xml @@ -0,0 +1,20 @@ + + + + + + SAPLZABAPGIT_PARALLEL + A + X + S + D$ + F + S + E + X + D$S + X + + + + diff --git a/src/zabapgit_parallel.fugr.xml b/src/zabapgit_parallel.fugr.xml new file mode 100644 index 000000000..5474e28a9 --- /dev/null +++ b/src/zabapgit_parallel.fugr.xml @@ -0,0 +1,102 @@ + + + + + abapGit - Parallel Processing + + LZABAPGIT_PARALLELTOP + SAPLZABAPGIT_PARALLEL + + + + Z_ABAPGIT_SERIALIZE_PARALLEL + R + Serialize object + + + IV_OBJ_TYPE + TADIR-OBJECT + + + IV_OBJ_NAME + TADIR-OBJ_NAME + + + IV_DEVCLASS + TADIR-DEVCLASS + + + IV_LANGUAGE + SY-LANGU + + + IV_PATH + STRING + + + + + EV_RESULT + XSTRING + + + EV_PATH + STRING + + + + + ERROR + + + + + IV_OBJ_TYPE + P + Object Type + 001 + + + IV_OBJ_NAME + P + Object Name in Object Directory + 002 + + + IV_DEVCLASS + P + Package + 003 + + + IV_LANGUAGE + P + ABAP System Field: Language Key of Text Environment + 004 + + + IV_PATH + P + 005 + + + EV_RESULT + P + 006 + + + EV_PATH + P + 007 + + + ERROR + X + 008 + + + + + + + diff --git a/src/zabapgit_parallel.fugr.z_abapgit_serialize_parallel.abap b/src/zabapgit_parallel.fugr.z_abapgit_serialize_parallel.abap new file mode 100644 index 000000000..66a6364cf --- /dev/null +++ b/src/zabapgit_parallel.fugr.z_abapgit_serialize_parallel.abap @@ -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. diff --git a/src/zcl_abapgit_repo.clas.abap b/src/zcl_abapgit_repo.clas.abap index 055226cfa..99201668c 100644 --- a/src/zcl_abapgit_repo.clas.abap +++ b/src/zcl_abapgit_repo.clas.abap @@ -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: LIKE LINE OF ls_fils_item-files, - LIKE LINE OF rt_files, - LIKE LINE OF lt_tadir. + FIELD-SYMBOLS: 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 . - - lo_progress->show( - iv_current = sy-tabix - iv_text = |Serialize { -obj_name }| ) ##NO_TEXT. - - ls_fils_item-item-obj_type = -object. - ls_fils_item-item-obj_name = -obj_name. - ls_fils_item-item-devclass = -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 . - -path = -path. - - APPEND INITIAL LINE TO rt_files ASSIGNING . - -file = . - -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. diff --git a/src/zcl_abapgit_serialize.clas.abap b/src/zcl_abapgit_serialize.clas.abap new file mode 100644 index 000000000..f2c9bbbae --- /dev/null +++ b/src/zcl_abapgit_serialize.clas.abap @@ -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: LIKE LINE OF is_fils_item-files, + LIKE LINE OF mt_files. + + + LOOP AT is_fils_item-files ASSIGNING . + APPEND INITIAL LINE TO mt_files ASSIGNING . + -file = . + -file-path = iv_path. + -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: 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 . + + lo_progress->show( + iv_current = sy-tabix + iv_text = |Serialize { -obj_name }, { lv_max } threads| ) ##NO_TEXT. + + IF lv_max = 1. + run_sequential( + is_tadir = + iv_language = iv_language ). + ELSE. + run_parallel( + iv_group = 'parallel_generators' " todo + is_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. diff --git a/src/zcl_abapgit_serialize.clas.testclasses.abap b/src/zcl_abapgit_serialize.clas.testclasses.abap new file mode 100644 index 000000000..aef0e7520 --- /dev/null +++ b/src/zcl_abapgit_serialize.clas.testclasses.abap @@ -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: LIKE LINE OF lt_tadir. + + + APPEND INITIAL LINE TO lt_tadir ASSIGNING . + -object = 'PROG'. + -obj_name = 'RSABAPPROGRAM'. + -devclass = 'PACKAGE'. + -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: LIKE LINE OF lt_tadir. + + + APPEND INITIAL LINE TO lt_tadir ASSIGNING . + -object = 'ABCD'. + -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. diff --git a/src/zcl_abapgit_serialize.clas.xml b/src/zcl_abapgit_serialize.clas.xml new file mode 100644 index 000000000..849ae4fb0 --- /dev/null +++ b/src/zcl_abapgit_serialize.clas.xml @@ -0,0 +1,19 @@ + + + + + + ZCL_ABAPGIT_SERIALIZE + 1 + E + Serialize objects in parallel + 2 + 1 + X + X + X + X + + + +