@@ -70,7 +70,9 @@ public void library() {
7070 "lastIndexOf" ,
7171 "lowerAscii" ,
7272 "replace" ,
73+ "reverse" ,
7374 "split" ,
75+ "strings.quote" ,
7476 "substring" ,
7577 "trim" ,
7678 "upperAscii" );
@@ -1467,6 +1469,100 @@ public void stringExtension_functionSubset_success() throws Exception {
14671469 assertThat (evaluatedResult ).isEqualTo (true );
14681470 }
14691471
1472+ @ Test
1473+ @ TestParameters ("{string: 'abcd', expectedResult: 'dcba'}" )
1474+ @ TestParameters ("{string: '', expectedResult: ''}" )
1475+ @ TestParameters ("{string: 'a', expectedResult: 'a'}" )
1476+ @ TestParameters ("{string: 'hello world', expectedResult: 'dlrow olleh'}" )
1477+ @ TestParameters ("{string: 'ab가cd', expectedResult: 'dc가ba'}" )
1478+ public void reverse_success (String string , String expectedResult ) throws Exception {
1479+ CelAbstractSyntaxTree ast = COMPILER .compile ("s.reverse()" ).getAst ();
1480+ CelRuntime .Program program = RUNTIME .createProgram (ast );
1481+
1482+ Object evaluatedResult = program .eval (ImmutableMap .of ("s" , string ));
1483+
1484+ assertThat (evaluatedResult ).isEqualTo (expectedResult );
1485+ }
1486+
1487+ @ Test
1488+ @ TestParameters ("{string: '😁😑😦', expectedResult: '😦😑😁'}" )
1489+ @ TestParameters (
1490+ "{string: '\u180e \u200b \u200c \u200d \u2060 \ufeff ', expectedResult:"
1491+ + " '\ufeff \u2060 \u200d \u200c \u200b \u180e '}" )
1492+ public void reverse_unicode (String string , String expectedResult ) throws Exception {
1493+ CelAbstractSyntaxTree ast = COMPILER .compile ("s.reverse()" ).getAst ();
1494+ CelRuntime .Program program = RUNTIME .createProgram (ast );
1495+
1496+ Object evaluatedResult = program .eval (ImmutableMap .of ("s" , string ));
1497+
1498+ assertThat (evaluatedResult ).isEqualTo (expectedResult );
1499+ }
1500+
1501+ @ Test
1502+ @ TestParameters ("{string: 'hello', expectedResult: '\" hello\" '}" )
1503+ @ TestParameters ("{string: '', expectedResult: '\" \" '}" )
1504+ @ TestParameters (
1505+ "{string: 'contains \\ \" quotes\\ \" ', expectedResult: '\" contains \\ \\ \\ \" quotes\\ \\ \\ \" \" '}" )
1506+ @ TestParameters ("{string: 'ends with \\ \\ ', expectedResult: '\" ends with \\ \\ \\ \\ \" '}" )
1507+ @ TestParameters ("{string: '\\ \\ starts with', expectedResult: '\" \\ \\ \\ \\ starts with\" '}" )
1508+ public void quote_success (String string , String expectedResult ) throws Exception {
1509+ CelAbstractSyntaxTree ast = COMPILER .compile ("strings.quote(s)" ).getAst ();
1510+ CelRuntime .Program program = RUNTIME .createProgram (ast );
1511+
1512+ Object evaluatedResult = program .eval (ImmutableMap .of ("s" , string ));
1513+
1514+ assertThat (evaluatedResult ).isEqualTo (expectedResult );
1515+ }
1516+
1517+ @ Test
1518+ public void quote_singleWithDoubleQuotes () throws Exception {
1519+ String expr = "strings.quote('single-quote with \" double quote\" ')" ;
1520+ String expected = "\" \\ \" single-quote with \\ \\ \\ \" double quote\\ \\ \\ \" \\ \" \" " ;
1521+ CelAbstractSyntaxTree ast = COMPILER .compile (expr + " == " + expected ).getAst ();
1522+ CelRuntime .Program program = RUNTIME .createProgram (ast );
1523+
1524+ Object evaluatedResult = program .eval ();
1525+
1526+ assertThat (evaluatedResult ).isEqualTo (true );
1527+ }
1528+
1529+ @ Test
1530+ public void quote_escapesSpecialCharacters () throws Exception {
1531+ CelAbstractSyntaxTree ast = COMPILER .compile ("strings.quote(s)" ).getAst ();
1532+ CelRuntime .Program program = RUNTIME .createProgram (ast );
1533+
1534+ Object evaluatedResult =
1535+ program .eval (
1536+ ImmutableMap .of ("s" , "\u0007 bell\u000B vtab\b back\f feed\r ret\n line\t tab\\ slash 가 😁" ));
1537+
1538+ assertThat (evaluatedResult )
1539+ .isEqualTo ("\" \\ abell\\ vvtab\\ bback\\ ffeed\\ rret\\ nline\\ ttab\\ \\ slash 가 😁\" " );
1540+ }
1541+
1542+ @ Test
1543+ public void quote_escapesMalformed_endWithHighSurrogate () throws Exception {
1544+ CelRuntime .Program program =
1545+ RUNTIME .createProgram (COMPILER .compile ("strings.quote(s)" ).getAst ());
1546+ assertThat (program .eval (ImmutableMap .of ("s" , "end with high surrogate \uD83D " )))
1547+ .isEqualTo ("\" end with high surrogate \uFFFD \" " );
1548+ }
1549+
1550+ @ Test
1551+ public void quote_escapesMalformed_unpairedHighSurrogate () throws Exception {
1552+ CelRuntime .Program program =
1553+ RUNTIME .createProgram (COMPILER .compile ("strings.quote(s)" ).getAst ());
1554+ assertThat (program .eval (ImmutableMap .of ("s" , "bad pair \uD83D A" )))
1555+ .isEqualTo ("\" bad pair \uFFFD A\" " );
1556+ }
1557+
1558+ @ Test
1559+ public void quote_escapesMalformed_unpairedLowSurrogate () throws Exception {
1560+ CelRuntime .Program program =
1561+ RUNTIME .createProgram (COMPILER .compile ("strings.quote(s)" ).getAst ());
1562+ assertThat (program .eval (ImmutableMap .of ("s" , "bad pair \uDC00 A" )))
1563+ .isEqualTo ("\" bad pair \uFFFD A\" " );
1564+ }
1565+
14701566 @ Test
14711567 public void stringExtension_compileUnallowedFunction_throws () {
14721568 CelCompiler celCompiler =
0 commit comments