2626import org .springframework .expression .spel .standard .SpelExpression ;
2727
2828import static org .assertj .core .api .Assertions .assertThat ;
29+ import static org .springframework .expression .spel .SpelMessage .MAX_CONCATENATED_STRING_LENGTH_EXCEEDED ;
2930import static org .springframework .expression .spel .SpelMessage .MAX_REPEATED_TEXT_SIZE_EXCEEDED ;
3031
3132/**
@@ -391,11 +392,7 @@ void plus() {
391392 evaluate ("3.0f + 5.0f" , 8.0f , Float .class );
392393 evaluate ("3.0d + 5.0d" , 8.0d , Double .class );
393394 evaluate ("3 + new java.math.BigDecimal('5')" , new BigDecimal ("8" ), BigDecimal .class );
394-
395- evaluate ("'ab' + 2" , "ab2" , String .class );
396- evaluate ("2 + 'a'" , "2a" , String .class );
397- evaluate ("'ab' + null" , "abnull" , String .class );
398- evaluate ("null + 'ab'" , "nullab" , String .class );
395+ evaluate ("5 + new Integer('37')" , 42 , Integer .class );
399396
400397 // AST:
401398 SpelExpression expr = (SpelExpression ) parser .parseExpression ("+3" );
@@ -409,11 +406,6 @@ void plus() {
409406 evaluate ("+5" , 5 , Integer .class );
410407 evaluate ("+new java.math.BigDecimal('5')" , new BigDecimal ("5" ), BigDecimal .class );
411408 evaluateAndCheckError ("+'abc'" , SpelMessage .OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES );
412-
413- // string concatenation
414- evaluate ("'abc'+'def'" , "abcdef" , String .class );
415-
416- evaluate ("5 + new Integer('37')" , 42 , Integer .class );
417409 }
418410
419411 @ Test
@@ -587,6 +579,59 @@ void stringRepeat() {
587579 evaluateAndCheckError ("'a' * 257" , String .class , MAX_REPEATED_TEXT_SIZE_EXCEEDED , 4 );
588580 }
589581
582+ @ Test
583+ void stringConcatenation () {
584+ evaluate ("'' + ''" , "" , String .class );
585+ evaluate ("'' + null" , "null" , String .class );
586+ evaluate ("null + ''" , "null" , String .class );
587+ evaluate ("'ab' + null" , "abnull" , String .class );
588+ evaluate ("null + 'ab'" , "nullab" , String .class );
589+ evaluate ("'ab' + 2" , "ab2" , String .class );
590+ evaluate ("2 + 'ab'" , "2ab" , String .class );
591+ evaluate ("'abc' + 'def'" , "abcdef" , String .class );
592+
593+ // Text is big but not too big
594+ final int maxSize = 100_000 ;
595+ context .setVariable ("text1" , createString (maxSize ));
596+ Expression expr = parser .parseExpression ("#text1 + ''" );
597+ assertThat (expr .getValue (context , String .class )).hasSize (maxSize );
598+
599+ expr = parser .parseExpression ("'' + #text1" );
600+ assertThat (expr .getValue (context , String .class )).hasSize (maxSize );
601+
602+ context .setVariable ("text1" , createString (maxSize / 2 ));
603+ expr = parser .parseExpression ("#text1 + #text1" );
604+ assertThat (expr .getValue (context , String .class )).hasSize (maxSize );
605+
606+ // Text is too big
607+ context .setVariable ("text1" , createString (maxSize + 1 ));
608+ evaluateAndCheckError ("#text1 + ''" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 7 );
609+ evaluateAndCheckError ("#text1 + true" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 7 );
610+ evaluateAndCheckError ("'' + #text1" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 3 );
611+ evaluateAndCheckError ("true + #text1" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 5 );
612+
613+ context .setVariable ("text1" , createString (maxSize / 2 ));
614+ context .setVariable ("text2" , createString ((maxSize / 2 ) + 1 ));
615+ evaluateAndCheckError ("#text1 + #text2" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 7 );
616+ evaluateAndCheckError ("#text1 + #text2 + true" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 7 );
617+ evaluateAndCheckError ("#text1 + true + #text2" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 14 );
618+ evaluateAndCheckError ("true + #text1 + #text2" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 14 );
619+
620+ evaluateAndCheckError ("#text2 + #text1" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 7 );
621+ evaluateAndCheckError ("#text2 + #text1 + true" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 7 );
622+ evaluateAndCheckError ("#text2 + true + #text1" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 14 );
623+ evaluateAndCheckError ("true + #text2 + #text1" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 14 );
624+
625+ context .setVariable ("text1" , createString ((maxSize / 3 ) + 1 ));
626+ evaluateAndCheckError ("#text1 + #text1 + #text1" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 16 );
627+ evaluateAndCheckError ("(#text1 + #text1) + #text1" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 18 );
628+ evaluateAndCheckError ("#text1 + (#text1 + #text1)" , String .class , MAX_CONCATENATED_STRING_LENGTH_EXCEEDED , 7 );
629+ }
630+
631+ private static String createString (int size ) {
632+ return new String (new char [size ]);
633+ }
634+
590635 @ Test
591636 void longs () {
592637 evaluate ("3L == 4L" , false , Boolean .class );
0 commit comments