Skip to content

Instantly share code, notes, and snippets.

@sandraros
Last active August 17, 2020 14:00
Show Gist options
  • Save sandraros/092b79ecc58e050c4e6798e110600b57 to your computer and use it in GitHub Desktop.
Save sandraros/092b79ecc58e050c4e6798e110600b57 to your computer and use it in GitHub Desktop.
Test class to verify the behavior of cl_http_utility=>unescape_url, that all escaped characters (from %00 to %EF%BF%BF which are equivalent to U+0000 to U+FFFF) are unescaped correctly, and more...
* SUMMARY OF SPECIFIC BEHAVIORS:
*
* input string (formatted as string template) returned string (formatted as string template)
* ------------------------------------------- -----------------------------------------
* any string containing %00 return empty string
* unencoded null character null character returned unchanged
* A%0AB A\nB
* A%0DB A\rB
* A%B return empty string
* A+B A B
* A\nB AB
* A\rB AB
* any character >= U+0080 #
CLASS ltc_main DEFINITION
FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS each_65536_percent_characters FOR TESTING.
METHODS null_character FOR TESTING.
METHODS special_characters FOR TESTING.
METHODS classic FOR TESTING.
CLASS-METHODS process_range
EXPORTING
string TYPE string
count_okay TYPE i.
ENDCLASS.
CLASS ltc_main IMPLEMENTATION.
METHOD each_65536_percent_characters.
DATA l_string TYPE string.
DATA count_okay TYPE i.
process_range(
IMPORTING
string = l_string
count_okay = count_okay ).
cl_abap_unit_assert=>assert_equals( act = l_string exp = '{%00->null}{x000A->null}{x000D->null}{x0025->null}{x002B->0020}' ).
" 129019 = 65532 + 63487
" 65532 = 65536 - 4
" 63487 = 65536 - 1 (null byte) - 2048 (surrogate code points D800 to D8FF)
cl_abap_unit_assert=>assert_equals( act = count_okay exp = 129019 ).
ENDMETHOD.
METHOD process_range.
DATA c1 TYPE c LENGTH 1.
DATA c2 TYPE c LENGTH 2.
DATA str TYPE string.
DATA x2 TYPE x LENGTH 2.
DATA int TYPE i.
count_okay = 0.
DATA(utf8) = cl_abap_codepage=>create( ).
string = ``.
int = 0.
WHILE int <= 65535.
c1 = cl_abap_conv_in_ce=>uccpi( int ).
x2 = cl_abap_conv_out_ce=>uccp( c1 ).
str = c1.
IF str IS INITIAL.
str = ` `.
ENDIF.
IF int < 128.
DATA(unescape) = cl_http_utility=>unescape_url( str ).
IF unescape = str.
ADD 1 TO count_okay.
ELSE.
IF unescape IS INITIAL.
unescape = 'null'.
ELSE.
unescape = cl_abap_conv_out_ce=>uccp( unescape ).
ENDIF.
string = |{ string }\{x{ x2 }->{ unescape }\}|.
ENDIF.
ELSE.
unescape = cl_http_utility=>unescape_url( str ).
IF unescape = '#'.
ADD 1 TO count_okay.
ELSE.
unescape = cl_abap_conv_out_ce=>uccp( unescape ).
string = |{ string }\{x{ x2 }->{ unescape }\}|.
ENDIF.
ENDIF.
IF int BETWEEN 55296 AND 57343.
" surrogate code points U+D800 U+DFFF
ELSE.
DATA(utf8_bytes) = utf8->convert_to( str ).
DATA(escaped) = ``.
DO xstrlen( utf8_bytes ) TIMES.
escaped = escaped && '%' && utf8_bytes(1).
SHIFT utf8_bytes LEFT IN BYTE MODE.
ENDDO.
unescape = cl_http_utility=>unescape_url( escaped ).
IF unescape = str.
ADD 1 TO count_okay.
ELSE.
IF unescape IS INITIAL.
unescape = 'null'.
ELSE.
TRY.
DATA(unescape_cp) = cl_abap_conv_out_ce=>uccp( unescape ).
unescape = unescape_cp.
CATCH cx_root.
ENDTRY.
ENDIF.
string = |{ string }\{{ escaped }->{ unescape }\}|.
ENDIF.
ENDIF.
ADD 1 TO int.
ENDWHILE.
ENDMETHOD.
METHOD null_character.
cl_abap_unit_assert=>assert_equals( act = cl_http_utility=>unescape_url( 'A%00B' ) exp = `` ).
data(escaped) = 'A' && cl_abap_char_utilities=>minchar && 'B'.
data(unescaped) = cl_http_utility=>unescape_url( escaped ).
cl_abap_unit_assert=>assert_equals( act = unescaped exp = escaped ).
ENDMETHOD.
METHOD special_characters.
cl_abap_unit_assert=>assert_equals( act = cl_http_utility=>unescape_url( 'A%0AB' ) exp = |A\nB| ).
cl_abap_unit_assert=>assert_equals( act = cl_http_utility=>unescape_url( 'A%0DB' ) exp = |A\rB| ).
cl_abap_unit_assert=>assert_equals( act = cl_http_utility=>unescape_url( 'A%B' ) exp = `` ).
cl_abap_unit_assert=>assert_equals( act = cl_http_utility=>unescape_url( 'A+B' ) exp = `A B` ).
cl_abap_unit_assert=>assert_equals( act = cl_http_utility=>unescape_url( |A\nB| ) exp = |AB| ).
cl_abap_unit_assert=>assert_equals( act = cl_http_utility=>unescape_url( |A\rB| ) exp = |AB| ).
ENDMETHOD.
METHOD classic.
cl_abap_unit_assert=>assert_equals( act = cl_http_utility=>unescape_url( 'Aa%20%22%25%26%3D%2F' ) exp = `Aa "%&=/` ).
ENDMETHOD.
ENDCLASS.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment