View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3;
18  
19  import static org.apache.commons.lang3.LangAssertions.assertIllegalArgumentException;
20  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotEquals;
24  import static org.junit.jupiter.api.Assertions.assertNotNull;
25  import static org.junit.jupiter.api.Assertions.assertNull;
26  import static org.junit.jupiter.api.Assertions.assertSame;
27  import static org.junit.jupiter.api.Assertions.assertThrows;
28  import static org.junit.jupiter.api.Assertions.assertTrue;
29  
30  import java.io.UnsupportedEncodingException;
31  import java.lang.reflect.Constructor;
32  import java.lang.reflect.Method;
33  import java.lang.reflect.Modifier;
34  import java.nio.CharBuffer;
35  import java.nio.charset.Charset;
36  import java.nio.charset.StandardCharsets;
37  import java.util.Arrays;
38  import java.util.Collections;
39  import java.util.Iterator;
40  import java.util.List;
41  import java.util.Locale;
42  import java.util.function.Supplier;
43  import java.util.regex.PatternSyntaxException;
44  
45  import org.apache.commons.lang3.function.Suppliers;
46  import org.apache.commons.lang3.mutable.MutableInt;
47  import org.apache.commons.lang3.text.WordUtils;
48  import org.junit.jupiter.api.Disabled;
49  import org.junit.jupiter.api.Test;
50  import org.junit.jupiter.params.ParameterizedTest;
51  import org.junit.jupiter.params.provider.CsvSource;
52  import org.junit.jupiter.params.provider.ValueSource;
53  import org.junitpioneer.jupiter.DefaultLocale;
54  import org.junitpioneer.jupiter.ReadsDefaultLocale;
55  import org.junitpioneer.jupiter.WritesDefaultLocale;
56  
57  /**
58   * Tests for methods of {@link StringUtils}
59   * which been moved to their own test classes.
60   */
61  @SuppressWarnings("deprecation") // deliberate use of deprecated code
62  class StringUtilsTest extends AbstractLangTest {
63  
64      static final String WHITESPACE;
65      static final String NON_WHITESPACE;
66      static final String HARD_SPACE;
67      static final String TRIMMABLE;
68      static final String NON_TRIMMABLE;
69  
70      static {
71          final StringBuilder ws = new StringBuilder();
72          final StringBuilder nws = new StringBuilder();
73          final String hs = String.valueOf((char) 160);
74          final StringBuilder tr = new StringBuilder();
75          final StringBuilder ntr = new StringBuilder();
76          for (int i = 0; i < Character.MAX_VALUE; i++) {
77              if (Character.isWhitespace((char) i)) {
78                  ws.append((char) i);
79                  if (i > 32) {
80                      ntr.append((char) i);
81                  }
82              } else if (i < 40) {
83                  nws.append((char) i);
84              }
85          }
86          for (int i = 0; i <= 32; i++) {
87              tr.append((char) i);
88          }
89          WHITESPACE = ws.toString();
90          NON_WHITESPACE = nws.toString();
91          HARD_SPACE = hs;
92          TRIMMABLE = tr.toString();
93          NON_TRIMMABLE = ntr.toString();
94      }
95  
96      private static final String[] ARRAY_LIST = {"foo", "bar", "baz"};
97      private static final String[] EMPTY_ARRAY_LIST = {};
98      private static final String[] NULL_ARRAY_LIST = {null};
99      private static final Object[] NULL_TO_STRING_LIST = {
100             new Object() {
101                 @Override
102                 public String toString() {
103                     return null;
104                 }
105             }
106     };
107     private static final String[] MIXED_ARRAY_LIST = {null, "", "foo"};
108     private static final Object[] MIXED_TYPE_LIST = {"foo", Long.valueOf(2L)};
109     private static final long[] LONG_PRIM_LIST = {1, 2};
110     private static final int[] INT_PRIM_LIST = {1, 2};
111     private static final byte[] BYTE_PRIM_LIST = {1, 2};
112     private static final short[] SHORT_PRIM_LIST = {1, 2};
113     private static final char[] CHAR_PRIM_LIST = {'1', '2'};
114     private static final float[] FLOAT_PRIM_LIST = {1, 2};
115     private static final double[] DOUBLE_PRIM_LIST = {1, 2};
116     private static final List<String> MIXED_STRING_LIST = Arrays.asList(null, "", "foo");
117     private static final List<Object> MIXED_TYPE_OBJECT_LIST = Arrays.<Object>asList("foo", Long.valueOf(2L));
118     private static final List<String> STRING_LIST = Arrays.asList("foo", "bar", "baz");
119     private static final List<String> EMPTY_STRING_LIST = Collections.emptyList();
120     private static final List<String> NULL_STRING_LIST = Collections.singletonList(null);
121 
122     private static final String SEPARATOR = ",";
123     private static final char SEPARATOR_CHAR = ';';
124     private static final char COMMA_SEPARATOR_CHAR = ',';
125 
126     private static final String TEXT_LIST = "foo,bar,baz";
127     private static final String TEXT_LIST_CHAR = "foo;bar;baz";
128     private static final String TEXT_LIST_NOSEP = "foobarbaz";
129 
130     private static final String FOO_UNCAP = "foo";
131     private static final String FOO_CAP = "Foo";
132 
133     private static final String SENTENCE_UNCAP = "foo bar baz";
134     private static final String SENTENCE_CAP = "Foo Bar Baz";
135 
136     private static final boolean[] EMPTY = {};
137     private static final boolean[] ARRAY_FALSE_FALSE = {false, false};
138     private static final boolean[] ARRAY_FALSE_TRUE = {false, true};
139     private static final boolean[] ARRAY_FALSE_TRUE_FALSE = {false, true, false};
140 
141     private void innerTestSplit(final char separator, final String sepStr, final char noMatch) {
142         final String msg = "Failed on separator hex(" + Integer.toHexString(separator) +
143                 "), noMatch hex(" + Integer.toHexString(noMatch) + "), sepStr(" + sepStr + ")";
144 
145         final String str = "a" + separator + "b" + separator + separator + noMatch + "c";
146         String[] res;
147         // (str, sepStr)
148         res = StringUtils.split(str, sepStr);
149         assertEquals(3, res.length, msg);
150         assertEquals("a", res[0]);
151         assertEquals("b", res[1]);
152         assertEquals(noMatch + "c", res[2]);
153 
154         final String str2 = separator + "a" + separator;
155         res = StringUtils.split(str2, sepStr);
156         assertEquals(1, res.length, msg);
157         assertEquals("a", res[0], msg);
158 
159         res = StringUtils.split(str, sepStr, -1);
160         assertEquals(3, res.length, msg);
161         assertEquals("a", res[0], msg);
162         assertEquals("b", res[1], msg);
163         assertEquals(noMatch + "c", res[2], msg);
164 
165         res = StringUtils.split(str, sepStr, 0);
166         assertEquals(3, res.length, msg);
167         assertEquals("a", res[0], msg);
168         assertEquals("b", res[1], msg);
169         assertEquals(noMatch + "c", res[2], msg);
170 
171         res = StringUtils.split(str, sepStr, 1);
172         assertEquals(1, res.length, msg);
173         assertEquals(str, res[0], msg);
174 
175         res = StringUtils.split(str, sepStr, 2);
176         assertEquals(2, res.length, msg);
177         assertEquals("a", res[0], msg);
178         assertEquals(str.substring(2), res[1], msg);
179     }
180 
181     private void innerTestSplitPreserveAllTokens(final char separator, final String sepStr, final char noMatch) {
182         final String msg = "Failed on separator hex(" + Integer.toHexString(separator) +
183                 "), noMatch hex(" + Integer.toHexString(noMatch) + "), sepStr(" + sepStr + ")";
184 
185         final String str = "a" + separator + "b" + separator + separator + noMatch + "c";
186         String[] res;
187         // (str, sepStr)
188         res = StringUtils.splitPreserveAllTokens(str, sepStr);
189         assertEquals(4, res.length, msg);
190         assertEquals("a", res[0], msg);
191         assertEquals("b", res[1], msg);
192         assertEquals("", res[2], msg);
193         assertEquals(noMatch + "c", res[3], msg);
194 
195         final String str2 = separator + "a" + separator;
196         res = StringUtils.splitPreserveAllTokens(str2, sepStr);
197         assertEquals(3, res.length, msg);
198         assertEquals("", res[0], msg);
199         assertEquals("a", res[1], msg);
200         assertEquals("", res[2], msg);
201 
202         res = StringUtils.splitPreserveAllTokens(str, sepStr, -1);
203         assertEquals(4, res.length, msg);
204         assertEquals("a", res[0], msg);
205         assertEquals("b", res[1], msg);
206         assertEquals("", res[2], msg);
207         assertEquals(noMatch + "c", res[3], msg);
208 
209         res = StringUtils.splitPreserveAllTokens(str, sepStr, 0);
210         assertEquals(4, res.length, msg);
211         assertEquals("a", res[0], msg);
212         assertEquals("b", res[1], msg);
213         assertEquals("", res[2], msg);
214         assertEquals(noMatch + "c", res[3], msg);
215 
216         res = StringUtils.splitPreserveAllTokens(str, sepStr, 1);
217         assertEquals(1, res.length, msg);
218         assertEquals(str, res[0], msg);
219 
220         res = StringUtils.splitPreserveAllTokens(str, sepStr, 2);
221         assertEquals(2, res.length, msg);
222         assertEquals("a", res[0], msg);
223         assertEquals(str.substring(2), res[1], msg);
224     }
225 
226     /**
227      * Tests {@code appendIfMissing}.
228      */
229     @Test
230     void testAppendIfMissing() {
231         assertNull(StringUtils.appendIfMissing(null, null), "appendIfMissing(null,null)");
232         assertEquals("abc", StringUtils.appendIfMissing("abc", null), "appendIfMissing(abc,null)");
233         assertEquals("xyz", StringUtils.appendIfMissing("", "xyz"), "appendIfMissing(\"\",xyz)");
234         assertEquals("abcxyz", StringUtils.appendIfMissing("abc", "xyz"), "appendIfMissing(abc,xyz)");
235         assertEquals("abcxyz", StringUtils.appendIfMissing("abcxyz", "xyz"), "appendIfMissing(abcxyz,xyz)");
236         assertEquals("aXYZxyz", StringUtils.appendIfMissing("aXYZ", "xyz"), "appendIfMissing(aXYZ,xyz)");
237 
238         assertNull(StringUtils.appendIfMissing(null, null, (CharSequence[]) null), "appendIfMissing(null,null,null)");
239         assertEquals("abc", StringUtils.appendIfMissing("abc", null, (CharSequence[]) null), "appendIfMissing(abc,null,null)");
240         assertEquals("xyz", StringUtils.appendIfMissing("", "xyz", (CharSequence[]) null), "appendIfMissing(\"\",xyz,null))");
241         assertEquals("abcxyz", StringUtils.appendIfMissing("abc", "xyz", (CharSequence) null), "appendIfMissing(abc,xyz,{null})");
242         assertEquals("abc", StringUtils.appendIfMissing("abc", "xyz", ""), "appendIfMissing(abc,xyz,\"\")");
243         assertEquals("abcxyz", StringUtils.appendIfMissing("abc", "xyz", "mno"), "appendIfMissing(abc,xyz,mno)");
244         assertEquals("abcxyz", StringUtils.appendIfMissing("abcxyz", "xyz", "mno"), "appendIfMissing(abcxyz,xyz,mno)");
245         assertEquals("abcmno", StringUtils.appendIfMissing("abcmno", "xyz", "mno"), "appendIfMissing(abcmno,xyz,mno)");
246         assertEquals("abcXYZxyz", StringUtils.appendIfMissing("abcXYZ", "xyz", "mno"), "appendIfMissing(abcXYZ,xyz,mno)");
247         assertEquals("abcMNOxyz", StringUtils.appendIfMissing("abcMNO", "xyz", "mno"), "appendIfMissing(abcMNO,xyz,mno)");
248     }
249 
250     /**
251      * Tests {@code appendIfMissingIgnoreCase}.
252      */
253     @Test
254     void testAppendIfMissingIgnoreCase() {
255         assertNull(StringUtils.appendIfMissingIgnoreCase(null, null), "appendIfMissingIgnoreCase(null,null)");
256         assertEquals("abc", StringUtils.appendIfMissingIgnoreCase("abc", null), "appendIfMissingIgnoreCase(abc,null)");
257         assertEquals("xyz", StringUtils.appendIfMissingIgnoreCase("", "xyz"), "appendIfMissingIgnoreCase(\"\",xyz)");
258         assertEquals("abcxyz", StringUtils.appendIfMissingIgnoreCase("abc", "xyz"), "appendIfMissingIgnoreCase(abc,xyz)");
259         assertEquals("abcxyz", StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz"), "appendIfMissingIgnoreCase(abcxyz,xyz)");
260         assertEquals("abcXYZ", StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz"), "appendIfMissingIgnoreCase(abcXYZ,xyz)");
261 
262         assertNull(StringUtils.appendIfMissingIgnoreCase(null, null, (CharSequence[]) null), "appendIfMissingIgnoreCase(null,null,null)");
263         assertEquals("abc", StringUtils.appendIfMissingIgnoreCase("abc", null, (CharSequence[]) null), "appendIfMissingIgnoreCase(abc,null,null)");
264         assertEquals("xyz", StringUtils.appendIfMissingIgnoreCase("", "xyz", (CharSequence[]) null), "appendIfMissingIgnoreCase(\"\",xyz,null)");
265         assertEquals("abcxyz", StringUtils.appendIfMissingIgnoreCase("abc", "xyz", (CharSequence) null), "appendIfMissingIgnoreCase(abc,xyz,{null})");
266         assertEquals("abc", StringUtils.appendIfMissingIgnoreCase("abc", "xyz", ""), "appendIfMissingIgnoreCase(abc,xyz,\"\")");
267         assertEquals("abcxyz", StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno"), "appendIfMissingIgnoreCase(abc,xyz,mno)");
268         assertEquals("abcxyz", StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno"), "appendIfMissingIgnoreCase(abcxyz,xyz,mno)");
269         assertEquals("abcmno", StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno"), "appendIfMissingIgnoreCase(abcmno,xyz,mno)");
270         assertEquals("abcXYZ", StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno"), "appendIfMissingIgnoreCase(abcXYZ,xyz,mno)");
271         assertEquals("abcMNO", StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno"), "appendIfMissingIgnoreCase(abcMNO,xyz,mno)");
272     }
273 
274     @Test
275     void testCapitalize() {
276         assertNull(StringUtils.capitalize(null));
277 
278         assertEquals("", StringUtils.capitalize(""), "capitalize(empty-string) failed");
279         assertEquals("X", StringUtils.capitalize("x"), "capitalize(single-char-string) failed");
280         assertEquals(FOO_CAP, StringUtils.capitalize(FOO_CAP), "capitalize(String) failed");
281         assertEquals(FOO_CAP, StringUtils.capitalize(FOO_UNCAP), "capitalize(string) failed");
282 
283         assertEquals("\u01C8", StringUtils.capitalize("\u01C9"), "capitalize(String) is not using TitleCase");
284 
285         // Javadoc examples
286         assertNull(StringUtils.capitalize(null));
287         assertEquals("", StringUtils.capitalize(""));
288         assertEquals("Cat", StringUtils.capitalize("cat"));
289         assertEquals("CAt", StringUtils.capitalize("cAt"));
290         assertEquals("'cat'", StringUtils.capitalize("'cat'"));
291     }
292 
293     @Test
294     void testCenter_StringInt() {
295         assertNull(StringUtils.center(null, -1));
296         assertNull(StringUtils.center(null, 4));
297         assertEquals("    ", StringUtils.center("", 4));
298         assertEquals("ab", StringUtils.center("ab", 0));
299         assertEquals("ab", StringUtils.center("ab", -1));
300         assertEquals("ab", StringUtils.center("ab", 1));
301         assertEquals("    ", StringUtils.center("", 4));
302         assertEquals(" ab ", StringUtils.center("ab", 4));
303         assertEquals("abcd", StringUtils.center("abcd", 2));
304         assertEquals(" a  ", StringUtils.center("a", 4));
305         assertEquals("  a  ", StringUtils.center("a", 5));
306     }
307 
308     @Test
309     void testCenter_StringIntChar() {
310         assertNull(StringUtils.center(null, -1, ' '));
311         assertNull(StringUtils.center(null, 4, ' '));
312         assertEquals("    ", StringUtils.center("", 4, ' '));
313         assertEquals("ab", StringUtils.center("ab", 0, ' '));
314         assertEquals("ab", StringUtils.center("ab", -1, ' '));
315         assertEquals("ab", StringUtils.center("ab", 1, ' '));
316         assertEquals("    ", StringUtils.center("", 4, ' '));
317         assertEquals(" ab ", StringUtils.center("ab", 4, ' '));
318         assertEquals("abcd", StringUtils.center("abcd", 2, ' '));
319         assertEquals(" a  ", StringUtils.center("a", 4, ' '));
320         assertEquals("  a  ", StringUtils.center("a", 5, ' '));
321         assertEquals("xxaxx", StringUtils.center("a", 5, 'x'));
322     }
323 
324     @Test
325     void testCenter_StringIntString() {
326         assertNull(StringUtils.center(null, 4, null));
327         assertNull(StringUtils.center(null, -1, " "));
328         assertNull(StringUtils.center(null, 4, " "));
329         assertEquals("    ", StringUtils.center("", 4, " "));
330         assertEquals("ab", StringUtils.center("ab", 0, " "));
331         assertEquals("ab", StringUtils.center("ab", -1, " "));
332         assertEquals("ab", StringUtils.center("ab", 1, " "));
333         assertEquals("    ", StringUtils.center("", 4, " "));
334         assertEquals(" ab ", StringUtils.center("ab", 4, " "));
335         assertEquals("abcd", StringUtils.center("abcd", 2, " "));
336         assertEquals(" a  ", StringUtils.center("a", 4, " "));
337         assertEquals("yayz", StringUtils.center("a", 4, "yz"));
338         assertEquals("yzyayzy", StringUtils.center("a", 7, "yz"));
339         assertEquals("  abc  ", StringUtils.center("abc", 7, null));
340         assertEquals("  abc  ", StringUtils.center("abc", 7, ""));
341     }
342 
343     @Test
344     void testChomp() {
345 
346         final String[][] chompCases = {
347                 {FOO_UNCAP + "\r\n", FOO_UNCAP},
348                 {FOO_UNCAP + "\n", FOO_UNCAP},
349                 {FOO_UNCAP + "\r", FOO_UNCAP},
350                 {FOO_UNCAP + " \r", FOO_UNCAP + " "},
351                 {FOO_UNCAP, FOO_UNCAP},
352                 {FOO_UNCAP + "\n\n", FOO_UNCAP + "\n"},
353                 {FOO_UNCAP + "\r\n\r\n", FOO_UNCAP + "\r\n"},
354                 {"foo\nfoo", "foo\nfoo"},
355                 {"foo\n\rfoo", "foo\n\rfoo"},
356                 {"\n", ""},
357                 {"\r", ""},
358                 {"a", "a"},
359                 {"\r\n", ""},
360                 {"", ""},
361                 {null, null},
362                 {FOO_UNCAP + "\n\r", FOO_UNCAP + "\n"}
363         };
364         for (final String[] chompCase : chompCases) {
365             final String original = chompCase[0];
366             final String expectedResult = chompCase[1];
367             assertEquals(expectedResult, StringUtils.chomp(original), "chomp(String) failed");
368         }
369 
370         assertEquals("foo", StringUtils.chomp("foobar", "bar"), "chomp(String, String) failed");
371         assertEquals("foobar", StringUtils.chomp("foobar", "baz"), "chomp(String, String) failed");
372         assertEquals("foo", StringUtils.chomp("foo", "foooo"), "chomp(String, String) failed");
373         assertEquals("foobar", StringUtils.chomp("foobar", ""), "chomp(String, String) failed");
374         assertEquals("foobar", StringUtils.chomp("foobar", null), "chomp(String, String) failed");
375         assertEquals("", StringUtils.chomp("", "foo"), "chomp(String, String) failed");
376         assertEquals("", StringUtils.chomp("", null), "chomp(String, String) failed");
377         assertEquals("", StringUtils.chomp("", ""), "chomp(String, String) failed");
378         assertNull(StringUtils.chomp(null, "foo"), "chomp(String, String) failed");
379         assertNull(StringUtils.chomp(null, null), "chomp(String, String) failed");
380         assertNull(StringUtils.chomp(null, ""), "chomp(String, String) failed");
381         assertEquals("", StringUtils.chomp("foo", "foo"), "chomp(String, String) failed");
382         assertEquals(" ", StringUtils.chomp(" foo", "foo"), "chomp(String, String) failed");
383         assertEquals("foo ", StringUtils.chomp("foo ", "foo"), "chomp(String, String) failed");
384     }
385 
386     @Test
387     void testChop() {
388 
389         final String[][] chopCases = {
390                 {FOO_UNCAP + "\r\n", FOO_UNCAP},
391                 {FOO_UNCAP + "\n", FOO_UNCAP},
392                 {FOO_UNCAP + "\r", FOO_UNCAP},
393                 {FOO_UNCAP + " \r", FOO_UNCAP + " "},
394                 {"foo", "fo"},
395                 {"foo\nfoo", "foo\nfo"},
396                 {"\n", ""},
397                 {"\r", ""},
398                 {"\r\n", ""},
399                 {null, null},
400                 {"", ""},
401                 {"a", ""},
402                 // U+1F600: a trailing supplementary code point must be dropped whole, not split into a lone surrogate
403                 {"\uD83D\uDE00", ""},
404                 {"x\uD83D\uDE00", "x"},
405                 {"\uD83D\uDE00x", "\uD83D\uDE00"},
406         };
407         for (final String[] chopCase : chopCases) {
408             final String original = chopCase[0];
409             final String expectedResult = chopCase[1];
410             assertEquals(expectedResult, StringUtils.chop(original), "chop(String) failed");
411         }
412     }
413 
414     @Test
415     void testConstructor() {
416         assertNotNull(new StringUtils());
417         final Constructor<?>[] cons = StringUtils.class.getDeclaredConstructors();
418         assertEquals(1, cons.length);
419         assertTrue(Modifier.isPublic(cons[0].getModifiers()));
420         assertTrue(Modifier.isPublic(StringUtils.class.getModifiers()));
421         assertFalse(Modifier.isFinal(StringUtils.class.getModifiers()));
422     }
423 
424     @Test
425     void testDefault_String() {
426         assertEquals("", StringUtils.defaultString(null));
427         assertEquals("", StringUtils.defaultString(""));
428         assertEquals("abc", StringUtils.defaultString("abc"));
429     }
430 
431     @Test
432     void testDefault_StringString() {
433         assertEquals("NULL", StringUtils.defaultString(null, "NULL"));
434         assertEquals("", StringUtils.defaultString("", "NULL"));
435         assertEquals("abc", StringUtils.defaultString("abc", "NULL"));
436     }
437 
438     @Test
439     void testDefaultIfBlank_CharBuffers() {
440         assertEquals("NULL", StringUtils.defaultIfBlank(CharBuffer.wrap(""), CharBuffer.wrap("NULL")).toString());
441         assertEquals("NULL", StringUtils.defaultIfBlank(CharBuffer.wrap(" "), CharBuffer.wrap("NULL")).toString());
442         assertEquals("abc", StringUtils.defaultIfBlank(CharBuffer.wrap("abc"), CharBuffer.wrap("NULL")).toString());
443         assertNull(StringUtils.defaultIfBlank(CharBuffer.wrap(""), (CharBuffer) null));
444         // Tests compatibility for the API return type
445         final CharBuffer s = StringUtils.defaultIfBlank(CharBuffer.wrap("abc"), CharBuffer.wrap("NULL"));
446         assertEquals("abc", s.toString());
447     }
448 
449     @Test
450     void testDefaultIfBlank_StringBuffers() {
451         assertEquals("NULL", StringUtils.defaultIfBlank(new StringBuffer(""), new StringBuffer("NULL")).toString());
452         assertEquals("NULL", StringUtils.defaultIfBlank(new StringBuffer(" "), new StringBuffer("NULL")).toString());
453         assertEquals("abc", StringUtils.defaultIfBlank(new StringBuffer("abc"), new StringBuffer("NULL")).toString());
454         assertNull(StringUtils.defaultIfBlank(new StringBuffer(""), (StringBuffer) null));
455         // Tests compatibility for the API return type
456         final StringBuffer s = StringUtils.defaultIfBlank(new StringBuffer("abc"), new StringBuffer("NULL"));
457         assertEquals("abc", s.toString());
458     }
459 
460     @Test
461     void testDefaultIfBlank_StringBuilders() {
462         assertEquals("NULL", StringUtils.defaultIfBlank(new StringBuilder(""), new StringBuilder("NULL")).toString());
463         assertEquals("NULL", StringUtils.defaultIfBlank(new StringBuilder(" "), new StringBuilder("NULL")).toString());
464         assertEquals("abc", StringUtils.defaultIfBlank(new StringBuilder("abc"), new StringBuilder("NULL")).toString());
465         assertNull(StringUtils.defaultIfBlank(new StringBuilder(""), (StringBuilder) null));
466         // Tests compatibility for the API return type
467         final StringBuilder s = StringUtils.defaultIfBlank(new StringBuilder("abc"), new StringBuilder("NULL"));
468         assertEquals("abc", s.toString());
469     }
470 
471     @Test
472     void testDefaultIfBlank_StringString() {
473         assertEquals("NULL", StringUtils.defaultIfBlank(null, "NULL"));
474         assertEquals("NULL", StringUtils.defaultIfBlank("", "NULL"));
475         assertEquals("NULL", StringUtils.defaultIfBlank(" ", "NULL"));
476         assertEquals("abc", StringUtils.defaultIfBlank("abc", "NULL"));
477         assertNull(StringUtils.defaultIfBlank("", (String) null));
478         // Tests compatibility for the API return type
479         final String s = StringUtils.defaultIfBlank("abc", "NULL");
480         assertEquals("abc", s);
481     }
482 
483     @Test
484     void testDefaultIfEmpty_CharBuffers() {
485         assertEquals("NULL", StringUtils.defaultIfEmpty(CharBuffer.wrap(""), CharBuffer.wrap("NULL")).toString());
486         assertEquals("abc", StringUtils.defaultIfEmpty(CharBuffer.wrap("abc"), CharBuffer.wrap("NULL")).toString());
487         assertNull(StringUtils.defaultIfEmpty(CharBuffer.wrap(""), (CharBuffer) null));
488         // Tests compatibility for the API return type
489         final CharBuffer s = StringUtils.defaultIfEmpty(CharBuffer.wrap("abc"), CharBuffer.wrap("NULL"));
490         assertEquals("abc", s.toString());
491     }
492 
493     @Test
494     void testDefaultIfEmpty_StringBuffers() {
495         assertEquals("NULL", StringUtils.defaultIfEmpty(new StringBuffer(""), new StringBuffer("NULL")).toString());
496         assertEquals("abc", StringUtils.defaultIfEmpty(new StringBuffer("abc"), new StringBuffer("NULL")).toString());
497         assertNull(StringUtils.defaultIfEmpty(new StringBuffer(""), (StringBuffer) null));
498         // Tests compatibility for the API return type
499         final StringBuffer s = StringUtils.defaultIfEmpty(new StringBuffer("abc"), new StringBuffer("NULL"));
500         assertEquals("abc", s.toString());
501     }
502 
503     @Test
504     void testDefaultIfEmpty_StringBuilders() {
505         assertEquals("NULL", StringUtils.defaultIfEmpty(new StringBuilder(""), new StringBuilder("NULL")).toString());
506         assertEquals("abc", StringUtils.defaultIfEmpty(new StringBuilder("abc"), new StringBuilder("NULL")).toString());
507         assertNull(StringUtils.defaultIfEmpty(new StringBuilder(""), (StringBuilder) null));
508         // Tests compatibility for the API return type
509         final StringBuilder s = StringUtils.defaultIfEmpty(new StringBuilder("abc"), new StringBuilder("NULL"));
510         assertEquals("abc", s.toString());
511     }
512 
513     @Test
514     void testDefaultIfEmpty_StringString() {
515         assertEquals("NULL", StringUtils.defaultIfEmpty(null, "NULL"));
516         assertEquals("NULL", StringUtils.defaultIfEmpty("", "NULL"));
517         assertEquals("abc", StringUtils.defaultIfEmpty("abc", "NULL"));
518         assertNull(StringUtils.getIfEmpty("", null));
519         // Tests compatibility for the API return type
520         final String s = StringUtils.defaultIfEmpty("abc", "NULL");
521         assertEquals("abc", s);
522     }
523 
524     @Test
525     void testDeleteWhitespace_String() {
526         assertNull(StringUtils.deleteWhitespace(null));
527         assertEquals("", StringUtils.deleteWhitespace(""));
528         assertEquals("", StringUtils.deleteWhitespace("  \u000C  \t\t\u001F\n\n \u000B  "));
529         assertEquals("", StringUtils.deleteWhitespace(StringUtilsTest.WHITESPACE));
530         assertEquals(StringUtilsTest.NON_WHITESPACE, StringUtils.deleteWhitespace(StringUtilsTest.NON_WHITESPACE));
531         // Note: u-2007 and u-000A both cause problems in the source code
532         // it should ignore 2007 but delete 000A
533         assertEquals("\u00A0\u202F", StringUtils.deleteWhitespace("  \u00A0  \t\t\n\n \u202F  "));
534         assertEquals("\u00A0\u202F", StringUtils.deleteWhitespace("\u00A0\u202F"));
535         assertEquals("test", StringUtils.deleteWhitespace("\u000Bt  \t\n\u0009e\rs\n\n   \tt"));
536     }
537 
538     @Test
539     void testDifference_StringString() {
540         assertNull(StringUtils.difference(null, null));
541         assertEquals("", StringUtils.difference("", ""));
542         assertEquals("abc", StringUtils.difference("", "abc"));
543         assertEquals("", StringUtils.difference("abc", ""));
544         assertEquals("i am a robot", StringUtils.difference(null, "i am a robot"));
545         assertEquals("i am a machine", StringUtils.difference("i am a machine", null));
546         assertEquals("robot", StringUtils.difference("i am a machine", "i am a robot"));
547         assertEquals("", StringUtils.difference("abc", "abc"));
548         assertEquals("you are a robot", StringUtils.difference("i am a robot", "you are a robot"));
549         // 0x10400 and 0x10401 share the same high surrogate; the difference must not begin with a lone low surrogate
550         final String cp10400 = new String(Character.toChars(0x10400));
551         final String cp10401 = new String(Character.toChars(0x10401));
552         assertEquals(cp10401, StringUtils.difference(cp10400, cp10401));
553         assertEquals("Y", StringUtils.difference(cp10400 + "X", cp10400 + "Y"));
554     }
555 
556     @Test
557     void testDifferenceAt_StringArray() {
558         assertEquals(-1, StringUtils.indexOfDifference((String[]) null));
559         assertEquals(-1, StringUtils.indexOfDifference());
560         assertEquals(-1, StringUtils.indexOfDifference("abc"));
561         assertEquals(-1, StringUtils.indexOfDifference(null, null));
562         assertEquals(-1, StringUtils.indexOfDifference("", ""));
563         assertEquals(0, StringUtils.indexOfDifference("", null));
564         assertEquals(0, StringUtils.indexOfDifference("abc", null, null));
565         assertEquals(0, StringUtils.indexOfDifference(null, null, "abc"));
566         assertEquals(0, StringUtils.indexOfDifference("", "abc"));
567         assertEquals(0, StringUtils.indexOfDifference("abc", ""));
568         assertEquals(-1, StringUtils.indexOfDifference("abc", "abc"));
569         assertEquals(1, StringUtils.indexOfDifference("abc", "a"));
570         assertEquals(2, StringUtils.indexOfDifference("ab", "abxyz"));
571         assertEquals(2, StringUtils.indexOfDifference("abcde", "abxyz"));
572         assertEquals(0, StringUtils.indexOfDifference("abcde", "xyz"));
573         assertEquals(0, StringUtils.indexOfDifference("xyz", "abcde"));
574         assertEquals(7, StringUtils.indexOfDifference("i am a machine", "i am a robot"));
575         // a difference that falls inside a shared surrogate pair is reported at the start of the pair, not mid-pair
576         final String cp10400 = new String(Character.toChars(0x10400));
577         final String cp10401 = new String(Character.toChars(0x10401));
578         assertEquals(0, StringUtils.indexOfDifference(new String[] {cp10400, cp10401}));
579         assertEquals(2, StringUtils.indexOfDifference(new String[] {cp10400 + "X", cp10400 + "Y"}));
580     }
581 
582     @Test
583     void testDifferenceAt_StringString() {
584         assertEquals(-1, StringUtils.indexOfDifference(null, null));
585         assertEquals(0, StringUtils.indexOfDifference(null, "i am a robot"));
586         assertEquals(-1, StringUtils.indexOfDifference("", ""));
587         assertEquals(0, StringUtils.indexOfDifference("", "abc"));
588         assertEquals(0, StringUtils.indexOfDifference("abc", ""));
589         assertEquals(0, StringUtils.indexOfDifference("i am a machine", null));
590         assertEquals(7, StringUtils.indexOfDifference("i am a machine", "i am a robot"));
591         assertEquals(-1, StringUtils.indexOfDifference("foo", "foo"));
592         assertEquals(0, StringUtils.indexOfDifference("i am a robot", "you are a robot"));
593         // a difference that falls inside a shared surrogate pair is reported at the start of the pair, not mid-pair
594         final String cp10400 = new String(Character.toChars(0x10400));
595         final String cp10401 = new String(Character.toChars(0x10401));
596         assertEquals(0, StringUtils.indexOfDifference(cp10400, cp10401));
597         assertEquals(2, StringUtils.indexOfDifference(cp10400 + "X", cp10400 + "Y"));
598     }
599 
600     /**
601      * A sanity check for {@link StringUtils#EMPTY}.
602      */
603     @Test
604     void testEMPTY() {
605         assertNotNull(StringUtils.EMPTY);
606         assertEquals("", StringUtils.EMPTY);
607         assertEquals(0, StringUtils.EMPTY.length());
608     }
609 
610     @Test
611     void testEscapeSurrogatePairs() {
612         assertEquals("\uD83D\uDE30", StringEscapeUtils.escapeCsv("\uD83D\uDE30"));
613         // Examples from https://en.wikipedia.org/wiki/UTF-16
614         assertEquals("\uD800\uDC00", StringEscapeUtils.escapeCsv("\uD800\uDC00"));
615         assertEquals("\uD834\uDD1E", StringEscapeUtils.escapeCsv("\uD834\uDD1E"));
616         assertEquals("\uDBFF\uDFFD", StringEscapeUtils.escapeCsv("\uDBFF\uDFFD"));
617         assertEquals("\uDBFF\uDFFD", StringEscapeUtils.escapeHtml3("\uDBFF\uDFFD"));
618         assertEquals("\uDBFF\uDFFD", StringEscapeUtils.escapeHtml4("\uDBFF\uDFFD"));
619         assertEquals("\uDBFF\uDFFD", StringEscapeUtils.escapeXml("\uDBFF\uDFFD"));
620     }
621 
622     /**
623      * Tests LANG-858.
624      */
625     @Test
626     void testEscapeSurrogatePairsLang858() {
627         assertEquals("\\uDBFF\\uDFFD", StringEscapeUtils.escapeJava("\uDBFF\uDFFD"));       //fail LANG-858
628         assertEquals("\\uDBFF\\uDFFD", StringEscapeUtils.escapeEcmaScript("\uDBFF\uDFFD")); //fail LANG-858
629     }
630 
631     @Test
632     void testGeorgianSample() {
633         final char[] arrayI = {
634                 //Latin Small Letter dotless I
635                 (char) 0x0131,
636                 //Greek Capital Letter Theta
637                 (char) 0x03F4
638         };
639         final char[] arrayJ = {
640                 //Latin Capital Letter I with dot above
641                 (char) 0x0130,
642                 //Greek Theta Symbol
643                 (char) 0x03D1
644         };
645         for (final char i : arrayI) {
646             for (final char j : arrayJ) {
647                 final String si = String.valueOf(i);
648                 final String sj = String.valueOf(j);
649                 final boolean res1 = si.equalsIgnoreCase(sj);
650                 final CharSequence ci = new StringBuilder(si);
651                 final CharSequence cj = new StringBuilder(sj);
652                 boolean res2 = StringUtils.startsWithIgnoreCase(ci, cj);
653                 assertEquals(res1, res2, "si : " + si + " sj : " + sj);
654                 res2 = StringUtils.endsWithIgnoreCase(ci, cj);
655                 assertEquals(res1, res2, "si : " + si + " sj : " + sj);
656                 res2 = StringUtils.compareIgnoreCase(ci.toString(), cj.toString()) == 0;
657                 assertEquals(res1, res2, "si : " + si + " sj : " + sj);
658                 res2 = StringUtils.indexOfIgnoreCase(ci.toString(), cj.toString()) == 0;
659                 assertEquals(res1, res2, "si : " + si + " sj : " + sj);
660                 res2 = StringUtils.lastIndexOfIgnoreCase(ci.toString(), cj.toString()) == 0;
661                 assertEquals(res1, res2, "si : " + si + " sj : " + sj);
662             }
663         }
664     }
665 
666     @Test
667     void testGetBytes_Charset() {
668         assertEquals(ArrayUtils.EMPTY_BYTE_ARRAY, StringUtils.getBytes(null, (Charset) null));
669         assertArrayEquals(StringUtils.EMPTY.getBytes(), StringUtils.getBytes(StringUtils.EMPTY, (Charset) null));
670         assertArrayEquals(StringUtils.EMPTY.getBytes(StandardCharsets.US_ASCII),
671             StringUtils.getBytes(StringUtils.EMPTY, StandardCharsets.US_ASCII));
672     }
673 
674     @Test
675     void testGetBytes_String() throws UnsupportedEncodingException {
676         assertEquals(ArrayUtils.EMPTY_BYTE_ARRAY, StringUtils.getBytes(null, (String) null));
677         assertArrayEquals(StringUtils.EMPTY.getBytes(), StringUtils.getBytes(StringUtils.EMPTY, (String) null));
678         assertArrayEquals(StringUtils.EMPTY.getBytes(StandardCharsets.US_ASCII.name()),
679             StringUtils.getBytes(StringUtils.EMPTY, StandardCharsets.US_ASCII.name()));
680     }
681 
682     @Test
683     void testGetCommonPrefix_StringArray() {
684         assertEquals("", StringUtils.getCommonPrefix((String[]) null));
685         assertEquals("", StringUtils.getCommonPrefix());
686         assertEquals("abc", StringUtils.getCommonPrefix("abc"));
687         assertEquals("", StringUtils.getCommonPrefix(null, null));
688         assertEquals("", StringUtils.getCommonPrefix("", ""));
689         assertEquals("", StringUtils.getCommonPrefix("", null));
690         assertEquals("", StringUtils.getCommonPrefix("abc", null, null));
691         assertEquals("", StringUtils.getCommonPrefix(null, null, "abc"));
692         assertEquals("", StringUtils.getCommonPrefix("", "abc"));
693         assertEquals("", StringUtils.getCommonPrefix("abc", ""));
694         assertEquals("abc", StringUtils.getCommonPrefix("abc", "abc"));
695         assertEquals("a", StringUtils.getCommonPrefix("abc", "a"));
696         assertEquals("ab", StringUtils.getCommonPrefix("ab", "abxyz"));
697         assertEquals("ab", StringUtils.getCommonPrefix("abcde", "abxyz"));
698         assertEquals("", StringUtils.getCommonPrefix("abcde", "xyz"));
699         assertEquals("", StringUtils.getCommonPrefix("xyz", "abcde"));
700         assertEquals("i am a ", StringUtils.getCommonPrefix("i am a machine", "i am a robot"));
701         // 0x10400 and 0x10401 share the high surrogate but differ; the common prefix must not be a lone high surrogate
702         final String cp10400 = new String(Character.toChars(0x10400));
703         final String cp10401 = new String(Character.toChars(0x10401));
704         assertEquals("", StringUtils.getCommonPrefix(cp10400, cp10401));
705         assertEquals(cp10400, StringUtils.getCommonPrefix(cp10400 + "X", cp10400 + "Y"));
706     }
707 
708     @Test
709     void testGetDigits() {
710         assertNull(StringUtils.getDigits(null));
711         assertEquals("", StringUtils.getDigits(""));
712         assertEquals("", StringUtils.getDigits("abc"));
713         assertEquals("1000", StringUtils.getDigits("1000$"));
714         assertEquals("12345", StringUtils.getDigits("123password45"));
715         assertEquals("5417543010", StringUtils.getDigits("(541) 754-3010"));
716         assertEquals("\u0967\u0968\u0969", StringUtils.getDigits("\u0967\u0968\u0969"));
717     }
718 
719     @Test
720     void testGetDigitsKeycaps() {
721         assertEquals("0123456789", StringUtils.getDigits("0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣#️⃣"));
722     }
723 
724     @Test
725     void testGetDigitsSupplementary() {
726         // U+1D7CF MATHEMATICAL BOLD DIGIT ONE: Character.isDigit is true but it is a surrogate pair
727         final String mathOne = new String(Character.toChars(0x1D7CF));
728         assertEquals(mathOne, StringUtils.getDigits(mathOne));
729         assertEquals(mathOne + "9", StringUtils.getDigits("a" + mathOne + "9"));
730     }
731 
732     @Test
733     void testGetFuzzyDistance() {
734         assertEquals(0, StringUtils.getFuzzyDistance("", "", Locale.ENGLISH));
735         assertEquals(0, StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH));
736         assertEquals(1, StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH));
737         assertEquals(1, StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH));
738         assertEquals(2, StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH));
739         assertEquals(4, StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH));
740         assertEquals(3, StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH));
741     }
742 
743     @Test
744     void testGetFuzzyDistance_NullNullNull() {
745         assertIllegalArgumentException(() -> StringUtils.getFuzzyDistance(null, null, null));
746     }
747 
748     @Test
749     void testGetFuzzyDistance_NullStringLocale() {
750         assertIllegalArgumentException(() -> StringUtils.getFuzzyDistance(null, "clear", Locale.ENGLISH));
751     }
752 
753     @Test
754     void testGetFuzzyDistance_StringNullLoclae() {
755         assertIllegalArgumentException(() -> StringUtils.getFuzzyDistance(" ", null, Locale.ENGLISH));
756     }
757 
758     @Test
759     void testGetFuzzyDistance_StringStringNull() {
760         assertIllegalArgumentException(() -> StringUtils.getFuzzyDistance(" ", "clear", null));
761     }
762 
763     @Test
764     void testGetIfBlank_StringStringSupplier() {
765         assertEquals("NULL", StringUtils.getIfBlank(null, () -> "NULL"));
766         assertEquals("NULL", StringUtils.getIfBlank("",  () -> "NULL"));
767         assertEquals("NULL", StringUtils.getIfBlank(" ", () -> "NULL"));
768         assertEquals("abc", StringUtils.getIfBlank("abc", () -> "NULL"));
769         assertNull(StringUtils.getIfBlank("", Suppliers.nul()));
770         assertNull(StringUtils.defaultIfBlank("", (String) null));
771         // Tests compatibility for the API return type
772         final String s = StringUtils.getIfBlank("abc", () -> "NULL");
773         assertEquals("abc", s);
774         //Checking that default value supplied only on demand
775         final MutableInt numberOfCalls = new MutableInt(0);
776         final Supplier<String> countingDefaultSupplier = () -> {
777             numberOfCalls.increment();
778             return "NULL";
779         };
780         StringUtils.getIfBlank("abc", countingDefaultSupplier);
781         assertEquals(0, numberOfCalls.get());
782         StringUtils.getIfBlank("", countingDefaultSupplier);
783         assertEquals(1, numberOfCalls.get());
784         StringUtils.getIfBlank(" ", countingDefaultSupplier);
785         assertEquals(2, numberOfCalls.get());
786         StringUtils.getIfBlank(null, countingDefaultSupplier);
787         assertEquals(3, numberOfCalls.get());
788     }
789 
790     @Test
791     void testGetIfEmpty_StringStringSupplier() {
792         assertEquals("NULL", StringUtils.getIfEmpty((String) null, () -> "NULL"));
793         assertEquals("NULL", StringUtils.getIfEmpty("", () -> "NULL"));
794         assertEquals("abc", StringUtils.getIfEmpty("abc", () -> "NULL"));
795         assertNull(StringUtils.getIfEmpty("", Suppliers.nul()));
796         assertNull(StringUtils.defaultIfEmpty("", (String) null));
797         // Tests compatibility for the API return type
798         final String s = StringUtils.getIfEmpty("abc", () -> "NULL");
799         assertEquals("abc", s);
800         //Checking that default value supplied only on demand
801         final MutableInt numberOfCalls = new MutableInt(0);
802         final Supplier<String> countingDefaultSupplier = () -> {
803             numberOfCalls.increment();
804             return "NULL";
805         };
806         StringUtils.getIfEmpty("abc", countingDefaultSupplier);
807         assertEquals(0, numberOfCalls.get());
808         StringUtils.getIfEmpty("", countingDefaultSupplier);
809         assertEquals(1, numberOfCalls.get());
810         StringUtils.getIfEmpty(null, countingDefaultSupplier);
811         assertEquals(2, numberOfCalls.get());
812     }
813 
814     @Test
815     void testGetJaroWinklerDistance_NullNull() {
816         assertIllegalArgumentException(() -> StringUtils.getJaroWinklerDistance(null, null));
817     }
818 
819     @Test
820     void testGetJaroWinklerDistance_NullString() {
821         assertIllegalArgumentException(() -> StringUtils.getJaroWinklerDistance(null, "clear"));
822     }
823 
824     @Test
825     void testGetJaroWinklerDistance_StringNull() {
826         assertIllegalArgumentException(() -> StringUtils.getJaroWinklerDistance(" ", null));
827     }
828 
829     @Test
830     void testGetJaroWinklerDistance_StringString() {
831         assertEquals(0.93d, StringUtils.getJaroWinklerDistance("frog", "fog"));
832         assertEquals(0.0d, StringUtils.getJaroWinklerDistance("fly", "ant"));
833         assertEquals(0.44d, StringUtils.getJaroWinklerDistance("elephant", "hippo"));
834         assertEquals(0.84d, StringUtils.getJaroWinklerDistance("dwayne", "duane"));
835         assertEquals(0.93d, StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp"));
836         assertEquals(0.95d, StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc."));
837         assertEquals(0.92d, StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness"));
838         assertEquals(0.88d, StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA"));
839         assertEquals(0.63d, StringUtils.getJaroWinklerDistance("Haus Ingeborg", "Ingeborg Esser"));
840     }
841 
842     @Test
843     void testGetLevenshteinDistance_NullString() {
844         assertIllegalArgumentException(() -> StringUtils.getLevenshteinDistance("a", null));
845     }
846 
847     @Test
848     void testGetLevenshteinDistance_NullStringInt() {
849         assertIllegalArgumentException(() -> StringUtils.getLevenshteinDistance(null, "a", 0));
850     }
851 
852     @Test
853     void testGetLevenshteinDistance_StringNull() {
854         assertIllegalArgumentException(() -> StringUtils.getLevenshteinDistance(null, "a"));
855     }
856 
857     @Test
858     void testGetLevenshteinDistance_StringNullInt() {
859         assertIllegalArgumentException(() -> StringUtils.getLevenshteinDistance("a", null, 0));
860     }
861 
862     @Test
863     void testGetLevenshteinDistance_StringString() {
864         assertEquals(0, StringUtils.getLevenshteinDistance("", ""));
865         assertEquals(1, StringUtils.getLevenshteinDistance("", "a"));
866         assertEquals(7, StringUtils.getLevenshteinDistance("aaapppp", ""));
867         assertEquals(1, StringUtils.getLevenshteinDistance("frog", "fog"));
868         assertEquals(3, StringUtils.getLevenshteinDistance("fly", "ant"));
869         assertEquals(7, StringUtils.getLevenshteinDistance("elephant", "hippo"));
870         assertEquals(7, StringUtils.getLevenshteinDistance("hippo", "elephant"));
871         assertEquals(8, StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz"));
872         assertEquals(8, StringUtils.getLevenshteinDistance("zzzzzzzz", "hippo"));
873         assertEquals(1, StringUtils.getLevenshteinDistance("hello", "hallo"));
874     }
875 
876     @Test
877     void testGetLevenshteinDistance_StringStringInt() {
878         // empty strings
879         assertEquals(0, StringUtils.getLevenshteinDistance("", "", 0));
880         assertEquals(7, StringUtils.getLevenshteinDistance("aaapppp", "", 8));
881         assertEquals(7, StringUtils.getLevenshteinDistance("aaapppp", "", 7));
882         assertEquals(-1, StringUtils.getLevenshteinDistance("aaapppp", "", 6));
883 
884         // unequal strings, zero threshold
885         assertEquals(-1, StringUtils.getLevenshteinDistance("b", "a", 0));
886         assertEquals(-1, StringUtils.getLevenshteinDistance("a", "b", 0));
887 
888         // equal strings
889         assertEquals(0, StringUtils.getLevenshteinDistance("aa", "aa", 0));
890         assertEquals(0, StringUtils.getLevenshteinDistance("aa", "aa", 2));
891 
892         // same length
893         assertEquals(-1, StringUtils.getLevenshteinDistance("aaa", "bbb", 2));
894         assertEquals(3, StringUtils.getLevenshteinDistance("aaa", "bbb", 3));
895 
896         // big stripe
897         assertEquals(6, StringUtils.getLevenshteinDistance("aaaaaa", "b", 10));
898 
899         // distance less than threshold
900         assertEquals(7, StringUtils.getLevenshteinDistance("aaapppp", "b", 8));
901         assertEquals(3, StringUtils.getLevenshteinDistance("a", "bbb", 4));
902 
903         // distance equal to threshold
904         assertEquals(7, StringUtils.getLevenshteinDistance("aaapppp", "b", 7));
905         assertEquals(3, StringUtils.getLevenshteinDistance("a", "bbb", 3));
906 
907         // distance greater than threshold
908         assertEquals(-1, StringUtils.getLevenshteinDistance("a", "bbb", 2));
909         assertEquals(-1, StringUtils.getLevenshteinDistance("bbb", "a", 2));
910         assertEquals(-1, StringUtils.getLevenshteinDistance("aaapppp", "b", 6));
911 
912         // stripe runs off array, strings not similar
913         assertEquals(-1, StringUtils.getLevenshteinDistance("a", "bbb", 1));
914         assertEquals(-1, StringUtils.getLevenshteinDistance("bbb", "a", 1));
915 
916         // stripe runs off array, strings are similar
917         assertEquals(-1, StringUtils.getLevenshteinDistance("12345", "1234567", 1));
918         assertEquals(-1, StringUtils.getLevenshteinDistance("1234567", "12345", 1));
919 
920         // old getLevenshteinDistance test cases
921         assertEquals(1, StringUtils.getLevenshteinDistance("frog", "fog", 1));
922         assertEquals(3, StringUtils.getLevenshteinDistance("fly", "ant", 3));
923         assertEquals(7, StringUtils.getLevenshteinDistance("elephant", "hippo", 7));
924         assertEquals(-1, StringUtils.getLevenshteinDistance("elephant", "hippo", 6));
925         assertEquals(7, StringUtils.getLevenshteinDistance("hippo", "elephant", 7));
926         assertEquals(-1, StringUtils.getLevenshteinDistance("hippo", "elephant", 6));
927         assertEquals(8, StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz", 8));
928         assertEquals(8, StringUtils.getLevenshteinDistance("zzzzzzzz", "hippo", 8));
929         assertEquals(1, StringUtils.getLevenshteinDistance("hello", "hallo", 1));
930 
931         assertEquals(1, StringUtils.getLevenshteinDistance("frog", "fog", Integer.MAX_VALUE));
932         assertEquals(3, StringUtils.getLevenshteinDistance("fly", "ant", Integer.MAX_VALUE));
933         assertEquals(7, StringUtils.getLevenshteinDistance("elephant", "hippo", Integer.MAX_VALUE));
934         assertEquals(7, StringUtils.getLevenshteinDistance("hippo", "elephant", Integer.MAX_VALUE));
935         assertEquals(8, StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz", Integer.MAX_VALUE));
936         assertEquals(8, StringUtils.getLevenshteinDistance("zzzzzzzz", "hippo", Integer.MAX_VALUE));
937         assertEquals(1, StringUtils.getLevenshteinDistance("hello", "hallo", Integer.MAX_VALUE));
938     }
939 
940     @Test
941     void testGetLevenshteinDistance_StringStringNegativeInt() {
942         assertIllegalArgumentException(() -> StringUtils.getLevenshteinDistance("a", "a", -1));
943     }
944 
945     /**
946      * Test for {@link StringUtils#isAllLowerCase(CharSequence)}.
947      */
948     @Test
949     void testIsAllLowerCase() {
950         assertFalse(StringUtils.isAllLowerCase(null));
951         assertFalse(StringUtils.isAllLowerCase(StringUtils.EMPTY));
952         assertFalse(StringUtils.isAllLowerCase("  "));
953         assertTrue(StringUtils.isAllLowerCase("abc"));
954         assertFalse(StringUtils.isAllLowerCase("abc "));
955         assertFalse(StringUtils.isAllLowerCase("abc\n"));
956         assertFalse(StringUtils.isAllLowerCase("abC"));
957         assertFalse(StringUtils.isAllLowerCase("ab c"));
958         assertFalse(StringUtils.isAllLowerCase("ab1c"));
959         assertFalse(StringUtils.isAllLowerCase("ab/c"));
960     }
961 
962     /**
963      * Test for {@link StringUtils#isAllLowerCase(CharSequence)} with supplementary code points.
964      */
965     @Test
966     void testIsAllLowerCaseSupplementary() {
967         // U+10428 DESERET SMALL LETTER LONG I is a lowercase supplementary letter
968         assertTrue(StringUtils.isAllLowerCase(new String(Character.toChars(0x10428))));
969         // U+10400 DESERET CAPITAL LETTER LONG I is an uppercase supplementary letter
970         assertFalse(StringUtils.isAllLowerCase(new String(Character.toChars(0x10400))));
971     }
972 
973     /**
974      * Test for {@link StringUtils#isAllUpperCase(CharSequence)}.
975      */
976     @Test
977     void testIsAllUpperCase() {
978         assertFalse(StringUtils.isAllUpperCase(null));
979         assertFalse(StringUtils.isAllUpperCase(StringUtils.EMPTY));
980         assertFalse(StringUtils.isAllUpperCase("  "));
981         assertTrue(StringUtils.isAllUpperCase("ABC"));
982         assertFalse(StringUtils.isAllUpperCase("ABC "));
983         assertFalse(StringUtils.isAllUpperCase("ABC\n"));
984         assertFalse(StringUtils.isAllUpperCase("aBC"));
985         assertFalse(StringUtils.isAllUpperCase("A C"));
986         assertFalse(StringUtils.isAllUpperCase("A1C"));
987         assertFalse(StringUtils.isAllUpperCase("A/C"));
988     }
989 
990     /**
991      * Test for {@link StringUtils#isAllUpperCase(CharSequence)} with supplementary code points.
992      */
993     @Test
994     void testIsAllUpperCaseSupplementary() {
995         // U+10400 DESERET CAPITAL LETTER LONG I is an uppercase supplementary letter
996         assertTrue(StringUtils.isAllUpperCase(new String(Character.toChars(0x10400))));
997         // U+10428 DESERET SMALL LETTER LONG I is a lowercase supplementary letter
998         assertFalse(StringUtils.isAllUpperCase(new String(Character.toChars(0x10428))));
999     }
1000 
1001     /**
1002      * Test for {@link StringUtils#isMixedCase(CharSequence)}.
1003      */
1004     @Test
1005     void testIsMixedCase() {
1006         assertFalse(StringUtils.isMixedCase(null));
1007         assertFalse(StringUtils.isMixedCase(StringUtils.EMPTY));
1008         assertFalse(StringUtils.isMixedCase(" "));
1009         assertFalse(StringUtils.isMixedCase("A"));
1010         assertFalse(StringUtils.isMixedCase("a"));
1011         assertFalse(StringUtils.isMixedCase("/"));
1012         assertFalse(StringUtils.isMixedCase("A/"));
1013         assertFalse(StringUtils.isMixedCase("/b"));
1014         assertFalse(StringUtils.isMixedCase("abc"));
1015         assertFalse(StringUtils.isMixedCase("ABC"));
1016         assertTrue(StringUtils.isMixedCase("aBc"));
1017         assertTrue(StringUtils.isMixedCase("aBc "));
1018         assertTrue(StringUtils.isMixedCase("A c"));
1019         assertTrue(StringUtils.isMixedCase("aBc\n"));
1020         assertTrue(StringUtils.isMixedCase("A1c"));
1021         assertTrue(StringUtils.isMixedCase("a/C"));
1022     }
1023 
1024     /**
1025      * Test for {@link StringUtils#isMixedCase(CharSequence)} with supplementary code points.
1026      */
1027     @Test
1028     void testIsMixedCaseSupplementary() {
1029         // lowercase 'a' mixed with the uppercase supplementary letter U+10400
1030         assertTrue(StringUtils.isMixedCase("a" + new String(Character.toChars(0x10400))));
1031         // a single uppercase supplementary letter is not mixed case
1032         assertFalse(StringUtils.isMixedCase(new String(Character.toChars(0x10400))));
1033     }
1034 
1035     @Test
1036     void testJoin_ArrayCharSeparator() {
1037         assertNull(StringUtils.join((Object[]) null, ','));
1038         assertEquals(TEXT_LIST_CHAR, StringUtils.join(ARRAY_LIST, SEPARATOR_CHAR));
1039         assertEquals("", StringUtils.join(EMPTY_ARRAY_LIST, SEPARATOR_CHAR));
1040         assertEquals(";;foo", StringUtils.join(MIXED_ARRAY_LIST, SEPARATOR_CHAR));
1041         assertEquals("foo;2", StringUtils.join(MIXED_TYPE_LIST, SEPARATOR_CHAR));
1042 
1043         assertNull(StringUtils.join((Object[]) null, ',', 0, 1));
1044         assertEquals("/", StringUtils.join(MIXED_ARRAY_LIST, '/', 0, MIXED_ARRAY_LIST.length - 1));
1045         assertEquals("foo", StringUtils.join(MIXED_TYPE_LIST, '/', 0, 1));
1046         assertEquals("null", StringUtils.join(NULL_TO_STRING_LIST, '/', 0, 1));
1047         assertEquals("foo/2", StringUtils.join(MIXED_TYPE_LIST, '/', 0, 2));
1048         assertEquals("2", StringUtils.join(MIXED_TYPE_LIST, '/', 1, 2));
1049         assertEquals("", StringUtils.join(MIXED_TYPE_LIST, '/', 2, 1));
1050     }
1051 
1052     @Test
1053     void testJoin_ArrayOfBooleans() {
1054         assertNull(StringUtils.join((boolean[]) null, COMMA_SEPARATOR_CHAR));
1055         assertEquals("false;false", StringUtils.join(ARRAY_FALSE_FALSE, SEPARATOR_CHAR));
1056         assertEquals("", StringUtils.join(EMPTY, SEPARATOR_CHAR));
1057         assertEquals("false,true,false", StringUtils.join(ARRAY_FALSE_TRUE_FALSE, COMMA_SEPARATOR_CHAR));
1058         assertEquals("true", StringUtils.join(ARRAY_FALSE_TRUE, SEPARATOR_CHAR, 1, 2));
1059         assertNull(StringUtils.join((boolean[]) null, SEPARATOR_CHAR, 0, 1));
1060         assertEquals(StringUtils.EMPTY, StringUtils.join(ARRAY_FALSE_FALSE, SEPARATOR_CHAR, 0, 0));
1061         assertEquals(StringUtils.EMPTY, StringUtils.join(ARRAY_FALSE_TRUE_FALSE, SEPARATOR_CHAR, 1, 0));
1062     }
1063 
1064     @Test
1065     void testJoin_ArrayOfBytes() {
1066         assertNull(StringUtils.join((byte[]) null, ','));
1067         assertEquals("1;2", StringUtils.join(BYTE_PRIM_LIST, SEPARATOR_CHAR));
1068         assertEquals("2", StringUtils.join(BYTE_PRIM_LIST, SEPARATOR_CHAR, 1, 2));
1069         assertNull(StringUtils.join((byte[]) null, SEPARATOR_CHAR, 0, 1));
1070         assertEquals(StringUtils.EMPTY, StringUtils.join(BYTE_PRIM_LIST, SEPARATOR_CHAR, 0, 0));
1071         assertEquals(StringUtils.EMPTY, StringUtils.join(BYTE_PRIM_LIST, SEPARATOR_CHAR, 1, 0));
1072     }
1073 
1074     @Test
1075     void testJoin_ArrayOfChars() {
1076         assertNull(StringUtils.join((char[]) null, ','));
1077         assertEquals("1;2", StringUtils.join(CHAR_PRIM_LIST, SEPARATOR_CHAR));
1078         assertEquals("2", StringUtils.join(CHAR_PRIM_LIST, SEPARATOR_CHAR, 1, 2));
1079         assertNull(StringUtils.join((char[]) null, SEPARATOR_CHAR, 0, 1));
1080         assertEquals(StringUtils.EMPTY, StringUtils.join(CHAR_PRIM_LIST, SEPARATOR_CHAR, 0, 0));
1081         assertEquals(StringUtils.EMPTY, StringUtils.join(CHAR_PRIM_LIST, SEPARATOR_CHAR, 1, 0));
1082     }
1083 
1084     @Test
1085     void testJoin_ArrayOfDoubles() {
1086         assertNull(StringUtils.join((double[]) null, ','));
1087         assertEquals("1.0;2.0", StringUtils.join(DOUBLE_PRIM_LIST, SEPARATOR_CHAR));
1088         assertEquals("2.0", StringUtils.join(DOUBLE_PRIM_LIST, SEPARATOR_CHAR, 1, 2));
1089         assertNull(StringUtils.join((double[]) null, SEPARATOR_CHAR, 0, 1));
1090         assertEquals(StringUtils.EMPTY, StringUtils.join(DOUBLE_PRIM_LIST, SEPARATOR_CHAR, 0, 0));
1091         assertEquals(StringUtils.EMPTY, StringUtils.join(DOUBLE_PRIM_LIST, SEPARATOR_CHAR, 1, 0));
1092     }
1093 
1094     @Test
1095     void testJoin_ArrayOfFloats() {
1096         assertNull(StringUtils.join((float[]) null, ','));
1097         assertEquals("1.0;2.0", StringUtils.join(FLOAT_PRIM_LIST, SEPARATOR_CHAR));
1098         assertEquals("2.0", StringUtils.join(FLOAT_PRIM_LIST, SEPARATOR_CHAR, 1, 2));
1099         assertNull(StringUtils.join((float[]) null, SEPARATOR_CHAR, 0, 1));
1100         assertEquals(StringUtils.EMPTY, StringUtils.join(FLOAT_PRIM_LIST, SEPARATOR_CHAR, 0, 0));
1101         assertEquals(StringUtils.EMPTY, StringUtils.join(FLOAT_PRIM_LIST, SEPARATOR_CHAR, 1, 0));
1102     }
1103 
1104     @Test
1105     void testJoin_ArrayOfInts() {
1106         assertNull(StringUtils.join((int[]) null, ','));
1107         assertEquals("1;2", StringUtils.join(INT_PRIM_LIST, SEPARATOR_CHAR));
1108         assertEquals("2", StringUtils.join(INT_PRIM_LIST, SEPARATOR_CHAR, 1, 2));
1109         assertNull(StringUtils.join((int[]) null, SEPARATOR_CHAR, 0, 1));
1110         assertEquals(StringUtils.EMPTY, StringUtils.join(INT_PRIM_LIST, SEPARATOR_CHAR, 0, 0));
1111         assertEquals(StringUtils.EMPTY, StringUtils.join(INT_PRIM_LIST, SEPARATOR_CHAR, 1, 0));
1112     }
1113 
1114     @Test
1115     void testJoin_ArrayOfLongs() {
1116         assertNull(StringUtils.join((long[]) null, ','));
1117         assertEquals("1;2", StringUtils.join(LONG_PRIM_LIST, SEPARATOR_CHAR));
1118         assertEquals("2", StringUtils.join(LONG_PRIM_LIST, SEPARATOR_CHAR, 1, 2));
1119         assertNull(StringUtils.join((long[]) null, SEPARATOR_CHAR, 0, 1));
1120         assertEquals(StringUtils.EMPTY, StringUtils.join(LONG_PRIM_LIST, SEPARATOR_CHAR, 0, 0));
1121         assertEquals(StringUtils.EMPTY, StringUtils.join(LONG_PRIM_LIST, SEPARATOR_CHAR, 1, 0));
1122     }
1123 
1124     @Test
1125     void testJoin_ArrayOfShorts() {
1126         assertNull(StringUtils.join((short[]) null, ','));
1127         assertEquals("1;2", StringUtils.join(SHORT_PRIM_LIST, SEPARATOR_CHAR));
1128         assertEquals("2", StringUtils.join(SHORT_PRIM_LIST, SEPARATOR_CHAR, 1, 2));
1129         assertNull(StringUtils.join((short[]) null, SEPARATOR_CHAR, 0, 1));
1130         assertEquals(StringUtils.EMPTY, StringUtils.join(SHORT_PRIM_LIST, SEPARATOR_CHAR, 0, 0));
1131         assertEquals(StringUtils.EMPTY, StringUtils.join(SHORT_PRIM_LIST, SEPARATOR_CHAR, 1, 0));
1132     }
1133 
1134     @Test
1135     void testJoin_ArrayString_EmptyDelimiter() {
1136         assertNull(StringUtils.join((Object[]) null, null));
1137         assertEquals(TEXT_LIST_NOSEP, StringUtils.join(ARRAY_LIST, null));
1138         assertEquals(TEXT_LIST_NOSEP, StringUtils.join(ARRAY_LIST, ""));
1139 
1140         assertEquals("", StringUtils.join(NULL_ARRAY_LIST, null));
1141 
1142         assertEquals("", StringUtils.join(EMPTY_ARRAY_LIST, null));
1143         assertEquals("", StringUtils.join(EMPTY_ARRAY_LIST, ""));
1144 
1145         assertEquals("", StringUtils.join(MIXED_ARRAY_LIST, "", 0, MIXED_ARRAY_LIST.length - 1));
1146     }
1147 
1148     @ParameterizedTest
1149     @ValueSource(strings = {",", ";", Supplementary.CharU20000, Supplementary.CharU20001})
1150     void testJoin_ArrayString_NonEmptyDelimiter(final String delimiter) {
1151         assertEquals("", StringUtils.join(EMPTY_ARRAY_LIST, delimiter));
1152 
1153         assertEquals(String.join(delimiter, ARRAY_LIST), StringUtils.join(ARRAY_LIST, delimiter));
1154         assertEquals(delimiter + delimiter + "foo", StringUtils.join(MIXED_ARRAY_LIST, delimiter));
1155         assertEquals(String.join(delimiter, "foo", "2"), StringUtils.join(MIXED_TYPE_LIST, delimiter));
1156 
1157         assertEquals(delimiter, StringUtils.join(MIXED_ARRAY_LIST, delimiter, 0, MIXED_ARRAY_LIST.length - 1));
1158         assertEquals("foo", StringUtils.join(MIXED_TYPE_LIST, delimiter, 0, 1));
1159         assertEquals(String.join(delimiter, "foo", "2"), StringUtils.join(MIXED_TYPE_LIST, delimiter, 0, 2));
1160         assertEquals("2", StringUtils.join(MIXED_TYPE_LIST, delimiter, 1, 2));
1161         assertEquals("", StringUtils.join(MIXED_TYPE_LIST, delimiter, 2, 1));
1162     }
1163 
1164     @Test
1165     void testJoin_IterableChar() {
1166         assertNull(StringUtils.join((Iterable<?>) null, ','));
1167         assertEquals(TEXT_LIST_CHAR, StringUtils.join(Arrays.asList(ARRAY_LIST), SEPARATOR_CHAR));
1168         assertEquals("", StringUtils.join(Arrays.asList(NULL_ARRAY_LIST), SEPARATOR_CHAR));
1169         assertEquals("", StringUtils.join(Arrays.asList(EMPTY_ARRAY_LIST), SEPARATOR_CHAR));
1170         assertEquals("foo", StringUtils.join(Collections.singleton("foo"), 'x'));
1171     }
1172 
1173     @Test
1174     void testJoin_IterableString() {
1175         assertNull(StringUtils.join((Iterable<?>) null, null));
1176         assertEquals(TEXT_LIST_NOSEP, StringUtils.join(Arrays.asList(ARRAY_LIST), null));
1177         assertEquals(TEXT_LIST_NOSEP, StringUtils.join(Arrays.asList(ARRAY_LIST), ""));
1178         assertEquals("foo", StringUtils.join(Collections.singleton("foo"), "x"));
1179         assertEquals("foo", StringUtils.join(Collections.singleton("foo"), null));
1180 
1181         assertEquals("", StringUtils.join(Arrays.asList(NULL_ARRAY_LIST), null));
1182 
1183         assertEquals("", StringUtils.join(Arrays.asList(EMPTY_ARRAY_LIST), null));
1184         assertEquals("", StringUtils.join(Arrays.asList(EMPTY_ARRAY_LIST), ""));
1185         assertEquals("", StringUtils.join(Arrays.asList(EMPTY_ARRAY_LIST), SEPARATOR));
1186 
1187         assertEquals(TEXT_LIST, StringUtils.join(Arrays.asList(ARRAY_LIST), SEPARATOR));
1188     }
1189 
1190     @Test
1191     void testJoin_IteratorChar() {
1192         assertNull(StringUtils.join((Iterator<?>) null, ','));
1193         assertEquals(TEXT_LIST_CHAR, StringUtils.join(Arrays.asList(ARRAY_LIST).iterator(), SEPARATOR_CHAR));
1194         assertEquals("", StringUtils.join(Arrays.asList(NULL_ARRAY_LIST).iterator(), SEPARATOR_CHAR));
1195         assertEquals("", StringUtils.join(Arrays.asList(EMPTY_ARRAY_LIST).iterator(), SEPARATOR_CHAR));
1196         assertEquals("foo", StringUtils.join(Collections.singleton("foo").iterator(), 'x'));
1197         assertEquals("null", StringUtils.join(Arrays.asList(NULL_TO_STRING_LIST).iterator(), SEPARATOR_CHAR));
1198     }
1199 
1200     @Test
1201     void testJoin_IteratorString() {
1202         assertNull(StringUtils.join((Iterator<?>) null, null));
1203         assertEquals(TEXT_LIST_NOSEP, StringUtils.join(Arrays.asList(ARRAY_LIST).iterator(), null));
1204         assertEquals(TEXT_LIST_NOSEP, StringUtils.join(Arrays.asList(ARRAY_LIST).iterator(), ""));
1205         assertEquals("foo", StringUtils.join(Collections.singleton("foo").iterator(), "x"));
1206         assertEquals("foo", StringUtils.join(Collections.singleton("foo").iterator(), null));
1207 
1208         assertEquals("", StringUtils.join(Arrays.asList(NULL_ARRAY_LIST).iterator(), null));
1209 
1210         assertEquals("", StringUtils.join(Arrays.asList(EMPTY_ARRAY_LIST).iterator(), null));
1211         assertEquals("", StringUtils.join(Arrays.asList(EMPTY_ARRAY_LIST).iterator(), ""));
1212         assertEquals("", StringUtils.join(Arrays.asList(EMPTY_ARRAY_LIST).iterator(), SEPARATOR));
1213 
1214         assertEquals(TEXT_LIST, StringUtils.join(Arrays.asList(ARRAY_LIST).iterator(), SEPARATOR));
1215 
1216         assertEquals("null", StringUtils.join(Arrays.asList(NULL_TO_STRING_LIST).iterator(), SEPARATOR));
1217     }
1218 
1219     @Test
1220     void testJoin_List_CharDelimiter() {
1221         assertEquals("/", StringUtils.join(MIXED_STRING_LIST, '/', 0, MIXED_STRING_LIST.size() - 1));
1222         assertEquals("foo", StringUtils.join(MIXED_TYPE_OBJECT_LIST, '/', 0, 1));
1223         assertEquals("foo/2", StringUtils.join(MIXED_TYPE_OBJECT_LIST, '/', 0, 2));
1224         assertEquals("2", StringUtils.join(MIXED_TYPE_OBJECT_LIST, '/', 1, 2));
1225         assertEquals("", StringUtils.join(MIXED_TYPE_OBJECT_LIST, '/', 2, 1));
1226         assertNull(null, StringUtils.join((List<?>) null, '/', 0, 1));
1227     }
1228 
1229     @Test
1230     void testJoin_List_EmptyDelimiter() {
1231         assertNull(StringUtils.join((List<String>) null, null));
1232         assertEquals(TEXT_LIST_NOSEP, StringUtils.join(STRING_LIST, null));
1233         assertEquals(TEXT_LIST_NOSEP, StringUtils.join(STRING_LIST, ""));
1234 
1235         assertEquals("", StringUtils.join(NULL_STRING_LIST, null));
1236 
1237         assertEquals("", StringUtils.join(EMPTY_STRING_LIST, null));
1238         assertEquals("", StringUtils.join(EMPTY_STRING_LIST, ""));
1239 
1240         assertEquals("", StringUtils.join(MIXED_STRING_LIST, "", 0, MIXED_STRING_LIST.size() - 1));
1241     }
1242 
1243     @ParameterizedTest
1244     @ValueSource(strings = {",", ";", Supplementary.CharU20000, Supplementary.CharU20001})
1245     void testJoin_List_NonEmptyDelimiter(final String delimiter) {
1246         assertEquals("", StringUtils.join(EMPTY_STRING_LIST, delimiter));
1247 
1248         assertEquals(String.join(delimiter, STRING_LIST), StringUtils.join(STRING_LIST, delimiter));
1249         assertEquals(delimiter + delimiter + "foo", StringUtils.join(MIXED_STRING_LIST, delimiter));
1250         assertEquals(String.join(delimiter, "foo", "2"), StringUtils.join(MIXED_TYPE_OBJECT_LIST, delimiter));
1251 
1252         assertEquals(delimiter, StringUtils.join(MIXED_STRING_LIST, delimiter, 0, MIXED_STRING_LIST.size() - 1));
1253         assertEquals("foo", StringUtils.join(MIXED_TYPE_OBJECT_LIST, delimiter, 0, 1));
1254         assertEquals(String.join(delimiter, "foo", "2"), StringUtils.join(MIXED_TYPE_OBJECT_LIST, delimiter, 0, 2));
1255         assertEquals("2", StringUtils.join(MIXED_TYPE_OBJECT_LIST, delimiter, 1, 2));
1256         assertEquals("", StringUtils.join(MIXED_TYPE_OBJECT_LIST, delimiter, 2, 1));
1257         assertNull(null, StringUtils.join((List<?>) null, delimiter, 0, 1));
1258     }
1259 
1260     @Test
1261     void testJoin_Objectarray() {
1262 //        assertNull(StringUtils.join(null)); // generates warning
1263         assertNull(StringUtils.join((Object[]) null)); // equivalent explicit cast
1264         // test additional varargs calls
1265         assertEquals("", StringUtils.join()); // empty array
1266         assertEquals("", StringUtils.join((Object) null)); // => new Object[]{null}
1267 
1268         assertEquals("", StringUtils.join(EMPTY_ARRAY_LIST));
1269         assertEquals("", StringUtils.join(NULL_ARRAY_LIST));
1270         assertEquals("null", StringUtils.join(NULL_TO_STRING_LIST));
1271         assertEquals("abc", StringUtils.join("a", "b", "c"));
1272         assertEquals("a", StringUtils.join(null, "a", ""));
1273         assertEquals("foo", StringUtils.join(MIXED_ARRAY_LIST));
1274         assertEquals("foo2", StringUtils.join(MIXED_TYPE_LIST));
1275     }
1276 
1277     @Test
1278     void testJoin_Objects() {
1279         assertEquals("abc", StringUtils.join("a", "b", "c"));
1280         assertEquals("a", StringUtils.join(null, "", "a"));
1281         assertNull(StringUtils.join((Object[]) null));
1282     }
1283 
1284     @ParameterizedTest
1285     @ValueSource(strings = {",", ";", Supplementary.CharU20000, Supplementary.CharU20001})
1286     void testJoinWith(final String delimiter) {
1287         assertEquals("", StringUtils.joinWith(delimiter)); // empty array
1288         assertEquals("", StringUtils.joinWith(delimiter, (Object[]) NULL_ARRAY_LIST));
1289         assertEquals("null", StringUtils.joinWith(delimiter, NULL_TO_STRING_LIST)); // toString method prints 'null'
1290 
1291         assertEquals(String.join(delimiter, "a", "b", "c"), StringUtils.joinWith(delimiter, "a", "b", "c"));
1292         assertEquals(String.join(delimiter, "", "a", ""), StringUtils.joinWith(delimiter, null, "a", ""));
1293         assertEquals(String.join(delimiter, "", "a", ""), StringUtils.joinWith(delimiter, "", "a", ""));
1294 
1295         assertEquals("ab", StringUtils.joinWith(null, "a", "b"));
1296     }
1297 
1298     @Test
1299     void testJoinWithThrowsException() {
1300         assertIllegalArgumentException(() -> StringUtils.joinWith(",", (Object[]) null));
1301     }
1302 
1303     @Disabled
1304     @Test
1305     void testLang1593() {
1306         final int[] arr = {1, 2, 3, 4, 5, 6, 7};
1307         final String expected = StringUtils.join(arr, '-');
1308         final String actual = StringUtils.join(arr, "-");
1309         assertEquals(expected, actual);
1310     }
1311 
1312     @Test
1313     void testLang623() {
1314         assertEquals("t", StringUtils.replaceChars("\u00DE", '\u00DE', 't'));
1315         assertEquals("t", StringUtils.replaceChars("\u00FE", '\u00FE', 't'));
1316     }
1317 
1318     @Test
1319     void testLANG666() {
1320         assertEquals("12", StringUtils.stripEnd("120.00", ".0"));
1321         assertEquals("121", StringUtils.stripEnd("121.00", ".0"));
1322     }
1323 
1324     @Test
1325     void testLeftPad_StringInt() {
1326         assertNull(StringUtils.leftPad(null, 5));
1327         assertEquals("     ", StringUtils.leftPad("", 5));
1328         assertEquals("  abc", StringUtils.leftPad("abc", 5));
1329         assertEquals("abc", StringUtils.leftPad("abc", 2));
1330         assertEquals("abc", StringUtils.leftPad("abc", Integer.MIN_VALUE));
1331     }
1332 
1333     @Test
1334     void testLeftPad_StringIntChar() {
1335         assertNull(StringUtils.leftPad(null, 5, ' '));
1336         assertEquals("     ", StringUtils.leftPad("", 5, ' '));
1337         assertEquals("  abc", StringUtils.leftPad("abc", 5, ' '));
1338         assertEquals("xxabc", StringUtils.leftPad("abc", 5, 'x'));
1339         assertEquals("\uffff\uffffabc", StringUtils.leftPad("abc", 5, '\uffff'));
1340         assertEquals("abc", StringUtils.leftPad("abc", 2, ' '));
1341         assertEquals("abc", StringUtils.leftPad("abc", Integer.MIN_VALUE, ' '));
1342         final String str = StringUtils.leftPad("aaa", 10000, 'a');  // bigger than pad length
1343         assertEquals(10000, str.length());
1344         assertTrue(StringUtils.containsOnly(str, 'a'));
1345     }
1346 
1347     @Test
1348     void testLeftPad_StringIntString() {
1349         assertNull(StringUtils.leftPad(null, 5, "-+"));
1350         assertNull(StringUtils.leftPad(null, 5, null));
1351         assertEquals("     ", StringUtils.leftPad("", 5, " "));
1352         assertEquals("-+-+abc", StringUtils.leftPad("abc", 7, "-+"));
1353         assertEquals("-+~abc", StringUtils.leftPad("abc", 6, "-+~"));
1354         assertEquals("-+abc", StringUtils.leftPad("abc", 5, "-+~"));
1355         assertEquals("abc", StringUtils.leftPad("abc", 2, " "));
1356         assertEquals("abc", StringUtils.leftPad("abc", -1, " "));
1357         assertEquals("  abc", StringUtils.leftPad("abc", 5, null));
1358         assertEquals("  abc", StringUtils.leftPad("abc", 5, ""));
1359         assertEquals("abc", StringUtils.leftPad("abc", Integer.MIN_VALUE, " "));
1360     }
1361 
1362     @Test
1363     void testLength_CharBuffer() {
1364         assertEquals(0, StringUtils.length(CharBuffer.wrap("")));
1365         assertEquals(1, StringUtils.length(CharBuffer.wrap("A")));
1366         assertEquals(1, StringUtils.length(CharBuffer.wrap(" ")));
1367         assertEquals(8, StringUtils.length(CharBuffer.wrap("ABCDEFGH")));
1368     }
1369 
1370     @Test
1371     void testLengthString() {
1372         assertEquals(0, StringUtils.length(null));
1373         assertEquals(0, StringUtils.length(""));
1374         assertEquals(0, StringUtils.length(StringUtils.EMPTY));
1375         assertEquals(1, StringUtils.length("A"));
1376         assertEquals(1, StringUtils.length(" "));
1377         assertEquals(8, StringUtils.length("ABCDEFGH"));
1378     }
1379 
1380     @Test
1381     void testLengthStringBuffer() {
1382         assertEquals(0, StringUtils.length(new StringBuffer("")));
1383         assertEquals(0, StringUtils.length(new StringBuffer(StringUtils.EMPTY)));
1384         assertEquals(1, StringUtils.length(new StringBuffer("A")));
1385         assertEquals(1, StringUtils.length(new StringBuffer(" ")));
1386         assertEquals(8, StringUtils.length(new StringBuffer("ABCDEFGH")));
1387     }
1388 
1389     @Test
1390     void testLengthStringBuilder() {
1391         assertEquals(0, StringUtils.length(new StringBuilder("")));
1392         assertEquals(0, StringUtils.length(new StringBuilder(StringUtils.EMPTY)));
1393         assertEquals(1, StringUtils.length(new StringBuilder("A")));
1394         assertEquals(1, StringUtils.length(new StringBuilder(" ")));
1395         assertEquals(8, StringUtils.length(new StringBuilder("ABCDEFGH")));
1396     }
1397 
1398     @Test
1399     void testLowerCase() {
1400         assertNull(StringUtils.lowerCase(null));
1401         assertNull(StringUtils.lowerCase(null, Locale.ENGLISH));
1402         assertEquals("foo test thing", StringUtils.lowerCase("fOo test THING"), "lowerCase(String) failed");
1403         assertEquals("", StringUtils.lowerCase(""), "lowerCase(empty-string) failed");
1404         assertEquals("foo test thing", StringUtils.lowerCase("fOo test THING", Locale.ENGLISH),
1405                 "lowerCase(String, Locale) failed");
1406         assertEquals("", StringUtils.lowerCase("", Locale.ENGLISH), "lowerCase(empty-string, Locale) failed");
1407     }
1408 
1409     @Test
1410     void testNormalizeSpace() {
1411         // Java says a non-breaking whitespace is not a whitespace.
1412         assertFalse(Character.isWhitespace('\u00A0'));
1413         //
1414         assertNull(StringUtils.normalizeSpace(null));
1415         assertEquals("", StringUtils.normalizeSpace(""));
1416         assertEquals("", StringUtils.normalizeSpace(" "));
1417         assertEquals("", StringUtils.normalizeSpace("\t"));
1418         assertEquals("", StringUtils.normalizeSpace("\n"));
1419         assertEquals("", StringUtils.normalizeSpace("\u0009"));
1420         assertEquals("", StringUtils.normalizeSpace("\u000B"));
1421         assertEquals("", StringUtils.normalizeSpace("\u000C"));
1422         assertEquals("", StringUtils.normalizeSpace("\u001C"));
1423         assertEquals("", StringUtils.normalizeSpace("\u001D"));
1424         assertEquals("", StringUtils.normalizeSpace("\u001E"));
1425         assertEquals("", StringUtils.normalizeSpace("\u001F"));
1426         assertEquals("", StringUtils.normalizeSpace("\f"));
1427         assertEquals("", StringUtils.normalizeSpace("\r"));
1428         assertEquals("a", StringUtils.normalizeSpace("  a  "));
1429         assertEquals("a b c", StringUtils.normalizeSpace("  a  b   c  "));
1430         assertEquals("a b c", StringUtils.normalizeSpace("a\t\f\r  b\u000B   c\n"));
1431         assertEquals("a   b c", StringUtils.normalizeSpace("a\t\f\r  " + HARD_SPACE + HARD_SPACE + "b\u000B   c\n"));
1432         assertEquals("b", StringUtils.normalizeSpace("\u0000b"));
1433         assertEquals("b", StringUtils.normalizeSpace("b\u0000"));
1434     }
1435 
1436     @Test
1437     void testOverlay_StringStringIntInt() {
1438         assertNull(StringUtils.overlay(null, null, 2, 4));
1439         assertNull(StringUtils.overlay(null, null, -2, -4));
1440 
1441         assertEquals("", StringUtils.overlay("", null, 0, 0));
1442         assertEquals("", StringUtils.overlay("", "", 0, 0));
1443         assertEquals("zzzz", StringUtils.overlay("", "zzzz", 0, 0));
1444         assertEquals("zzzz", StringUtils.overlay("", "zzzz", 2, 4));
1445         assertEquals("zzzz", StringUtils.overlay("", "zzzz", -2, -4));
1446 
1447         assertEquals("abef", StringUtils.overlay("abcdef", null, 2, 4));
1448         assertEquals("abef", StringUtils.overlay("abcdef", null, 4, 2));
1449         assertEquals("abef", StringUtils.overlay("abcdef", "", 2, 4));
1450         assertEquals("abef", StringUtils.overlay("abcdef", "", 4, 2));
1451         assertEquals("abzzzzef", StringUtils.overlay("abcdef", "zzzz", 2, 4));
1452         assertEquals("abzzzzef", StringUtils.overlay("abcdef", "zzzz", 4, 2));
1453 
1454         assertEquals("zzzzef", StringUtils.overlay("abcdef", "zzzz", -1, 4));
1455         assertEquals("zzzzef", StringUtils.overlay("abcdef", "zzzz", 4, -1));
1456         assertEquals("zzzzabcdef", StringUtils.overlay("abcdef", "zzzz", -2, -1));
1457         assertEquals("zzzzabcdef", StringUtils.overlay("abcdef", "zzzz", -1, -2));
1458         assertEquals("abcdzzzz", StringUtils.overlay("abcdef", "zzzz", 4, 10));
1459         assertEquals("abcdzzzz", StringUtils.overlay("abcdef", "zzzz", 10, 4));
1460         assertEquals("abcdefzzzz", StringUtils.overlay("abcdef", "zzzz", 8, 10));
1461         assertEquals("abcdefzzzz", StringUtils.overlay("abcdef", "zzzz", 10, 8));
1462     }
1463 
1464     @Test
1465     void testOverlaySurrogatePair() {
1466         final String grin = "😀";
1467         // overlaying across surrogate pair boundary backs off start and advances end
1468         assertEquals("X", StringUtils.overlay(grin, "X", 1, 1));
1469         assertEquals("aXb", StringUtils.overlay("a" + grin + "b", "X", 1, 3));
1470         assertEquals("aXb", StringUtils.overlay("a" + grin + "b", "X", 2, 2));
1471 
1472         final String source = "a" + grin + "b" + grin + "cd" + grin + "ef";
1473         for (int start = 0; start <= source.length(); start++) {
1474             for (int end = 0; end <= source.length(); end++) {
1475                 final String result = StringUtils.overlay(source, "X", start, end);
1476                 for (int i = 0; i < result.length(); i++) {
1477                     final char ch = result.charAt(i);
1478                     if (Character.isHighSurrogate(ch)) {
1479                         assertTrue(i + 1 < result.length() && Character.isLowSurrogate(result.charAt(i + 1)), "lone high surrogate in: " + result);
1480                         i++; // skip the paired low surrogate
1481                     } else {
1482                         assertFalse(Character.isLowSurrogate(ch), "lone low surrogate in: " + result);
1483                     }
1484                 }
1485             }
1486         }
1487     }
1488 
1489     /**
1490      * Tests {@code prependIfMissing}.
1491      */
1492     @Test
1493     void testPrependIfMissing() {
1494         assertNull(StringUtils.prependIfMissing(null, null), "prependIfMissing(null,null)");
1495         assertEquals("abc", StringUtils.prependIfMissing("abc", null), "prependIfMissing(abc,null)");
1496         assertEquals("xyz", StringUtils.prependIfMissing("", "xyz"), "prependIfMissing(\"\",xyz)");
1497         assertEquals("xyzabc", StringUtils.prependIfMissing("abc", "xyz"), "prependIfMissing(abc,xyz)");
1498         assertEquals("xyzabc", StringUtils.prependIfMissing("xyzabc", "xyz"), "prependIfMissing(xyzabc,xyz)");
1499         assertEquals("xyzXYZabc", StringUtils.prependIfMissing("XYZabc", "xyz"), "prependIfMissing(XYZabc,xyz)");
1500 
1501         assertNull(StringUtils.prependIfMissing(null, null, (CharSequence[]) null), "prependIfMissing(null,null null)");
1502         assertEquals("abc", StringUtils.prependIfMissing("abc", null, (CharSequence[]) null), "prependIfMissing(abc,null,null)");
1503         assertEquals("xyz", StringUtils.prependIfMissing("", "xyz", (CharSequence[]) null), "prependIfMissing(\"\",xyz,null)");
1504         assertEquals("xyzabc", StringUtils.prependIfMissing("abc", "xyz", (CharSequence) null), "prependIfMissing(abc,xyz,{null})");
1505         assertEquals("abc", StringUtils.prependIfMissing("abc", "xyz", ""), "prependIfMissing(abc,xyz,\"\")");
1506         assertEquals("xyzabc", StringUtils.prependIfMissing("abc", "xyz", "mno"), "prependIfMissing(abc,xyz,mno)");
1507         assertEquals("xyzabc", StringUtils.prependIfMissing("xyzabc", "xyz", "mno"), "prependIfMissing(xyzabc,xyz,mno)");
1508         assertEquals("mnoabc", StringUtils.prependIfMissing("mnoabc", "xyz", "mno"), "prependIfMissing(mnoabc,xyz,mno)");
1509         assertEquals("xyzXYZabc", StringUtils.prependIfMissing("XYZabc", "xyz", "mno"), "prependIfMissing(XYZabc,xyz,mno)");
1510         assertEquals("xyzMNOabc", StringUtils.prependIfMissing("MNOabc", "xyz", "mno"), "prependIfMissing(MNOabc,xyz,mno)");
1511     }
1512 
1513     /**
1514      * Tests {@code prependIfMissingIgnoreCase}.
1515      */
1516     @Test
1517     void testPrependIfMissingIgnoreCase() {
1518         assertNull(StringUtils.prependIfMissingIgnoreCase(null, null), "prependIfMissingIgnoreCase(null,null)");
1519         assertEquals("abc", StringUtils.prependIfMissingIgnoreCase("abc", null), "prependIfMissingIgnoreCase(abc,null)");
1520         assertEquals("xyz", StringUtils.prependIfMissingIgnoreCase("", "xyz"), "prependIfMissingIgnoreCase(\"\",xyz)");
1521         assertEquals("xyzabc", StringUtils.prependIfMissingIgnoreCase("abc", "xyz"), "prependIfMissingIgnoreCase(abc,xyz)");
1522         assertEquals("xyzabc", StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz"), "prependIfMissingIgnoreCase(xyzabc,xyz)");
1523         assertEquals("XYZabc", StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz"), "prependIfMissingIgnoreCase(XYZabc,xyz)");
1524 
1525         assertNull(StringUtils.prependIfMissingIgnoreCase(null, null, (CharSequence[]) null), "prependIfMissingIgnoreCase(null,null null)");
1526         assertEquals("abc", StringUtils.prependIfMissingIgnoreCase("abc", null, (CharSequence[]) null), "prependIfMissingIgnoreCase(abc,null,null)");
1527         assertEquals("xyz", StringUtils.prependIfMissingIgnoreCase("", "xyz", (CharSequence[]) null), "prependIfMissingIgnoreCase(\"\",xyz,null)");
1528         assertEquals("xyzabc", StringUtils.prependIfMissingIgnoreCase("abc", "xyz", (CharSequence) null), "prependIfMissingIgnoreCase(abc,xyz,{null})");
1529         assertEquals("abc", StringUtils.prependIfMissingIgnoreCase("abc", "xyz", ""), "prependIfMissingIgnoreCase(abc,xyz,\"\")");
1530         assertEquals("xyzabc", StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno"), "prependIfMissingIgnoreCase(abc,xyz,mno)");
1531         assertEquals("xyzabc", StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno"), "prependIfMissingIgnoreCase(xyzabc,xyz,mno)");
1532         assertEquals("mnoabc", StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno"), "prependIfMissingIgnoreCase(mnoabc,xyz,mno)");
1533         assertEquals("XYZabc", StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno"), "prependIfMissingIgnoreCase(XYZabc,xyz,mno)");
1534         assertEquals("MNOabc", StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno"), "prependIfMissingIgnoreCase(MNOabc,xyz,mno)");
1535     }
1536 
1537     @Test
1538     void testReCapitalize() {
1539         // reflection type of tests: Sentences.
1540         assertEquals(SENTENCE_UNCAP, StringUtils.uncapitalize(StringUtils.capitalize(SENTENCE_UNCAP)),
1541                 "uncapitalize(capitalize(String)) failed");
1542         assertEquals(SENTENCE_CAP, StringUtils.capitalize(StringUtils.uncapitalize(SENTENCE_CAP)),
1543                 "capitalize(uncapitalize(String)) failed");
1544 
1545         // reflection type of tests: One word.
1546         assertEquals(FOO_UNCAP, StringUtils.uncapitalize(StringUtils.capitalize(FOO_UNCAP)),
1547                 "uncapitalize(capitalize(String)) failed");
1548         assertEquals(FOO_CAP, StringUtils.capitalize(StringUtils.uncapitalize(FOO_CAP)),
1549                 "capitalize(uncapitalize(String)) failed");
1550     }
1551 
1552     @Test
1553     void testRemove_char() {
1554         // StringUtils.remove(null, *)       = null
1555         assertNull(StringUtils.remove(null, null));
1556         assertNull(StringUtils.remove(null, 'a'));
1557 
1558         // StringUtils.remove("", *)          = ""
1559         assertEquals("", StringUtils.remove("", null));
1560         assertEquals("", StringUtils.remove("", 'a'));
1561 
1562         // StringUtils.remove("queued", 'u') = "qeed"
1563         assertEquals("qeed", StringUtils.remove("queued", 'u'));
1564 
1565         // StringUtils.remove("queued", 'z') = "queued"
1566         assertEquals("queued", StringUtils.remove("queued", 'z'));
1567     }
1568 
1569     @Test
1570     void testRemove_String() {
1571         // StringUtils.remove(null, *)        = null
1572         assertNull(StringUtils.remove(null, null));
1573         assertNull(StringUtils.remove(null, ""));
1574         assertNull(StringUtils.remove(null, "a"));
1575 
1576         // StringUtils.remove("", *)          = ""
1577         assertEquals("", StringUtils.remove("", null));
1578         assertEquals("", StringUtils.remove("", ""));
1579         assertEquals("", StringUtils.remove("", "a"));
1580 
1581         // StringUtils.remove(*, null)        = *
1582         assertNull(StringUtils.remove(null, null));
1583         assertEquals("", StringUtils.remove("", null));
1584         assertEquals("a", StringUtils.remove("a", null));
1585 
1586         // StringUtils.remove(*, "")          = *
1587         assertNull(StringUtils.remove(null, ""));
1588         assertEquals("", StringUtils.remove("", ""));
1589         assertEquals("a", StringUtils.remove("a", ""));
1590 
1591         // StringUtils.remove("queued", "ue") = "qd"
1592         assertEquals("qd", StringUtils.remove("queued", "ue"));
1593 
1594         // StringUtils.remove("queued", "zz") = "queued"
1595         assertEquals("queued", StringUtils.remove("queued", "zz"));
1596     }
1597 
1598     @Test
1599     void testRemoveAll_StringString() {
1600         assertNull(StringUtils.removeAll(null, ""));
1601         assertEquals("any", StringUtils.removeAll("any", null));
1602 
1603         assertEquals("any", StringUtils.removeAll("any", ""));
1604         assertEquals("", StringUtils.removeAll("any", ".*"));
1605         assertEquals("", StringUtils.removeAll("any", ".+"));
1606         assertEquals("", StringUtils.removeAll("any", ".?"));
1607 
1608         assertEquals("A\nB", StringUtils.removeAll("A<__>\n<__>B", "<.*>"));
1609         assertEquals("AB", StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>"));
1610         assertEquals("ABC123", StringUtils.removeAll("ABCabc123abc", "[a-z]"));
1611 
1612         assertThrows(PatternSyntaxException.class, () -> StringUtils.removeAll("any", "{badRegexSyntax}"),
1613                 "StringUtils.removeAll expecting PatternSyntaxException");
1614     }
1615 
1616     @Test
1617     void testRemoveEnd() {
1618         // StringUtils.removeEnd("", *)        = ""
1619         assertNull(StringUtils.removeEnd(null, null));
1620         assertNull(StringUtils.removeEnd(null, ""));
1621         assertNull(StringUtils.removeEnd(null, "a"));
1622 
1623         // StringUtils.removeEnd(*, null)      = *
1624         assertEquals(StringUtils.removeEnd("", null), "");
1625         assertEquals(StringUtils.removeEnd("", ""), "");
1626         assertEquals(StringUtils.removeEnd("", "a"), "");
1627 
1628         // All others:
1629         assertEquals(StringUtils.removeEnd("www.domain.com.", ".com"), "www.domain.com.");
1630         assertEquals(StringUtils.removeEnd("www.domain.com", ".com"), "www.domain");
1631         assertEquals(StringUtils.removeEnd("www.domain", ".com"), "www.domain");
1632         assertEquals(StringUtils.removeEnd("domain.com", ""), "domain.com");
1633         assertEquals(StringUtils.removeEnd("domain.com", null), "domain.com");
1634     }
1635 
1636     @Test
1637     void testRemoveEndIgnoreCase() {
1638         // StringUtils.removeEndIgnoreCase("", *)        = ""
1639         assertNull(StringUtils.removeEndIgnoreCase(null, null), "removeEndIgnoreCase(null, null)");
1640         assertNull(StringUtils.removeEndIgnoreCase(null, ""), "removeEndIgnoreCase(null, \"\")");
1641         assertNull(StringUtils.removeEndIgnoreCase(null, "a"), "removeEndIgnoreCase(null, \"a\")");
1642 
1643         // StringUtils.removeEnd(*, null)      = *
1644         assertEquals(StringUtils.removeEndIgnoreCase("", null), "", "removeEndIgnoreCase(\"\", null)");
1645         assertEquals(StringUtils.removeEndIgnoreCase("", ""), "", "removeEndIgnoreCase(\"\", \"\")");
1646         assertEquals(StringUtils.removeEndIgnoreCase("", "a"), "", "removeEndIgnoreCase(\"\", \"a\")");
1647 
1648         // All others:
1649         assertEquals(StringUtils.removeEndIgnoreCase("www.domain.com.", ".com"), "www.domain.com.", "removeEndIgnoreCase(\"www.domain.com.\", \".com\")");
1650         assertEquals(StringUtils.removeEndIgnoreCase("www.domain.com", ".com"), "www.domain", "removeEndIgnoreCase(\"www.domain.com\", \".com\")");
1651         assertEquals(StringUtils.removeEndIgnoreCase("www.domain", ".com"), "www.domain", "removeEndIgnoreCase(\"www.domain\", \".com\")");
1652         assertEquals(StringUtils.removeEndIgnoreCase("domain.com", ""), "domain.com", "removeEndIgnoreCase(\"domain.com\", \"\")");
1653         assertEquals(StringUtils.removeEndIgnoreCase("domain.com", null), "domain.com", "removeEndIgnoreCase(\"domain.com\", null)");
1654 
1655         // Case-insensitive:
1656         assertEquals(StringUtils.removeEndIgnoreCase("www.domain.com", ".COM"), "www.domain", "removeEndIgnoreCase(\"www.domain.com\", \".COM\")");
1657         assertEquals(StringUtils.removeEndIgnoreCase("www.domain.COM", ".com"), "www.domain", "removeEndIgnoreCase(\"www.domain.COM\", \".com\")");
1658     }
1659 
1660     @Test
1661     void testRemoveFirst_StringString() {
1662         assertNull(StringUtils.removeFirst(null, ""));
1663         assertEquals("any", StringUtils.removeFirst("any", null));
1664 
1665         assertEquals("any", StringUtils.removeFirst("any", ""));
1666         assertEquals("", StringUtils.removeFirst("any", ".*"));
1667         assertEquals("", StringUtils.removeFirst("any", ".+"));
1668         assertEquals("bc", StringUtils.removeFirst("abc", ".?"));
1669 
1670         assertEquals("A\n<__>B", StringUtils.removeFirst("A<__>\n<__>B", "<.*>"));
1671         assertEquals("AB", StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>"));
1672         assertEquals("ABCbc123", StringUtils.removeFirst("ABCabc123", "[a-z]"));
1673         assertEquals("ABC123abc", StringUtils.removeFirst("ABCabc123abc", "[a-z]+"));
1674 
1675         assertThrows(PatternSyntaxException.class, () -> StringUtils.removeFirst("any", "{badRegexSyntax}"),
1676                 "StringUtils.removeFirst expecting PatternSyntaxException");
1677     }
1678 
1679     @Test
1680     void testRemoveIgnoreCase_String() {
1681         // StringUtils.removeIgnoreCase(null, *) = null
1682         assertNull(StringUtils.removeIgnoreCase(null, null));
1683         assertNull(StringUtils.removeIgnoreCase(null, ""));
1684         assertNull(StringUtils.removeIgnoreCase(null, "a"));
1685 
1686         // StringUtils.removeIgnoreCase("", *) = ""
1687         assertEquals("", StringUtils.removeIgnoreCase("", null));
1688         assertEquals("", StringUtils.removeIgnoreCase("", ""));
1689         assertEquals("", StringUtils.removeIgnoreCase("", "a"));
1690 
1691         // StringUtils.removeIgnoreCase(*, null) = *
1692         assertNull(StringUtils.removeIgnoreCase(null, null));
1693         assertEquals("", StringUtils.removeIgnoreCase("", null));
1694         assertEquals("a", StringUtils.removeIgnoreCase("a", null));
1695 
1696         // StringUtils.removeIgnoreCase(*, "") = *
1697         assertNull(StringUtils.removeIgnoreCase(null, ""));
1698         assertEquals("", StringUtils.removeIgnoreCase("", ""));
1699         assertEquals("a", StringUtils.removeIgnoreCase("a", ""));
1700 
1701         // StringUtils.removeIgnoreCase("queued", "ue") = "qd"
1702         assertEquals("qd", StringUtils.removeIgnoreCase("queued", "ue"));
1703 
1704         // StringUtils.removeIgnoreCase("queued", "zz") = "queued"
1705         assertEquals("queued", StringUtils.removeIgnoreCase("queued", "zz"));
1706 
1707         // IgnoreCase
1708         // StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
1709         assertEquals("qd", StringUtils.removeIgnoreCase("quEUed", "UE"));
1710 
1711         // StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
1712         assertEquals("queued", StringUtils.removeIgnoreCase("queued", "zZ"));
1713 
1714         // StringUtils.removeIgnoreCase("\u0130x", "x") = "\u0130"
1715         assertEquals("\u0130", StringUtils.removeIgnoreCase("\u0130x", "x"));
1716 
1717         // LANG-1453
1718         StringUtils.removeIgnoreCase("İa", "a");
1719     }
1720 
1721     @Test
1722     void testRemovePattern_StringString() {
1723         assertNull(StringUtils.removePattern(null, ""));
1724         assertEquals("any", StringUtils.removePattern("any", null));
1725 
1726         assertEquals("", StringUtils.removePattern("", ""));
1727         assertEquals("", StringUtils.removePattern("", ".*"));
1728         assertEquals("", StringUtils.removePattern("", ".+"));
1729 
1730         assertEquals("AB", StringUtils.removePattern("A<__>\n<__>B", "<.*>"));
1731         assertEquals("AB", StringUtils.removePattern("A<__>\\n<__>B", "<.*>"));
1732         assertEquals("", StringUtils.removePattern("<A>x\\ny</A>", "<A>.*</A>"));
1733         assertEquals("", StringUtils.removePattern("<A>\nxy\n</A>", "<A>.*</A>"));
1734 
1735         assertEquals("ABC123", StringUtils.removePattern("ABCabc123", "[a-z]"));
1736     }
1737 
1738     @Test
1739     void testRemoveStartChar() {
1740         // StringUtils.removeStart("", *)        = ""
1741         assertNull(StringUtils.removeStart(null, '\0'));
1742         assertNull(StringUtils.removeStart(null, 'a'));
1743 
1744         // StringUtils.removeStart(*, null)      = *
1745         assertEquals(StringUtils.removeStart("", '\0'), "");
1746         assertEquals(StringUtils.removeStart("", 'a'), "");
1747 
1748         // All others:
1749         assertEquals(StringUtils.removeStart("/path", '/'), "path");
1750         assertEquals(StringUtils.removeStart("path", '/'), "path");
1751         assertEquals(StringUtils.removeStart("path", '\0'), "path");
1752     }
1753 
1754     @Test
1755     void testRemoveStartIgnoreCase() {
1756         // StringUtils.removeStart("", *)        = ""
1757         assertNull(StringUtils.removeStartIgnoreCase(null, null), "removeStartIgnoreCase(null, null)");
1758         assertNull(StringUtils.removeStartIgnoreCase(null, ""), "removeStartIgnoreCase(null, \"\")");
1759         assertNull(StringUtils.removeStartIgnoreCase(null, "a"), "removeStartIgnoreCase(null, \"a\")");
1760 
1761         // StringUtils.removeStart(*, null)      = *
1762         assertEquals(StringUtils.removeStartIgnoreCase("", null), "", "removeStartIgnoreCase(\"\", null)");
1763         assertEquals(StringUtils.removeStartIgnoreCase("", ""), "", "removeStartIgnoreCase(\"\", \"\")");
1764         assertEquals(StringUtils.removeStartIgnoreCase("", "a"), "", "removeStartIgnoreCase(\"\", \"a\")");
1765 
1766         // All others:
1767         assertEquals(StringUtils.removeStartIgnoreCase("www.domain.com", "www."), "domain.com", "removeStartIgnoreCase(\"www.domain.com\", \"www.\")");
1768         assertEquals(StringUtils.removeStartIgnoreCase("domain.com", "www."), "domain.com", "removeStartIgnoreCase(\"domain.com\", \"www.\")");
1769         assertEquals(StringUtils.removeStartIgnoreCase("domain.com", ""), "domain.com", "removeStartIgnoreCase(\"domain.com\", \"\")");
1770         assertEquals(StringUtils.removeStartIgnoreCase("domain.com", null), "domain.com", "removeStartIgnoreCase(\"domain.com\", null)");
1771 
1772         // Case-insensitive:
1773         assertEquals(StringUtils.removeStartIgnoreCase("www.domain.com", "WWW."), "domain.com", "removeStartIgnoreCase(\"www.domain.com\", \"WWW.\")");
1774     }
1775 
1776     @Test
1777     void testRemoveStartString() {
1778         // StringUtils.removeStart("", *)        = ""
1779         assertNull(StringUtils.removeStart(null, null));
1780         assertNull(StringUtils.removeStart(null, ""));
1781         assertNull(StringUtils.removeStart(null, "a"));
1782 
1783         // StringUtils.removeStart(*, null)      = *
1784         assertEquals(StringUtils.removeStart("", null), "");
1785         assertEquals(StringUtils.removeStart("", ""), "");
1786         assertEquals(StringUtils.removeStart("", "a"), "");
1787 
1788         // All others:
1789         assertEquals(StringUtils.removeStart("www.domain.com", "www."), "domain.com");
1790         assertEquals(StringUtils.removeStart("domain.com", "www."), "domain.com");
1791         assertEquals(StringUtils.removeStart("domain.com", ""), "domain.com");
1792         assertEquals(StringUtils.removeStart("domain.com", null), "domain.com");
1793     }
1794 
1795     @Test
1796     void testRepeat_CharInt() {
1797         assertEquals("zzz", StringUtils.repeat('z', 3));
1798         assertEquals("", StringUtils.repeat('z', 0));
1799         assertEquals("", StringUtils.repeat('z', -2));
1800     }
1801 
1802     @Test
1803     void testRepeat_StringInt() {
1804         assertNull(StringUtils.repeat(null, 2));
1805         assertEquals("", StringUtils.repeat("ab", 0));
1806         assertEquals("", StringUtils.repeat("", 3));
1807         assertEquals("aaa", StringUtils.repeat("a", 3));
1808         assertEquals("", StringUtils.repeat("a", -2));
1809         assertEquals("ababab", StringUtils.repeat("ab", 3));
1810         assertEquals("abcabcabc", StringUtils.repeat("abc", 3));
1811         final String str = StringUtils.repeat("a", 10000);  // bigger than pad limit
1812         assertEquals(10000, str.length());
1813         assertTrue(StringUtils.containsOnly(str, 'a'));
1814         assertThrows(IllegalArgumentException.class, () -> StringUtils.repeat("aa", 1_073_741_824));
1815     }
1816 
1817     @Test
1818     void testRepeat_StringStringInt() {
1819         assertNull(StringUtils.repeat(null, null, 2));
1820         assertNull(StringUtils.repeat(null, "x", 2));
1821         assertEquals("", StringUtils.repeat("", null, 2));
1822         assertEquals("", StringUtils.repeat("ab", "", 0));
1823         assertEquals("", StringUtils.repeat("", "", 2));
1824         assertEquals("xx", StringUtils.repeat("", "x", 3));
1825         assertEquals("?, ?, ?", StringUtils.repeat("?", ", ", 3));
1826         assertThrows(IllegalArgumentException.class, () -> StringUtils.repeat("?", ", ", 1_073_741_824));
1827     }
1828 
1829     /**
1830      * Test method for 'StringUtils.replaceEach(String, String[], String[])'
1831      */
1832     @Test
1833     void testReplace_StringStringArrayStringArray() {
1834         // JAVADOC TESTS START
1835         assertNull(StringUtils.replaceEach(null, new String[]{"a"}, new String[]{"b"}));
1836         assertEquals(StringUtils.replaceEach("", new String[]{"a"}, new String[]{"b"}), "");
1837         assertEquals(StringUtils.replaceEach("aba", null, null), "aba");
1838         assertEquals(StringUtils.replaceEach("aba", new String[0], null), "aba");
1839         assertEquals(StringUtils.replaceEach("aba", null, new String[0]), "aba");
1840         assertEquals(StringUtils.replaceEach("aba", new String[]{"a"}, null), "aba");
1841 
1842         assertEquals(StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}), "b");
1843         assertEquals(StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}), "aba");
1844         assertEquals(StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}), "wcte");
1845         assertEquals(StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}), "dcte");
1846         // JAVADOC TESTS END
1847 
1848         assertEquals("bcc", StringUtils.replaceEach("abc", new String[]{"a", "b"}, new String[]{"b", "c"}));
1849         assertEquals("q651.506bera", StringUtils.replaceEach("d216.102oren",
1850                 new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
1851                         "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D",
1852                         "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
1853                         "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
1854                 new String[]{"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "a",
1855                         "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "N", "O", "P", "Q",
1856                         "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "A", "B", "C", "D", "E", "F", "G",
1857                         "H", "I", "J", "K", "L", "M", "5", "6", "7", "8", "9", "1", "2", "3", "4"}));
1858 
1859         // Test null safety inside arrays - LANG-552
1860         assertEquals(StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{null}), "aba");
1861         assertEquals(StringUtils.replaceEach("aba", new String[]{"a", "b"}, new String[]{"c", null}), "cbc");
1862 
1863         assertIllegalArgumentException(() -> StringUtils.replaceEach("abba", new String[] { "a" }, new String[] { "b", "a" }),
1864                 "StringUtils.replaceEach(String, String[], String[]) expecting IllegalArgumentException");
1865     }
1866 
1867     /**
1868      * Test method for 'StringUtils.replaceEachRepeatedly(String, String[], String[])'
1869      */
1870     @Test
1871     void testReplace_StringStringArrayStringArrayBoolean() {
1872         //JAVADOC TESTS START
1873         assertNull(StringUtils.replaceEachRepeatedly(null, new String[]{"a"}, new String[]{"b"}));
1874         assertEquals("", StringUtils.replaceEachRepeatedly("", new String[]{"a"}, new String[]{"b"}));
1875         assertEquals("aba", StringUtils.replaceEachRepeatedly("aba", null, null));
1876         assertEquals("aba", StringUtils.replaceEachRepeatedly("aba", new String[0], null));
1877         assertEquals("aba", StringUtils.replaceEachRepeatedly("aba", null, new String[0]));
1878         assertEquals("aba", StringUtils.replaceEachRepeatedly("aba", new String[0], null));
1879 
1880         assertEquals("b", StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}));
1881         assertEquals("aba", StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}));
1882         assertEquals("wcte", StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}));
1883         assertEquals("tcte", StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}));
1884 
1885         // Test recursive replacement - LANG-1528 & LANG-1753
1886         assertEquals("blaan", StringUtils.replaceEachRepeatedly("blllaan", new String[]{"llaan"}, new String[]{"laan"}));
1887         assertEquals("blaan", StringUtils.replaceEachRepeatedly("bllllaan", new String[]{"llaan"}, new String[]{"laan"}));
1888 
1889         // Test default TTL for smaller search lists. 32 characters reduced to 16, then 8, 4, 2, 1.
1890         assertEquals("a", StringUtils.replaceEachRepeatedly("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
1891                 new String[]{"aa"}, new String[]{"a"}));
1892 
1893         // Test default TTL exceeded. 33 characters reduced to 17, then 9, 5, 3, 2 (still found).
1894         assertThrows(IllegalStateException.class,
1895                 () -> StringUtils.replaceEachRepeatedly("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", new String[] { "aa" }, new String[] { "a" }),
1896                 "Cannot be resolved within the default time-to-live limit");
1897         // The iteration budget is a fixed constant (no longer derived from the search-list size, which let the
1898         // input choose the recursion depth): a 61-step replacement chain exceeds the budget and aborts.
1899         assertThrows(IllegalStateException.class, () -> StringUtils.replaceEachRepeatedly("aA0aA0aA0",
1900                 new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
1901                         "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D",
1902                         "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
1903                         "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
1904                 new String[]{"b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
1905                         "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E",
1906                         "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
1907                         "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}),
1908                 "Cannot be resolved within the fixed time-to-live limit");
1909 
1910         // Test long infinite cycle: a -> b -> ... -> 9 -> 0 -> a -> b -> ...
1911         assertThrows(IllegalStateException.class,
1912                 () -> StringUtils.replaceEachRepeatedly("a",
1913                     new String[]{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
1914                             "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D",
1915                             "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
1916                             "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"},
1917                     new String[]{"b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
1918                             "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E",
1919                             "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
1920                             "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a"}),
1921                 "Should be a circular reference");
1922 
1923         assertThrows(IllegalStateException.class,
1924                 () -> StringUtils.replaceEachRepeatedly("%{key1}",
1925                     new String[] {"%{key1}", "%{key2}", "%{key3}"},
1926                     new String[] {"Key1 %{key2}", "Key2 %{key3}", "Key3 %{key1}"}),
1927                 "Should be a circular reference");
1928 
1929         assertThrows(IllegalStateException.class,
1930                 () -> StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}),
1931                 "Should be a circular reference");
1932 
1933         //JAVADOC TESTS END
1934     }
1935 
1936     @Test
1937     void testReplace_StringStringString() {
1938         assertNull(StringUtils.replace(null, null, null));
1939         assertNull(StringUtils.replace(null, null, "any"));
1940         assertNull(StringUtils.replace(null, "any", null));
1941         assertNull(StringUtils.replace(null, "any", "any"));
1942 
1943         assertEquals("", StringUtils.replace("", null, null));
1944         assertEquals("", StringUtils.replace("", null, "any"));
1945         assertEquals("", StringUtils.replace("", "any", null));
1946         assertEquals("", StringUtils.replace("", "any", "any"));
1947 
1948         assertEquals("FOO", StringUtils.replace("FOO", "", "any"));
1949         assertEquals("FOO", StringUtils.replace("FOO", null, "any"));
1950         assertEquals("FOO", StringUtils.replace("FOO", "F", null));
1951         assertEquals("FOO", StringUtils.replace("FOO", null, null));
1952 
1953         assertEquals("", StringUtils.replace("foofoofoo", "foo", ""));
1954         assertEquals("barbarbar", StringUtils.replace("foofoofoo", "foo", "bar"));
1955         assertEquals("farfarfar", StringUtils.replace("foofoofoo", "oo", "ar"));
1956     }
1957 
1958     @Test
1959     void testReplace_StringStringStringInt() {
1960         assertNull(StringUtils.replace(null, null, null, 2));
1961         assertNull(StringUtils.replace(null, null, "any", 2));
1962         assertNull(StringUtils.replace(null, "any", null, 2));
1963         assertNull(StringUtils.replace(null, "any", "any", 2));
1964 
1965         assertEquals("", StringUtils.replace("", null, null, 2));
1966         assertEquals("", StringUtils.replace("", null, "any", 2));
1967         assertEquals("", StringUtils.replace("", "any", null, 2));
1968         assertEquals("", StringUtils.replace("", "any", "any", 2));
1969 
1970         final String str = new String(new char[]{'o', 'o', 'f', 'o', 'o'});
1971         assertSame(str, StringUtils.replace(str, "x", "", -1));
1972 
1973         assertEquals("f", StringUtils.replace("oofoo", "o", "", -1));
1974         assertEquals("oofoo", StringUtils.replace("oofoo", "o", "", 0));
1975         assertEquals("ofoo", StringUtils.replace("oofoo", "o", "", 1));
1976         assertEquals("foo", StringUtils.replace("oofoo", "o", "", 2));
1977         assertEquals("fo", StringUtils.replace("oofoo", "o", "", 3));
1978         assertEquals("f", StringUtils.replace("oofoo", "o", "", 4));
1979 
1980         assertEquals("f", StringUtils.replace("oofoo", "o", "", -5));
1981         assertEquals("f", StringUtils.replace("oofoo", "o", "", 1000));
1982     }
1983 
1984     @Test
1985     void testReplaceAll_StringStringString() {
1986         assertNull(StringUtils.replaceAll(null, "", ""));
1987 
1988         assertEquals("any", StringUtils.replaceAll("any", null, ""));
1989         assertEquals("any", StringUtils.replaceAll("any", "", null));
1990 
1991         assertEquals("zzz", StringUtils.replaceAll("", "", "zzz"));
1992         assertEquals("zzz", StringUtils.replaceAll("", ".*", "zzz"));
1993         assertEquals("", StringUtils.replaceAll("", ".+", "zzz"));
1994         assertEquals("ZZaZZbZZcZZ", StringUtils.replaceAll("abc", "", "ZZ"));
1995 
1996         assertEquals("z\nz", StringUtils.replaceAll("<__>\n<__>", "<.*>", "z"));
1997         assertEquals("z", StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z"));
1998 
1999         assertEquals("ABC___123", StringUtils.replaceAll("ABCabc123", "[a-z]", "_"));
2000         assertEquals("ABC_123", StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_"));
2001         assertEquals("ABC123", StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", ""));
2002         assertEquals("Lorem_ipsum_dolor_sit",
2003                      StringUtils.replaceAll("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2"));
2004 
2005         assertThrows(PatternSyntaxException.class, () -> StringUtils.replaceAll("any", "{badRegexSyntax}", ""),
2006                 "StringUtils.replaceAll expecting PatternSyntaxException");
2007     }
2008 
2009     @Test
2010     void testReplaceChars_StringCharChar() {
2011         assertNull(StringUtils.replaceChars(null, 'b', 'z'));
2012         assertEquals("", StringUtils.replaceChars("", 'b', 'z'));
2013         assertEquals("azcza", StringUtils.replaceChars("abcba", 'b', 'z'));
2014         assertEquals("abcba", StringUtils.replaceChars("abcba", 'x', 'z'));
2015     }
2016 
2017     @Test
2018     void testReplaceChars_StringStringString() {
2019         assertNull(StringUtils.replaceChars(null, null, null));
2020         assertNull(StringUtils.replaceChars(null, "", null));
2021         assertNull(StringUtils.replaceChars(null, "a", null));
2022         assertNull(StringUtils.replaceChars(null, null, ""));
2023         assertNull(StringUtils.replaceChars(null, null, "x"));
2024 
2025         assertEquals("", StringUtils.replaceChars("", null, null));
2026         assertEquals("", StringUtils.replaceChars("", "", null));
2027         assertEquals("", StringUtils.replaceChars("", "a", null));
2028         assertEquals("", StringUtils.replaceChars("", null, ""));
2029         assertEquals("", StringUtils.replaceChars("", null, "x"));
2030 
2031         assertEquals("abc", StringUtils.replaceChars("abc", null, null));
2032         assertEquals("abc", StringUtils.replaceChars("abc", null, ""));
2033         assertEquals("abc", StringUtils.replaceChars("abc", null, "x"));
2034 
2035         assertEquals("abc", StringUtils.replaceChars("abc", "", null));
2036         assertEquals("abc", StringUtils.replaceChars("abc", "", ""));
2037         assertEquals("abc", StringUtils.replaceChars("abc", "", "x"));
2038 
2039         assertEquals("ac", StringUtils.replaceChars("abc", "b", null));
2040         assertEquals("ac", StringUtils.replaceChars("abc", "b", ""));
2041         assertEquals("axc", StringUtils.replaceChars("abc", "b", "x"));
2042 
2043         assertEquals("ayzya", StringUtils.replaceChars("abcba", "bc", "yz"));
2044         assertEquals("ayya", StringUtils.replaceChars("abcba", "bc", "y"));
2045         assertEquals("ayzya", StringUtils.replaceChars("abcba", "bc", "yzx"));
2046 
2047         assertEquals("abcba", StringUtils.replaceChars("abcba", "z", "w"));
2048         assertSame("abcba", StringUtils.replaceChars("abcba", "z", "w"));
2049 
2050         // Javadoc examples:
2051         assertEquals("jelly", StringUtils.replaceChars("hello", "ho", "jy"));
2052         assertEquals("ayzya", StringUtils.replaceChars("abcba", "bc", "yz"));
2053         assertEquals("ayya", StringUtils.replaceChars("abcba", "bc", "y"));
2054         assertEquals("ayzya", StringUtils.replaceChars("abcba", "bc", "yzx"));
2055 
2056         // From https://issues.apache.org/bugzilla/show_bug.cgi?id=25454
2057         assertEquals("bcc", StringUtils.replaceChars("abc", "ab", "bc"));
2058         assertEquals("q651.506bera", StringUtils.replaceChars("d216.102oren",
2059                 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789",
2060                 "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM567891234"));
2061     }
2062 
2063     @Test
2064     void testReplaceFirst_StringStringString() {
2065         assertNull(StringUtils.replaceFirst(null, "", ""));
2066 
2067         assertEquals("any", StringUtils.replaceFirst("any", null, ""));
2068         assertEquals("any", StringUtils.replaceFirst("any", "", null));
2069 
2070         assertEquals("zzz", StringUtils.replaceFirst("", "", "zzz"));
2071         assertEquals("zzz", StringUtils.replaceFirst("", ".*", "zzz"));
2072         assertEquals("", StringUtils.replaceFirst("", ".+", "zzz"));
2073         assertEquals("ZZabc", StringUtils.replaceFirst("abc", "", "ZZ"));
2074 
2075         assertEquals("z\n<__>", StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z"));
2076         assertEquals("z", StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z"));
2077 
2078         assertEquals("ABC_bc123", StringUtils.replaceFirst("ABCabc123", "[a-z]", "_"));
2079         assertEquals("ABC_123abc", StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_"));
2080         assertEquals("ABC123abc", StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", ""));
2081         assertEquals("Lorem_ipsum  dolor   sit",
2082                      StringUtils.replaceFirst("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2"));
2083 
2084         assertThrows(PatternSyntaxException.class, () -> StringUtils.replaceFirst("any", "{badRegexSyntax}", ""),
2085                 "StringUtils.replaceFirst expecting PatternSyntaxException");
2086     }
2087 
2088     @Test
2089     void testReplaceIgnoreCase_StringStringString() {
2090         assertNull(StringUtils.replaceIgnoreCase(null, null, null));
2091         assertNull(StringUtils.replaceIgnoreCase(null, null, "any"));
2092         assertNull(StringUtils.replaceIgnoreCase(null, "any", null));
2093         assertNull(StringUtils.replaceIgnoreCase(null, "any", "any"));
2094 
2095         assertEquals("", StringUtils.replaceIgnoreCase("", null, null));
2096         assertEquals("", StringUtils.replaceIgnoreCase("", null, "any"));
2097         assertEquals("", StringUtils.replaceIgnoreCase("", "any", null));
2098         assertEquals("", StringUtils.replaceIgnoreCase("", "any", "any"));
2099 
2100         assertEquals("FOO", StringUtils.replaceIgnoreCase("FOO", "", "any"));
2101         assertEquals("FOO", StringUtils.replaceIgnoreCase("FOO", null, "any"));
2102         assertEquals("FOO", StringUtils.replaceIgnoreCase("FOO", "F", null));
2103         assertEquals("FOO", StringUtils.replaceIgnoreCase("FOO", null, null));
2104 
2105         assertEquals("", StringUtils.replaceIgnoreCase("foofoofoo", "foo", ""));
2106         assertEquals("barbarbar", StringUtils.replaceIgnoreCase("foofoofoo", "foo", "bar"));
2107         assertEquals("farfarfar", StringUtils.replaceIgnoreCase("foofoofoo", "oo", "ar"));
2108 
2109         // IgnoreCase
2110         assertEquals("", StringUtils.replaceIgnoreCase("foofoofoo", "FOO", ""));
2111         assertEquals("barbarbar", StringUtils.replaceIgnoreCase("fooFOOfoo", "foo", "bar"));
2112         assertEquals("farfarfar", StringUtils.replaceIgnoreCase("foofOOfoo", "OO", "ar"));
2113     }
2114 
2115     @Test
2116     void testReplaceIgnoreCase_StringStringStringInt() {
2117         assertNull(StringUtils.replaceIgnoreCase(null, null, null, 2));
2118         assertNull(StringUtils.replaceIgnoreCase(null, null, "any", 2));
2119         assertNull(StringUtils.replaceIgnoreCase(null, "any", null, 2));
2120         assertNull(StringUtils.replaceIgnoreCase(null, "any", "any", 2));
2121 
2122         assertEquals("", StringUtils.replaceIgnoreCase("", null, null, 2));
2123         assertEquals("", StringUtils.replaceIgnoreCase("", null, "any", 2));
2124         assertEquals("", StringUtils.replaceIgnoreCase("", "any", null, 2));
2125         assertEquals("", StringUtils.replaceIgnoreCase("", "any", "any", 2));
2126 
2127         final String str = new String(new char[] { 'o', 'o', 'f', 'o', 'o' });
2128         assertSame(str, StringUtils.replaceIgnoreCase(str, "x", "", -1));
2129 
2130         assertEquals("f", StringUtils.replaceIgnoreCase("oofoo", "o", "", -1));
2131         assertEquals("oofoo", StringUtils.replaceIgnoreCase("oofoo", "o", "", 0));
2132         assertEquals("ofoo", StringUtils.replaceIgnoreCase("oofoo", "o", "", 1));
2133         assertEquals("foo", StringUtils.replaceIgnoreCase("oofoo", "o", "", 2));
2134         assertEquals("fo", StringUtils.replaceIgnoreCase("oofoo", "o", "", 3));
2135         assertEquals("f", StringUtils.replaceIgnoreCase("oofoo", "o", "", 4));
2136 
2137         assertEquals("f", StringUtils.replaceIgnoreCase("oofoo", "o", "", -5));
2138         assertEquals("f", StringUtils.replaceIgnoreCase("oofoo", "o", "", 1000));
2139 
2140         // IgnoreCase
2141         assertEquals("f", StringUtils.replaceIgnoreCase("oofoo", "O", "", -1));
2142         assertEquals("oofoo", StringUtils.replaceIgnoreCase("oofoo", "O", "", 0));
2143         assertEquals("ofoo", StringUtils.replaceIgnoreCase("oofoo", "O", "", 1));
2144         assertEquals("foo", StringUtils.replaceIgnoreCase("oofoo", "O", "", 2));
2145         assertEquals("fo", StringUtils.replaceIgnoreCase("oofoo", "O", "", 3));
2146         assertEquals("f", StringUtils.replaceIgnoreCase("oofoo", "O", "", 4));
2147 
2148         assertEquals("f", StringUtils.replaceIgnoreCase("oofoo", "O", "", -5));
2149         assertEquals("f", StringUtils.replaceIgnoreCase("oofoo", "O", "", 1000));
2150     }
2151 
2152     @Test
2153     void testReplaceOnce_StringStringString() {
2154         assertNull(StringUtils.replaceOnce(null, null, null));
2155         assertNull(StringUtils.replaceOnce(null, null, "any"));
2156         assertNull(StringUtils.replaceOnce(null, "any", null));
2157         assertNull(StringUtils.replaceOnce(null, "any", "any"));
2158 
2159         assertEquals("", StringUtils.replaceOnce("", null, null));
2160         assertEquals("", StringUtils.replaceOnce("", null, "any"));
2161         assertEquals("", StringUtils.replaceOnce("", "any", null));
2162         assertEquals("", StringUtils.replaceOnce("", "any", "any"));
2163 
2164         assertEquals("FOO", StringUtils.replaceOnce("FOO", "", "any"));
2165         assertEquals("FOO", StringUtils.replaceOnce("FOO", null, "any"));
2166         assertEquals("FOO", StringUtils.replaceOnce("FOO", "F", null));
2167         assertEquals("FOO", StringUtils.replaceOnce("FOO", null, null));
2168 
2169         assertEquals("foofoo", StringUtils.replaceOnce("foofoofoo", "foo", ""));
2170     }
2171 
2172     @Test
2173     void testReplaceOnceIgnoreCase_StringStringString() {
2174         assertNull(StringUtils.replaceOnceIgnoreCase(null, null, null));
2175         assertNull(StringUtils.replaceOnceIgnoreCase(null, null, "any"));
2176         assertNull(StringUtils.replaceOnceIgnoreCase(null, "any", null));
2177         assertNull(StringUtils.replaceOnceIgnoreCase(null, "any", "any"));
2178 
2179         assertEquals("", StringUtils.replaceOnceIgnoreCase("", null, null));
2180         assertEquals("", StringUtils.replaceOnceIgnoreCase("", null, "any"));
2181         assertEquals("", StringUtils.replaceOnceIgnoreCase("", "any", null));
2182         assertEquals("", StringUtils.replaceOnceIgnoreCase("", "any", "any"));
2183 
2184         assertEquals("FOO", StringUtils.replaceOnceIgnoreCase("FOO", "", "any"));
2185         assertEquals("FOO", StringUtils.replaceOnceIgnoreCase("FOO", null, "any"));
2186         assertEquals("FOO", StringUtils.replaceOnceIgnoreCase("FOO", "F", null));
2187         assertEquals("FOO", StringUtils.replaceOnceIgnoreCase("FOO", null, null));
2188 
2189         assertEquals("foofoo", StringUtils.replaceOnceIgnoreCase("foofoofoo", "foo", ""));
2190 
2191         // Ignore Case
2192         assertEquals("Foofoo", StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", ""));
2193     }
2194 
2195     @Test
2196     void testReplacePattern_StringStringString() {
2197         assertNull(StringUtils.replacePattern(null, "", ""));
2198         assertEquals("any", StringUtils.replacePattern("any", null, ""));
2199         assertEquals("any", StringUtils.replacePattern("any", "", null));
2200 
2201         assertEquals("zzz", StringUtils.replacePattern("", "", "zzz"));
2202         assertEquals("zzz", StringUtils.replacePattern("", ".*", "zzz"));
2203         assertEquals("", StringUtils.replacePattern("", ".+", "zzz"));
2204 
2205         assertEquals("z", StringUtils.replacePattern("<__>\n<__>", "<.*>", "z"));
2206         assertEquals("z", StringUtils.replacePattern("<__>\\n<__>", "<.*>", "z"));
2207         assertEquals("X", StringUtils.replacePattern("<A>\nxy\n</A>", "<A>.*</A>", "X"));
2208 
2209         assertEquals("ABC___123", StringUtils.replacePattern("ABCabc123", "[a-z]", "_"));
2210         assertEquals("ABC_123", StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_"));
2211         assertEquals("ABC123", StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", ""));
2212         assertEquals("Lorem_ipsum_dolor_sit",
2213                      StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2"));
2214     }
2215 
2216     @Test
2217     void testReverse_String() {
2218         assertNull(StringUtils.reverse(null));
2219         assertEquals("", StringUtils.reverse(""));
2220         assertEquals("sdrawkcab", StringUtils.reverse("backwards"));
2221     }
2222 
2223     @Test
2224     void testReverseDelimited_StringChar() {
2225         assertNull(StringUtils.reverseDelimited(null, '.'));
2226         assertEquals("", StringUtils.reverseDelimited("", '.'));
2227         assertEquals("c.b.a", StringUtils.reverseDelimited("a.b.c", '.'));
2228         assertEquals("a b c", StringUtils.reverseDelimited("a b c", '.'));
2229         assertEquals("", StringUtils.reverseDelimited("", '.'));
2230     }
2231 
2232     @Test
2233     void testRightPad_StringInt() {
2234         assertNull(StringUtils.rightPad(null, 5));
2235         assertEquals("     ", StringUtils.rightPad("", 5));
2236         assertEquals("abc  ", StringUtils.rightPad("abc", 5));
2237         assertEquals("abc", StringUtils.rightPad("abc", 2));
2238         assertEquals("abc", StringUtils.rightPad("abc", -1));
2239         assertEquals("abc", StringUtils.rightPad("abc", Integer.MIN_VALUE));
2240     }
2241 
2242     @Test
2243     void testRightPad_StringIntChar() {
2244         assertNull(StringUtils.rightPad(null, 5, ' '));
2245         assertEquals("     ", StringUtils.rightPad("", 5, ' '));
2246         assertEquals("abc  ", StringUtils.rightPad("abc", 5, ' '));
2247         assertEquals("abc", StringUtils.rightPad("abc", 2, ' '));
2248         assertEquals("abc", StringUtils.rightPad("abc", -1, ' '));
2249         assertEquals("abcxx", StringUtils.rightPad("abc", 5, 'x'));
2250         assertEquals("abc", StringUtils.rightPad("abc", Integer.MIN_VALUE, ' '));
2251         final String str = StringUtils.rightPad("aaa", 10000, 'a');  // bigger than pad length
2252         assertEquals(10000, str.length());
2253         assertTrue(StringUtils.containsOnly(str, 'a'));
2254     }
2255 
2256     @Test
2257     void testRightPad_StringIntString() {
2258         assertNull(StringUtils.rightPad(null, 5, "-+"));
2259         assertEquals("     ", StringUtils.rightPad("", 5, " "));
2260         assertNull(StringUtils.rightPad(null, 8, null));
2261         assertEquals("abc-+-+", StringUtils.rightPad("abc", 7, "-+"));
2262         assertEquals("abc-+~", StringUtils.rightPad("abc", 6, "-+~"));
2263         assertEquals("abc-+", StringUtils.rightPad("abc", 5, "-+~"));
2264         assertEquals("abc", StringUtils.rightPad("abc", 2, " "));
2265         assertEquals("abc", StringUtils.rightPad("abc", -1, " "));
2266         assertEquals("abc  ", StringUtils.rightPad("abc", 5, null));
2267         assertEquals("abc  ", StringUtils.rightPad("abc", 5, ""));
2268         assertEquals("abc", StringUtils.rightPad("abc", Integer.MIN_VALUE, " "));
2269     }
2270 
2271     @Test
2272     void testRotate_StringInt() {
2273         assertNull(StringUtils.rotate(null, 1));
2274         assertEquals("", StringUtils.rotate("", 1));
2275         assertEquals("abcdefg", StringUtils.rotate("abcdefg", 0));
2276         assertEquals("fgabcde", StringUtils.rotate("abcdefg", 2));
2277         assertEquals("cdefgab", StringUtils.rotate("abcdefg", -2));
2278         assertEquals("abcdefg", StringUtils.rotate("abcdefg", 7));
2279         assertEquals("abcdefg", StringUtils.rotate("abcdefg", -7));
2280         assertEquals("fgabcde", StringUtils.rotate("abcdefg", 9));
2281         assertEquals("cdefgab", StringUtils.rotate("abcdefg", -9));
2282         assertEquals("efgabcd", StringUtils.rotate("abcdefg", 17));
2283         assertEquals("defgabc", StringUtils.rotate("abcdefg", -17));
2284     }
2285 
2286     @Test
2287     void testSplit_String() {
2288         assertNull(StringUtils.split(null));
2289         assertEquals(0, StringUtils.split("").length);
2290 
2291         String str = "a b  .c";
2292         String[] res = StringUtils.split(str);
2293         assertEquals(3, res.length);
2294         assertEquals("a", res[0]);
2295         assertEquals("b", res[1]);
2296         assertEquals(".c", res[2]);
2297 
2298         str = " a ";
2299         res = StringUtils.split(str);
2300         assertEquals(1, res.length);
2301         assertEquals("a", res[0]);
2302 
2303         str = "a" + WHITESPACE + "b" + NON_WHITESPACE + "c";
2304         res = StringUtils.split(str);
2305         assertEquals(2, res.length);
2306         assertEquals("a", res[0]);
2307         assertEquals("b" + NON_WHITESPACE + "c", res[1]);
2308     }
2309 
2310     @Test
2311     void testSplit_StringChar() {
2312         assertNull(StringUtils.split(null, '.'));
2313         assertEquals(0, StringUtils.split("", '.').length);
2314 
2315         String str = "a.b.. c";
2316         String[] res = StringUtils.split(str, '.');
2317         assertEquals(3, res.length);
2318         assertEquals("a", res[0]);
2319         assertEquals("b", res[1]);
2320         assertEquals(" c", res[2]);
2321 
2322         str = ".a.";
2323         res = StringUtils.split(str, '.');
2324         assertEquals(1, res.length);
2325         assertEquals("a", res[0]);
2326 
2327         str = "a b c";
2328         res = StringUtils.split(str, ' ');
2329         assertEquals(3, res.length);
2330         assertEquals("a", res[0]);
2331         assertEquals("b", res[1]);
2332         assertEquals("c", res[2]);
2333     }
2334 
2335     @Test
2336     void testSplit_StringString_StringStringInt() {
2337         assertNull(StringUtils.split(null, "."));
2338         assertNull(StringUtils.split(null, ".", 3));
2339 
2340         assertEquals(0, StringUtils.split("", ".").length);
2341         assertEquals(0, StringUtils.split("", ".", 3).length);
2342 
2343         innerTestSplit('.', ".", ' ');
2344         innerTestSplit('.', ".", ',');
2345         innerTestSplit('.', ".,", 'x');
2346         for (int i = 0; i < WHITESPACE.length(); i++) {
2347             for (int j = 0; j < NON_WHITESPACE.length(); j++) {
2348                 innerTestSplit(WHITESPACE.charAt(i), null, NON_WHITESPACE.charAt(j));
2349                 innerTestSplit(WHITESPACE.charAt(i), String.valueOf(WHITESPACE.charAt(i)), NON_WHITESPACE.charAt(j));
2350             }
2351         }
2352 
2353         String[] results;
2354         final String[] expectedResults = {"ab", "de fg"};
2355         results = StringUtils.split("ab   de fg", null, 2);
2356         assertEquals(expectedResults.length, results.length);
2357         for (int i = 0; i < expectedResults.length; i++) {
2358             assertEquals(expectedResults[i], results[i]);
2359         }
2360 
2361         final String[] expectedResults2 = {"ab", "cd:ef"};
2362         results = StringUtils.split("ab:cd:ef", ":", 2);
2363         assertEquals(expectedResults2.length, results.length);
2364         for (int i = 0; i < expectedResults2.length; i++) {
2365             assertEquals(expectedResults2[i], results[i]);
2366         }
2367     }
2368 
2369     @Test
2370     void testSplitByCharacterType() {
2371         assertNull(StringUtils.splitByCharacterType(null));
2372         assertEquals(0, StringUtils.splitByCharacterType("").length);
2373         assertArrayEquals(new String[] { "ab", " ", "de", " ", "fg" }, StringUtils.splitByCharacterType("ab de fg"));
2374         assertArrayEquals(new String[] { "ab", "   ", "de", " ", "fg" }, StringUtils.splitByCharacterType("ab   de fg"));
2375         assertArrayEquals(new String[] { "ab", ":", "cd", ":", "ef" }, StringUtils.splitByCharacterType("ab:cd:ef"));
2376         assertArrayEquals(new String[] { "number", "5" }, StringUtils.splitByCharacterType("number5"));
2377         assertArrayEquals(new String[] { "foo", "B", "ar" }, StringUtils.splitByCharacterType("fooBar"));
2378         assertArrayEquals(new String[] { "foo", "200", "B", "ar" }, StringUtils.splitByCharacterType("foo200Bar"));
2379         assertArrayEquals(new String[] { "ASFR", "ules" }, StringUtils.splitByCharacterType("ASFRules"));
2380         // Supplementary code points are classified by their own type, not split apart as surrogates.
2381         // U+1D400 MATHEMATICAL BOLD CAPITAL A is an upper-case letter, like ASCII 'A'.
2382         final String boldA = new String(Character.toChars(0x1D400));
2383         // U+1D7D3 MATHEMATICAL BOLD DIGIT FIVE is a decimal digit, like ASCII '5'.
2384         final String boldFive = new String(Character.toChars(0x1D7D3));
2385         assertArrayEquals(new String[] { "A" + boldA }, StringUtils.splitByCharacterType("A" + boldA));
2386         assertArrayEquals(new String[] { "5" + boldFive }, StringUtils.splitByCharacterType("5" + boldFive));
2387         assertArrayEquals(new String[] { boldA, "5" + boldFive, "z" }, StringUtils.splitByCharacterType(boldA + "5" + boldFive + "z"));
2388     }
2389 
2390     @Test
2391     void testSplitByCharacterTypeCamelCase() {
2392         assertNull(StringUtils.splitByCharacterTypeCamelCase(null));
2393         assertEquals(0, StringUtils.splitByCharacterTypeCamelCase("").length);
2394         assertArrayEquals(new String[] { "ab", " ", "de", " ", "fg" }, StringUtils.splitByCharacterTypeCamelCase("ab de fg"));
2395         assertArrayEquals(new String[] { "ab", "   ", "de", " ", "fg" }, StringUtils.splitByCharacterTypeCamelCase("ab   de fg"));
2396         assertArrayEquals(new String[] { "ab", ":", "cd", ":", "ef" }, StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef"));
2397         assertArrayEquals(new String[] { "number", "5" }, StringUtils.splitByCharacterTypeCamelCase("number5"));
2398         assertArrayEquals(new String[] { "foo", "Bar" }, StringUtils.splitByCharacterTypeCamelCase("fooBar"));
2399         assertArrayEquals(new String[] { "foo", "200", "Bar" }, StringUtils.splitByCharacterTypeCamelCase("foo200Bar"));
2400         assertArrayEquals(new String[] { "ASF", "Rules" }, StringUtils.splitByCharacterTypeCamelCase("ASFRules"));
2401         // A supplementary upper-case letter immediately before a lower-case run joins the following token,
2402         // exactly as a BMP upper-case letter does. U+1D400 MATHEMATICAL BOLD CAPITAL A is an upper-case letter.
2403         final String boldA = new String(Character.toChars(0x1D400));
2404         assertArrayEquals(new String[] { boldA + "bc" }, StringUtils.splitByCharacterTypeCamelCase(boldA + "bc"));
2405         assertArrayEquals(new String[] { "AB", boldA + "cd" }, StringUtils.splitByCharacterTypeCamelCase("AB" + boldA + "cd"));
2406         assertArrayEquals(new String[] { "foo", boldA + "bar" }, StringUtils.splitByCharacterTypeCamelCase("foo" + boldA + "bar"));
2407     }
2408 
2409     @Test
2410     void testSplitByWholeSeparatorPreserveAllTokens_StringString() {
2411         assertArrayEquals(null, StringUtils.splitByWholeSeparatorPreserveAllTokens(null, "."));
2412 
2413         assertEquals(0, StringUtils.splitByWholeSeparatorPreserveAllTokens("", ".").length);
2414 
2415         // test whitespace
2416         String input = "ab   de fg";
2417         String[] expected = {"ab", "", "", "de", "fg"};
2418 
2419         String[] actual = StringUtils.splitByWholeSeparatorPreserveAllTokens(input, null);
2420         assertEquals(expected.length, actual.length);
2421         for (int i = 0; i < actual.length; i += 1) {
2422             assertEquals(expected[i], actual[i]);
2423         }
2424 
2425         // test delimiter singlechar
2426         input = "1::2:::3::::4";
2427         expected = new String[]{"1", "", "2", "", "", "3", "", "", "", "4"};
2428 
2429         actual = StringUtils.splitByWholeSeparatorPreserveAllTokens(input, ":");
2430         assertEquals(expected.length, actual.length);
2431         for (int i = 0; i < actual.length; i += 1) {
2432             assertEquals(expected[i], actual[i]);
2433         }
2434 
2435         // test delimiter multichar
2436         input = "1::2:::3::::4";
2437         expected = new String[]{"1", "2", ":3", "", "4"};
2438 
2439         actual = StringUtils.splitByWholeSeparatorPreserveAllTokens(input, "::");
2440         assertEquals(expected.length, actual.length);
2441         for (int i = 0; i < actual.length; i += 1) {
2442             assertEquals(expected[i], actual[i]);
2443         }
2444     }
2445 
2446     @Test
2447     void testSplitByWholeSeparatorPreserveAllTokens_StringStringInt() {
2448         assertArrayEquals(null, StringUtils.splitByWholeSeparatorPreserveAllTokens(null, ".", -1));
2449 
2450         assertEquals(0, StringUtils.splitByWholeSeparatorPreserveAllTokens("", ".", -1).length);
2451 
2452         // test whitespace
2453         String input = "ab   de fg";
2454         String[] expected = {"ab", "", "", "de", "fg"};
2455 
2456         String[] actual = StringUtils.splitByWholeSeparatorPreserveAllTokens(input, null, -1);
2457         assertEquals(expected.length, actual.length);
2458         for (int i = 0; i < actual.length; i += 1) {
2459             assertEquals(expected[i], actual[i]);
2460         }
2461 
2462         // test delimiter singlechar
2463         input = "1::2:::3::::4";
2464         expected = new String[]{"1", "", "2", "", "", "3", "", "", "", "4"};
2465 
2466         actual = StringUtils.splitByWholeSeparatorPreserveAllTokens(input, ":", -1);
2467         assertEquals(expected.length, actual.length);
2468         for (int i = 0; i < actual.length; i += 1) {
2469             assertEquals(expected[i], actual[i]);
2470         }
2471 
2472         // test delimiter multichar
2473         input = "1::2:::3::::4";
2474         expected = new String[]{"1", "2", ":3", "", "4"};
2475 
2476         actual = StringUtils.splitByWholeSeparatorPreserveAllTokens(input, "::", -1);
2477         assertEquals(expected.length, actual.length);
2478         for (int i = 0; i < actual.length; i += 1) {
2479             assertEquals(expected[i], actual[i]);
2480         }
2481 
2482         // test delimiter char with max
2483         input = "1::2::3:4";
2484         expected = new String[]{"1", "", "2", ":3:4"};
2485 
2486         actual = StringUtils.splitByWholeSeparatorPreserveAllTokens(input, ":", 4);
2487         assertEquals(expected.length, actual.length);
2488         for (int i = 0; i < actual.length; i += 1) {
2489             assertEquals(expected[i], actual[i]);
2490         }
2491     }
2492 
2493     @Test
2494     void testSplitByWholeString_StringStringBoolean() {
2495         assertArrayEquals(null, StringUtils.splitByWholeSeparator(null, "."));
2496 
2497         assertEquals(0, StringUtils.splitByWholeSeparator("", ".").length);
2498 
2499         final String stringToSplitOnNulls = "ab   de fg";
2500         final String[] splitOnNullExpectedResults = {"ab", "de", "fg"};
2501 
2502         final String[] splitOnNullResults = StringUtils.splitByWholeSeparator(stringToSplitOnNulls, null);
2503         assertEquals(splitOnNullExpectedResults.length, splitOnNullResults.length);
2504         for (int i = 0; i < splitOnNullExpectedResults.length; i += 1) {
2505             assertEquals(splitOnNullExpectedResults[i], splitOnNullResults[i]);
2506         }
2507 
2508         final String stringToSplitOnCharactersAndString = "abstemiouslyaeiouyabstemiously";
2509 
2510         final String[] splitOnStringExpectedResults = {"abstemiously", "abstemiously"};
2511         final String[] splitOnStringResults = StringUtils.splitByWholeSeparator(stringToSplitOnCharactersAndString, "aeiouy");
2512         assertEquals(splitOnStringExpectedResults.length, splitOnStringResults.length);
2513         for (int i = 0; i < splitOnStringExpectedResults.length; i += 1) {
2514             assertEquals(splitOnStringExpectedResults[i], splitOnStringResults[i]);
2515         }
2516 
2517         final String[] splitWithMultipleSeparatorExpectedResults = {"ab", "cd", "ef"};
2518         final String[] splitWithMultipleSeparator = StringUtils.splitByWholeSeparator("ab:cd::ef", ":");
2519         assertEquals(splitWithMultipleSeparatorExpectedResults.length, splitWithMultipleSeparator.length);
2520         for (int i = 0; i < splitWithMultipleSeparatorExpectedResults.length; i++) {
2521             assertEquals(splitWithMultipleSeparatorExpectedResults[i], splitWithMultipleSeparator[i]);
2522         }
2523     }
2524 
2525     @Test
2526     void testSplitByWholeString_StringStringBooleanInt() {
2527         assertArrayEquals(null, StringUtils.splitByWholeSeparator(null, ".", 3));
2528 
2529         assertEquals(0, StringUtils.splitByWholeSeparator("", ".", 3).length);
2530 
2531         final String stringToSplitOnNulls = "ab   de fg";
2532         final String[] splitOnNullExpectedResults = {"ab", "de fg"};
2533         //String[] splitOnNullExpectedResults = { "ab", "de" } ;
2534 
2535         final String[] splitOnNullResults = StringUtils.splitByWholeSeparator(stringToSplitOnNulls, null, 2);
2536         assertEquals(splitOnNullExpectedResults.length, splitOnNullResults.length);
2537         for (int i = 0; i < splitOnNullExpectedResults.length; i += 1) {
2538             assertEquals(splitOnNullExpectedResults[i], splitOnNullResults[i]);
2539         }
2540 
2541         final String stringToSplitOnCharactersAndString = "abstemiouslyaeiouyabstemiouslyaeiouyabstemiously";
2542 
2543         final String[] splitOnStringExpectedResults = {"abstemiously", "abstemiouslyaeiouyabstemiously"};
2544         //String[] splitOnStringExpectedResults = { "abstemiously", "abstemiously" } ;
2545         final String[] splitOnStringResults = StringUtils.splitByWholeSeparator(stringToSplitOnCharactersAndString, "aeiouy", 2);
2546         assertEquals(splitOnStringExpectedResults.length, splitOnStringResults.length);
2547         for (int i = 0; i < splitOnStringExpectedResults.length; i++) {
2548             assertEquals(splitOnStringExpectedResults[i], splitOnStringResults[i]);
2549         }
2550     }
2551 
2552     @ParameterizedTest
2553     @CsvSource({
2554         "a:b:,       :,   'a,b'",
2555         "a:,         :,   a",
2556         "ab-!-cd-!-, -!-, 'ab,cd'",
2557     })
2558     void testSplitByWholeStringDropsTrailingEmpty(final String str, final String separator, final String expected) {
2559         final String[] expectedTokens = expected.split(",");
2560         // a trailing separator must not leak an empty token (it is dropped, like leading and adjacent ones)
2561         assertArrayEquals(expectedTokens, StringUtils.splitByWholeSeparator(str, separator));
2562         // the preserve-all-tokens variant still keeps the trailing empty token
2563         assertArrayEquals(ArrayUtils.add(expectedTokens, ""), StringUtils.splitByWholeSeparatorPreserveAllTokens(str, separator));
2564     }
2565 
2566     @Test
2567     void testSplitPreserveAllTokens_String() {
2568         assertNull(StringUtils.splitPreserveAllTokens(null));
2569         assertEquals(0, StringUtils.splitPreserveAllTokens("").length);
2570 
2571         String str = "abc def";
2572         String[] res = StringUtils.splitPreserveAllTokens(str);
2573         assertEquals(2, res.length);
2574         assertEquals("abc", res[0]);
2575         assertEquals("def", res[1]);
2576 
2577         str = "abc  def";
2578         res = StringUtils.splitPreserveAllTokens(str);
2579         assertEquals(3, res.length);
2580         assertEquals("abc", res[0]);
2581         assertEquals("", res[1]);
2582         assertEquals("def", res[2]);
2583 
2584         str = " abc ";
2585         res = StringUtils.splitPreserveAllTokens(str);
2586         assertEquals(3, res.length);
2587         assertEquals("", res[0]);
2588         assertEquals("abc", res[1]);
2589         assertEquals("", res[2]);
2590 
2591         str = "a b .c";
2592         res = StringUtils.splitPreserveAllTokens(str);
2593         assertEquals(3, res.length);
2594         assertEquals("a", res[0]);
2595         assertEquals("b", res[1]);
2596         assertEquals(".c", res[2]);
2597 
2598         str = " a b .c";
2599         res = StringUtils.splitPreserveAllTokens(str);
2600         assertEquals(4, res.length);
2601         assertEquals("", res[0]);
2602         assertEquals("a", res[1]);
2603         assertEquals("b", res[2]);
2604         assertEquals(".c", res[3]);
2605 
2606         str = "a  b  .c";
2607         res = StringUtils.splitPreserveAllTokens(str);
2608         assertEquals(5, res.length);
2609         assertEquals("a", res[0]);
2610         assertEquals("", res[1]);
2611         assertEquals("b", res[2]);
2612         assertEquals("", res[3]);
2613         assertEquals(".c", res[4]);
2614 
2615         str = " a  ";
2616         res = StringUtils.splitPreserveAllTokens(str);
2617         assertEquals(4, res.length);
2618         assertEquals("", res[0]);
2619         assertEquals("a", res[1]);
2620         assertEquals("", res[2]);
2621         assertEquals("", res[3]);
2622 
2623         str = " a  b";
2624         res = StringUtils.splitPreserveAllTokens(str);
2625         assertEquals(4, res.length);
2626         assertEquals("", res[0]);
2627         assertEquals("a", res[1]);
2628         assertEquals("", res[2]);
2629         assertEquals("b", res[3]);
2630 
2631         str = "a" + WHITESPACE + "b" + NON_WHITESPACE + "c";
2632         res = StringUtils.splitPreserveAllTokens(str);
2633         assertEquals(WHITESPACE.length() + 1, res.length);
2634         assertEquals("a", res[0]);
2635         for (int i = 1; i < WHITESPACE.length() - 1; i++) {
2636             assertEquals("", res[i]);
2637         }
2638         assertEquals("b" + NON_WHITESPACE + "c", res[WHITESPACE.length()]);
2639     }
2640 
2641     @Test
2642     void testSplitPreserveAllTokens_StringChar() {
2643         assertNull(StringUtils.splitPreserveAllTokens(null, '.'));
2644         assertEquals(0, StringUtils.splitPreserveAllTokens("", '.').length);
2645 
2646         String str = "a.b. c";
2647         String[] res = StringUtils.splitPreserveAllTokens(str, '.');
2648         assertEquals(3, res.length);
2649         assertEquals("a", res[0]);
2650         assertEquals("b", res[1]);
2651         assertEquals(" c", res[2]);
2652 
2653         str = "a.b.. c";
2654         res = StringUtils.splitPreserveAllTokens(str, '.');
2655         assertEquals(4, res.length);
2656         assertEquals("a", res[0]);
2657         assertEquals("b", res[1]);
2658         assertEquals("", res[2]);
2659         assertEquals(" c", res[3]);
2660 
2661         str = ".a.";
2662         res = StringUtils.splitPreserveAllTokens(str, '.');
2663         assertEquals(3, res.length);
2664         assertEquals("", res[0]);
2665         assertEquals("a", res[1]);
2666         assertEquals("", res[2]);
2667 
2668         str = ".a..";
2669         res = StringUtils.splitPreserveAllTokens(str, '.');
2670         assertEquals(4, res.length);
2671         assertEquals("", res[0]);
2672         assertEquals("a", res[1]);
2673         assertEquals("", res[2]);
2674         assertEquals("", res[3]);
2675 
2676         str = "..a.";
2677         res = StringUtils.splitPreserveAllTokens(str, '.');
2678         assertEquals(4, res.length);
2679         assertEquals("", res[0]);
2680         assertEquals("", res[1]);
2681         assertEquals("a", res[2]);
2682         assertEquals("", res[3]);
2683 
2684         str = "..a";
2685         res = StringUtils.splitPreserveAllTokens(str, '.');
2686         assertEquals(3, res.length);
2687         assertEquals("", res[0]);
2688         assertEquals("", res[1]);
2689         assertEquals("a", res[2]);
2690 
2691         str = "a b c";
2692         res = StringUtils.splitPreserveAllTokens(str, ' ');
2693         assertEquals(3, res.length);
2694         assertEquals("a", res[0]);
2695         assertEquals("b", res[1]);
2696         assertEquals("c", res[2]);
2697 
2698         str = "a  b  c";
2699         res = StringUtils.splitPreserveAllTokens(str, ' ');
2700         assertEquals(5, res.length);
2701         assertEquals("a", res[0]);
2702         assertEquals("", res[1]);
2703         assertEquals("b", res[2]);
2704         assertEquals("", res[3]);
2705         assertEquals("c", res[4]);
2706 
2707         str = " a b c";
2708         res = StringUtils.splitPreserveAllTokens(str, ' ');
2709         assertEquals(4, res.length);
2710         assertEquals("", res[0]);
2711         assertEquals("a", res[1]);
2712         assertEquals("b", res[2]);
2713         assertEquals("c", res[3]);
2714 
2715         str = "  a b c";
2716         res = StringUtils.splitPreserveAllTokens(str, ' ');
2717         assertEquals(5, res.length);
2718         assertEquals("", res[0]);
2719         assertEquals("", res[1]);
2720         assertEquals("a", res[2]);
2721         assertEquals("b", res[3]);
2722         assertEquals("c", res[4]);
2723 
2724         str = "a b c ";
2725         res = StringUtils.splitPreserveAllTokens(str, ' ');
2726         assertEquals(4, res.length);
2727         assertEquals("a", res[0]);
2728         assertEquals("b", res[1]);
2729         assertEquals("c", res[2]);
2730         assertEquals("", res[3]);
2731 
2732         str = "a b c  ";
2733         res = StringUtils.splitPreserveAllTokens(str, ' ');
2734         assertEquals(5, res.length);
2735         assertEquals("a", res[0]);
2736         assertEquals("b", res[1]);
2737         assertEquals("c", res[2]);
2738         assertEquals("", res[3]);
2739         assertEquals("", res[4]);
2740 
2741         // Match example in javadoc
2742         {
2743             final String[] results;
2744             final String[] expectedResults = {"a", "", "b", "c"};
2745             results = StringUtils.splitPreserveAllTokens("a..b.c", '.');
2746             assertEquals(expectedResults.length, results.length);
2747             for (int i = 0; i < expectedResults.length; i++) {
2748                 assertEquals(expectedResults[i], results[i]);
2749             }
2750         }
2751     }
2752 
2753     @Test
2754     void testSplitPreserveAllTokens_StringString_StringStringInt() {
2755         assertNull(StringUtils.splitPreserveAllTokens(null, "."));
2756         assertNull(StringUtils.splitPreserveAllTokens(null, ".", 3));
2757 
2758         assertEquals(0, StringUtils.splitPreserveAllTokens("", ".").length);
2759         assertEquals(0, StringUtils.splitPreserveAllTokens("", ".", 3).length);
2760 
2761         innerTestSplitPreserveAllTokens('.', ".", ' ');
2762         innerTestSplitPreserveAllTokens('.', ".", ',');
2763         innerTestSplitPreserveAllTokens('.', ".,", 'x');
2764         for (int i = 0; i < WHITESPACE.length(); i++) {
2765             for (int j = 0; j < NON_WHITESPACE.length(); j++) {
2766                 innerTestSplitPreserveAllTokens(WHITESPACE.charAt(i), null, NON_WHITESPACE.charAt(j));
2767                 innerTestSplitPreserveAllTokens(WHITESPACE.charAt(i), String.valueOf(WHITESPACE.charAt(i)), NON_WHITESPACE.charAt(j));
2768             }
2769         }
2770 
2771         {
2772             final String[] results;
2773             final String[] expectedResults = {"ab", "de fg"};
2774             results = StringUtils.splitPreserveAllTokens("ab de fg", null, 2);
2775             assertEquals(expectedResults.length, results.length);
2776             for (int i = 0; i < expectedResults.length; i++) {
2777                 assertEquals(expectedResults[i], results[i]);
2778             }
2779         }
2780 
2781         {
2782             final String[] results;
2783             final String[] expectedResults = {"ab", "  de fg"};
2784             results = StringUtils.splitPreserveAllTokens("ab   de fg", null, 2);
2785             assertEquals(expectedResults.length, results.length);
2786             for (int i = 0; i < expectedResults.length; i++) {
2787                 assertEquals(expectedResults[i], results[i]);
2788             }
2789         }
2790 
2791         {
2792             final String[] results;
2793             final String[] expectedResults = {"ab", "::de:fg"};
2794             results = StringUtils.splitPreserveAllTokens("ab:::de:fg", ":", 2);
2795             assertEquals(expectedResults.length, results.length);
2796             for (int i = 0; i < expectedResults.length; i++) {
2797                 assertEquals(expectedResults[i], results[i]);
2798             }
2799         }
2800 
2801         {
2802             final String[] results;
2803             final String[] expectedResults = {"ab", "", " de fg"};
2804             results = StringUtils.splitPreserveAllTokens("ab   de fg", null, 3);
2805             assertEquals(expectedResults.length, results.length);
2806             for (int i = 0; i < expectedResults.length; i++) {
2807                 assertEquals(expectedResults[i], results[i]);
2808             }
2809         }
2810 
2811         {
2812             final String[] results;
2813             final String[] expectedResults = {"ab", "", "", "de fg"};
2814             results = StringUtils.splitPreserveAllTokens("ab   de fg", null, 4);
2815             assertEquals(expectedResults.length, results.length);
2816             for (int i = 0; i < expectedResults.length; i++) {
2817                 assertEquals(expectedResults[i], results[i]);
2818             }
2819         }
2820 
2821         {
2822             final String[] expectedResults = {"ab", "cd:ef"};
2823             final String[] results;
2824             results = StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2);
2825             assertEquals(expectedResults.length, results.length);
2826             for (int i = 0; i < expectedResults.length; i++) {
2827                 assertEquals(expectedResults[i], results[i]);
2828             }
2829         }
2830 
2831         {
2832             final String[] results;
2833             final String[] expectedResults = {"ab", ":cd:ef"};
2834             results = StringUtils.splitPreserveAllTokens("ab::cd:ef", ":", 2);
2835             assertEquals(expectedResults.length, results.length);
2836             for (int i = 0; i < expectedResults.length; i++) {
2837                 assertEquals(expectedResults[i], results[i]);
2838             }
2839         }
2840 
2841         {
2842             final String[] results;
2843             final String[] expectedResults = {"ab", "", ":cd:ef"};
2844             results = StringUtils.splitPreserveAllTokens("ab:::cd:ef", ":", 3);
2845             assertEquals(expectedResults.length, results.length);
2846             for (int i = 0; i < expectedResults.length; i++) {
2847                 assertEquals(expectedResults[i], results[i]);
2848             }
2849         }
2850 
2851         {
2852             final String[] results;
2853             final String[] expectedResults = {"ab", "", "", "cd:ef"};
2854             results = StringUtils.splitPreserveAllTokens("ab:::cd:ef", ":", 4);
2855             assertEquals(expectedResults.length, results.length);
2856             for (int i = 0; i < expectedResults.length; i++) {
2857                 assertEquals(expectedResults[i], results[i]);
2858             }
2859         }
2860 
2861         {
2862             final String[] results;
2863             final String[] expectedResults = {"", "ab", "", "", "cd:ef"};
2864             results = StringUtils.splitPreserveAllTokens(":ab:::cd:ef", ":", 5);
2865             assertEquals(expectedResults.length, results.length);
2866             for (int i = 0; i < expectedResults.length; i++) {
2867                 assertEquals(expectedResults[i], results[i]);
2868             }
2869         }
2870 
2871         {
2872             final String[] results;
2873             final String[] expectedResults = {"", "", "ab", "", "", "cd:ef"};
2874             results = StringUtils.splitPreserveAllTokens("::ab:::cd:ef", ":", 6);
2875             assertEquals(expectedResults.length, results.length);
2876             for (int i = 0; i < expectedResults.length; i++) {
2877                 assertEquals(expectedResults[i], results[i]);
2878             }
2879         }
2880 
2881     }
2882 
2883     // Methods on StringUtils that are immutable in spirit (i.e. calculate the length)
2884     // should take a CharSequence parameter. Methods that are mutable in spirit (i.e. capitalize)
2885     // should take a String or String[] parameter and return String or String[].
2886     // This test enforces that this is done.
2887     @Test
2888     void testStringUtilsCharSequenceContract() {
2889         final Class<StringUtils> c = StringUtils.class;
2890         // Methods that are expressly excluded from testStringUtilsCharSequenceContract()
2891         final String[] excludeMethods = {
2892             "public static int org.apache.commons.lang3.StringUtils.compare(java.lang.String,java.lang.String)",
2893             "public static int org.apache.commons.lang3.StringUtils.compare(java.lang.String,java.lang.String,boolean)",
2894             "public static int org.apache.commons.lang3.StringUtils.compareIgnoreCase(java.lang.String,java.lang.String)",
2895             "public static int org.apache.commons.lang3.StringUtils.compareIgnoreCase(java.lang.String,java.lang.String,boolean)",
2896             "public static byte[] org.apache.commons.lang3.StringUtils.getBytes(java.lang.String,java.nio.charset.Charset)",
2897             "public static byte[] org.apache.commons.lang3.StringUtils.getBytes(java.lang.String,java.lang.String) throws java.io.UnsupportedEncodingException"
2898         };
2899         final Method[] methods = c.getMethods();
2900 
2901         for (final Method m : methods) {
2902             final String methodStr = m.toString();
2903             if (m.getReturnType() == String.class || m.getReturnType() == String[].class) {
2904                 // Assume this is mutable and ensure the first parameter is not CharSequence.
2905                 // It may be String or it may be something else (String[], Object, Object[]) so
2906                 // don't actively test for that.
2907                 final Class<?>[] params = m.getParameterTypes();
2908                 if (params.length > 0 && (params[0] == CharSequence.class || params[0] == CharSequence[].class)) {
2909                     assertFalse(ArrayUtils.contains(excludeMethods, methodStr), "The method \"" + methodStr + "\" appears to be mutable in spirit and therefore must not accept a CharSequence");
2910                 }
2911             } else {
2912                 // Assume this is immutable in spirit and ensure the first parameter is not String.
2913                 // As above, it may be something other than CharSequence.
2914                 final Class<?>[] params = m.getParameterTypes();
2915                 if (params.length > 0 && (params[0] == String.class || params[0] == String[].class)) {
2916                     assertTrue(ArrayUtils.contains(excludeMethods, methodStr),
2917                             "The method \"" + methodStr + "\" appears to be immutable in spirit and therefore must not accept a String");
2918                 }
2919             }
2920         }
2921     }
2922 
2923     @Test
2924     void testSwapCase_String() {
2925         assertNull(StringUtils.swapCase(null));
2926         assertEquals("", StringUtils.swapCase(""));
2927         assertEquals("  ", StringUtils.swapCase("  "));
2928 
2929         assertEquals("i", WordUtils.swapCase("I"));
2930         assertEquals("I", WordUtils.swapCase("i"));
2931         assertEquals("I AM HERE 123", StringUtils.swapCase("i am here 123"));
2932         assertEquals("i aM hERE 123", StringUtils.swapCase("I Am Here 123"));
2933         assertEquals("I AM here 123", StringUtils.swapCase("i am HERE 123"));
2934         assertEquals("i am here 123", StringUtils.swapCase("I AM HERE 123"));
2935 
2936         final String test = "This String contains a TitleCase character: \u01C8";
2937         final String expect = "tHIS sTRING CONTAINS A tITLEcASE CHARACTER: \u01C9";
2938         assertEquals(expect, WordUtils.swapCase(test));
2939         assertEquals(expect, StringUtils.swapCase(test));
2940     }
2941 
2942     @Test
2943     void testToCodePoints() {
2944         final int orphanedHighSurrogate = 0xD801;
2945         final int orphanedLowSurrogate = 0xDC00;
2946         final int supplementary = 0x2070E;
2947         final int[] codePoints = { 'a', orphanedHighSurrogate, 'b', 'c', supplementary, 'd', orphanedLowSurrogate, 'e' };
2948         final String s = new String(codePoints, 0, codePoints.length);
2949         assertArrayEquals(codePoints, StringUtils.toCodePoints(s));
2950         assertNull(StringUtils.toCodePoints(null));
2951         assertArrayEquals(ArrayUtils.EMPTY_INT_ARRAY, StringUtils.toCodePoints(""));
2952         assertArrayEquals(new int[] { 'a' }, StringUtils.toCodePoints("a"));
2953         assertArrayEquals(new int[] { 'a', 'b' }, StringUtils.toCodePoints("ab"));
2954         assertArrayEquals(new int[] { 'a', 'b', 'c' }, StringUtils.toCodePoints("abc"));
2955     }
2956 
2957     @Test
2958     void testToCodePointsEmoji() {
2959         assertArrayEquals(ArrayFill.fill(new int[14], 129418), StringUtils.toCodePoints("🦊🦊🦊🦊🦊🦊🦊🦊🦊🦊🦊🦊🦊🦊"));
2960         assertArrayEquals(new int[] { 128105, 127995, 8205, 128104, 127995, 8205, 128102, 127995, 8205, 128102, 127995, 128105, 127996, 8205, 128104, 127996,
2961                 8205, 128102, 127996, 8205, 128102, 127996, 128105, 127997, 8205, 128104, 127997, 8205, 128102, 127997, 8205, 128102, 127997, 128105, 127998,
2962                 8205, 128104, 127998, 8205, 128102, 127998, 8205, 128102, 127998, 128105, 127999, 8205, 128104, 127999, 8205, 128102, 127999, 8205, 128102,
2963                 127999, 128105, 127995, 8205, 128104, 127995, 8205, 128102, 127995, 8205, 128102, 127995, 128105, 127996, 8205, 128104, 127996, 8205, 128102,
2964                 127996, 8205, 128102, 127996, 128105, 127997, 8205, 128104, 127997, 8205, 128102, 127997, 8205, 128102, 127997, 128105, 127998, 8205, 128104,
2965                 127998, 8205, 128102, 127998, 8205, 128102, 127998, 128105, 127999, 8205, 128104, 127999, 8205, 128102, 127999, 8205, 128102, 127999 },
2966                 StringUtils.toCodePoints(
2967                         "👩🏻‍👨🏻‍👦🏻‍👦🏻👩🏼‍👨🏼‍👦🏼‍👦🏼👩🏽‍👨🏽‍👦🏽‍👦🏽👩🏾‍👨🏾‍👦🏾‍👦🏾👩🏿‍👨🏿‍👦🏿‍👦🏿👩🏻‍👨🏻‍👦🏻‍👦🏻👩🏼‍👨🏼‍👦🏼‍👦🏼👩🏽‍👨🏽‍👦🏽‍👦🏽👩🏾‍👨🏾‍👦🏾‍👦🏾👩🏿‍👨🏿‍👦🏿‍👦🏿"));
2968     }
2969 
2970     /**
2971      * Tests {@link StringUtils#toEncodedString(byte[], Charset)}
2972      *
2973      * @see StringUtils#toEncodedString(byte[], Charset)
2974      */
2975     @Test
2976     void testToEncodedString() {
2977         final String expectedString = "The quick brown fox jumps over the lazy dog.";
2978         String encoding = SystemUtils.FILE_ENCODING;
2979         byte[] expectedBytes = expectedString.getBytes(Charset.defaultCharset());
2980         // sanity check start
2981         assertArrayEquals(expectedBytes, expectedString.getBytes());
2982         // sanity check end
2983         assertEquals(expectedString, StringUtils.toEncodedString(expectedBytes, Charset.defaultCharset()));
2984         assertEquals(expectedString, StringUtils.toEncodedString(expectedBytes, Charset.forName(encoding)));
2985         encoding = StandardCharsets.UTF_16.name();
2986         expectedBytes = expectedString.getBytes(Charset.forName(encoding));
2987         assertEquals(expectedString, StringUtils.toEncodedString(expectedBytes, Charset.forName(encoding)));
2988     }
2989 
2990     @Test
2991     @ReadsDefaultLocale
2992     @WritesDefaultLocale
2993     void testToRootLowerCase() {
2994         assertNull(StringUtils.toRootLowerCase(null));
2995         assertEquals("a", StringUtils.toRootLowerCase("A"));
2996         assertEquals("a", StringUtils.toRootLowerCase("a"));
2997         final Locale TURKISH = Locale.forLanguageTag("tr");
2998         // Sanity checks:
2999         assertNotEquals("title", "TITLE".toLowerCase(TURKISH));
3000         assertEquals("title", "TITLE".toLowerCase(Locale.ROOT));
3001         assertEquals("title", StringUtils.toRootLowerCase("TITLE"));
3002     }
3003 
3004     @Test
3005     @DefaultLocale("tr")
3006     @ReadsDefaultLocale
3007     void testToRootLowerCaseTurkish() {
3008         assertEquals("title", StringUtils.toRootLowerCase("TITLE"));
3009     }
3010 
3011     @Test
3012     @ReadsDefaultLocale
3013     @WritesDefaultLocale
3014     void testToRootUpperCase() {
3015         assertNull(StringUtils.toRootUpperCase(null));
3016         assertEquals("A", StringUtils.toRootUpperCase("a"));
3017         assertEquals("A", StringUtils.toRootUpperCase("A"));
3018         final Locale TURKISH = Locale.forLanguageTag("tr");
3019         // Sanity checks:
3020         assertNotEquals("TITLE", "title".toUpperCase(TURKISH));
3021         assertEquals("TITLE", "title".toUpperCase(Locale.ROOT));
3022         assertEquals("TITLE", StringUtils.toRootUpperCase("title"));
3023         // Make sure we are not using the default Locale:
3024         final Locale defaultLocale = Locale.getDefault();
3025         try {
3026             Locale.setDefault(TURKISH);
3027             assertEquals("TITLE", StringUtils.toRootUpperCase("title"));
3028         } finally {
3029             Locale.setDefault(defaultLocale);
3030         }
3031     }
3032 
3033     /**
3034      * Tests {@link StringUtils#toString(byte[], String)}
3035      *
3036      * @throws UnsupportedEncodingException Thrown if the method under test throws an exception.
3037      * @see StringUtils#toString(byte[], String)
3038      */
3039     @Test
3040     void testToString() throws UnsupportedEncodingException {
3041         final String expectedString = "The quick brown fox jumps over the lazy dog.";
3042         byte[] expectedBytes = expectedString.getBytes(Charset.defaultCharset());
3043         // sanity check start
3044         assertArrayEquals(expectedBytes, expectedString.getBytes());
3045         // sanity check end
3046         assertEquals(expectedString, StringUtils.toString(expectedBytes, null));
3047         assertEquals(expectedString, StringUtils.toString(expectedBytes, SystemUtils.FILE_ENCODING));
3048         final String encoding = StandardCharsets.UTF_16.name();
3049         expectedBytes = expectedString.getBytes(Charset.forName(encoding));
3050         assertEquals(expectedString, StringUtils.toString(expectedBytes, encoding));
3051     }
3052 
3053     @Test
3054     void testTruncate_StringInt() {
3055         assertNull(StringUtils.truncate(null, 12));
3056         assertIllegalArgumentException(() -> StringUtils.truncate(null, -1), "maxWidth cannot be negative");
3057         assertIllegalArgumentException(() -> StringUtils.truncate(null, -10), "maxWidth cannot be negative");
3058         assertIllegalArgumentException(() -> StringUtils.truncate(null, Integer.MIN_VALUE), "maxWidth cannot be negative");
3059         assertEquals("", StringUtils.truncate("", 10));
3060         assertEquals("abc", StringUtils.truncate("abcdefghij", 3));
3061         assertEquals("abcdef", StringUtils.truncate("abcdefghij", 6));
3062         assertEquals("", StringUtils.truncate("abcdefghij", 0));
3063         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", -1), "maxWidth cannot be negative");
3064         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", -100), "maxWidth cannot be negative");
3065         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", Integer.MIN_VALUE), "maxWidth cannot be negative");
3066         assertEquals("abcdefghij", StringUtils.truncate("abcdefghijklmno", 10));
3067         assertEquals("abcdefghijklmno", StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE));
3068         assertEquals("abcde", StringUtils.truncate("abcdefghijklmno", 5));
3069         assertEquals("abc", StringUtils.truncate("abcdefghijklmno", 3));
3070     }
3071 
3072     @Test
3073     void testTruncate_StringIntInt() {
3074         assertNull(StringUtils.truncate(null, 0, 12));
3075         assertIllegalArgumentException(() -> StringUtils.truncate(null, -1, 0), "offset cannot be negative");
3076         assertIllegalArgumentException(() -> StringUtils.truncate(null, -10, -4), "offset cannot be negative");
3077         assertIllegalArgumentException(() -> StringUtils.truncate(null, Integer.MIN_VALUE, Integer.MIN_VALUE), "offset cannot be negative");
3078         assertNull(StringUtils.truncate(null, 10, 12));
3079         assertEquals("", StringUtils.truncate("", 0, 10));
3080         assertEquals("", StringUtils.truncate("", 2, 10));
3081         assertEquals("abc", StringUtils.truncate("abcdefghij", 0, 3));
3082         assertEquals("fghij", StringUtils.truncate("abcdefghij", 5, 6));
3083         assertEquals("", StringUtils.truncate("abcdefghij", 0, 0));
3084         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", 0, -1), "maxWidth cannot be negative");
3085         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", 0, -10), "maxWidth cannot be negative");
3086         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", 0, -100), "maxWidth cannot be negative");
3087         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", 1, -100), "maxWidth cannot be negative");
3088         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", 0, Integer.MIN_VALUE), "maxWidth cannot be negative");
3089         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", -1, 0), "offset cannot be negative");
3090         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", -10, 0), "offset cannot be negative");
3091         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", -100, 1), "offset cannot be negative");
3092         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", Integer.MIN_VALUE, 0), "offset cannot be negative");
3093         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", -1, -1), "offset cannot be negative");
3094         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", -10, -10), "offset cannot be negative");
3095         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", -100, -100), "offset cannot be negative");
3096         assertIllegalArgumentException(() -> StringUtils.truncate("abcdefghij", Integer.MIN_VALUE, Integer.MIN_VALUE),
3097                 "offset cannot be negative");
3098         final String raspberry = "raspberry peach";
3099         assertEquals("peach", StringUtils.truncate(raspberry, 10, 15));
3100         assertEquals("abcdefghij", StringUtils.truncate("abcdefghijklmno", 0, 10));
3101         assertEquals("abcdefghijklmno", StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE));
3102         assertEquals("bcdefghijk", StringUtils.truncate("abcdefghijklmno", 1, 10));
3103         assertEquals("cdefghijkl", StringUtils.truncate("abcdefghijklmno", 2, 10));
3104         assertEquals("defghijklm", StringUtils.truncate("abcdefghijklmno", 3, 10));
3105         assertEquals("efghijklmn", StringUtils.truncate("abcdefghijklmno", 4, 10));
3106         assertEquals("fghijklmno", StringUtils.truncate("abcdefghijklmno", 5, 10));
3107         assertEquals("fghij", StringUtils.truncate("abcdefghijklmno", 5, 5));
3108         assertEquals("fgh", StringUtils.truncate("abcdefghijklmno", 5, 3));
3109         assertEquals("klm", StringUtils.truncate("abcdefghijklmno", 10, 3));
3110         assertEquals("klmno", StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE));
3111         assertEquals("n", StringUtils.truncate("abcdefghijklmno", 13, 1));
3112         assertEquals("no", StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE));
3113         assertEquals("o", StringUtils.truncate("abcdefghijklmno", 14, 1));
3114         assertEquals("o", StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE));
3115         assertEquals("", StringUtils.truncate("abcdefghijklmno", 15, 1));
3116         assertEquals("", StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE));
3117         assertEquals("", StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE));
3118     }
3119 
3120     @Test
3121     void testTruncate_StringIntInt_surrogatePair() {
3122         // U+1F600 GRINNING FACE is a single supplementary code point stored as a surrogate pair
3123         final String grin = "😀";
3124         // a cut that would land between the two halves keeps the result well formed instead of emitting a lone surrogate
3125         assertEquals("a", StringUtils.truncate("a" + grin + "b", 0, 2));
3126         assertEquals(grin, StringUtils.truncate("a" + grin + "b", 1, 2));
3127         assertEquals("ab", StringUtils.truncate("ab" + grin, 0, 3));
3128         // an offset that lands inside a pair skips the orphaned low surrogate
3129         assertEquals("a", StringUtils.truncate(grin + "ab", 1, 2));
3130         // an input that is only the pair stays whole or drops to empty, never a lone surrogate
3131         assertEquals(grin, StringUtils.truncate(grin, 0, 2));
3132         assertEquals(grin, StringUtils.truncate(grin, 0, 3));
3133         assertEquals("", StringUtils.truncate(grin, 0, 0));
3134         assertEquals("", StringUtils.truncate(grin, 0, 1));
3135         assertEquals("", StringUtils.truncate(grin, 1, 1));
3136         assertEquals("", StringUtils.truncate(grin, 1, 2));
3137         assertEquals("", StringUtils.truncate(grin, 2, 2));
3138     }
3139 
3140     @Test
3141     void testUnCapitalize() {
3142         assertNull(StringUtils.uncapitalize(null));
3143 
3144         assertEquals(FOO_UNCAP, StringUtils.uncapitalize(FOO_CAP), "uncapitalize(String) failed");
3145         assertEquals(FOO_UNCAP, StringUtils.uncapitalize(FOO_UNCAP), "uncapitalize(string) failed");
3146         assertEquals("", StringUtils.uncapitalize(""), "uncapitalize(empty-string) failed");
3147         assertEquals("x", StringUtils.uncapitalize("X"), "uncapitalize(single-char-string) failed");
3148 
3149         // Examples from uncapitalize Javadoc
3150         assertEquals("cat", StringUtils.uncapitalize("cat"));
3151         assertEquals("cat", StringUtils.uncapitalize("Cat"));
3152         assertEquals("cAT", StringUtils.uncapitalize("CAT"));
3153     }
3154 
3155     @Test
3156     void testUnescapeSurrogatePairs() {
3157         assertEquals("\uD83D\uDE30", StringEscapeUtils.unescapeCsv("\uD83D\uDE30"));
3158         // Examples from https://en.wikipedia.org/wiki/UTF-16
3159         assertEquals("\uD800\uDC00", StringEscapeUtils.unescapeCsv("\uD800\uDC00"));
3160         assertEquals("\uD834\uDD1E", StringEscapeUtils.unescapeCsv("\uD834\uDD1E"));
3161         assertEquals("\uDBFF\uDFFD", StringEscapeUtils.unescapeCsv("\uDBFF\uDFFD"));
3162         assertEquals("\uDBFF\uDFFD", StringEscapeUtils.unescapeHtml3("\uDBFF\uDFFD"));
3163         assertEquals("\uDBFF\uDFFD", StringEscapeUtils.unescapeHtml4("\uDBFF\uDFFD"));
3164     }
3165 
3166     @Test
3167     void testUnwrap_StringChar() {
3168         assertNull(StringUtils.unwrap(null, null));
3169         assertNull(StringUtils.unwrap(null, CharUtils.NUL));
3170         assertNull(StringUtils.unwrap(null, '1'));
3171 
3172         assertEquals("abc", StringUtils.unwrap("abc", null));
3173         assertEquals("a", StringUtils.unwrap("a", "a"));
3174         assertEquals("", StringUtils.unwrap("aa", "a"));
3175         assertEquals("abc", StringUtils.unwrap("\'abc\'", '\''));
3176         assertEquals("abc", StringUtils.unwrap("AabcA", 'A'));
3177         assertEquals("AabcA", StringUtils.unwrap("AAabcAA", 'A'));
3178         assertEquals("abc", StringUtils.unwrap("abc", 'b'));
3179         assertEquals("#A", StringUtils.unwrap("#A", '#'));
3180         assertEquals("A#", StringUtils.unwrap("A#", '#'));
3181         assertEquals("ABA", StringUtils.unwrap("AABAA", 'A'));
3182     }
3183 
3184     @Test
3185     void testUnwrap_StringString() {
3186         assertNull(StringUtils.unwrap(null, null));
3187         assertNull(StringUtils.unwrap(null, ""));
3188         assertNull(StringUtils.unwrap(null, "1"));
3189 
3190         assertEquals("abc", StringUtils.unwrap("abc", null));
3191         assertEquals("abc", StringUtils.unwrap("abc", ""));
3192         assertEquals("a", StringUtils.unwrap("a", "a"));
3193         assertEquals("ababa", StringUtils.unwrap("ababa", "aba"));
3194         assertEquals("", StringUtils.unwrap("aa", "a"));
3195         assertEquals("abc", StringUtils.unwrap("\'abc\'", "\'"));
3196         assertEquals("abc", StringUtils.unwrap("\"abc\"", "\""));
3197         assertEquals("abc\"xyz", StringUtils.unwrap("\"abc\"xyz\"", "\""));
3198         assertEquals("abc\"xyz\"", StringUtils.unwrap("\"abc\"xyz\"\"", "\""));
3199         assertEquals("abc\'xyz\'", StringUtils.unwrap("\"abc\'xyz\'\"", "\""));
3200         assertEquals("\"abc\'xyz\'\"", StringUtils.unwrap("AA\"abc\'xyz\'\"AA", "AA"));
3201         assertEquals("\"abc\'xyz\'\"", StringUtils.unwrap("123\"abc\'xyz\'\"123", "123"));
3202         assertEquals("AA\"abc\'xyz\'\"", StringUtils.unwrap("AA\"abc\'xyz\'\"", "AA"));
3203         assertEquals("AA\"abc\'xyz\'\"AA", StringUtils.unwrap("AAA\"abc\'xyz\'\"AAA", "A"));
3204         assertEquals("\"abc\'xyz\'\"AA", StringUtils.unwrap("\"abc\'xyz\'\"AA", "AA"));
3205     }
3206 
3207     @Test
3208     void testUpperCase() {
3209         assertNull(StringUtils.upperCase(null));
3210         assertNull(StringUtils.upperCase(null, Locale.ENGLISH));
3211         assertEquals("FOO TEST THING", StringUtils.upperCase("fOo test THING"), "upperCase(String) failed");
3212         assertEquals("", StringUtils.upperCase(""), "upperCase(empty-string) failed");
3213         assertEquals("FOO TEST THING", StringUtils.upperCase("fOo test THING", Locale.ENGLISH),
3214                 "upperCase(String, Locale) failed");
3215         assertEquals("", StringUtils.upperCase("", Locale.ENGLISH),
3216                 "upperCase(empty-string, Locale) failed");
3217     }
3218 
3219     @Test
3220     void testWrap_StringChar() {
3221         assertNull(StringUtils.wrap(null, CharUtils.NUL));
3222         assertNull(StringUtils.wrap(null, '1'));
3223 
3224         assertEquals("", StringUtils.wrap("", CharUtils.NUL));
3225         assertEquals("xabx", StringUtils.wrap("ab", 'x'));
3226         assertEquals("\"ab\"", StringUtils.wrap("ab", '\"'));
3227         assertEquals("\"\"ab\"\"", StringUtils.wrap("\"ab\"", '\"'));
3228         assertEquals("'ab'", StringUtils.wrap("ab", '\''));
3229         assertEquals("''abcd''", StringUtils.wrap("'abcd'", '\''));
3230         assertEquals("'\"abcd\"'", StringUtils.wrap("\"abcd\"", '\''));
3231         assertEquals("\"'abcd'\"", StringUtils.wrap("'abcd'", '\"'));
3232     }
3233 
3234     @Test
3235     void testWrap_StringString() {
3236         assertNull(StringUtils.wrap(null, null));
3237         assertNull(StringUtils.wrap(null, ""));
3238         assertNull(StringUtils.wrap(null, "1"));
3239 
3240         assertNull(StringUtils.wrap(null, null));
3241         assertEquals("", StringUtils.wrap("", ""));
3242         assertEquals("ab", StringUtils.wrap("ab", null));
3243         assertEquals("xabx", StringUtils.wrap("ab", "x"));
3244         assertEquals("\"ab\"", StringUtils.wrap("ab", "\""));
3245         assertEquals("\"\"ab\"\"", StringUtils.wrap("\"ab\"", "\""));
3246         assertEquals("'ab'", StringUtils.wrap("ab", "'"));
3247         assertEquals("''abcd''", StringUtils.wrap("'abcd'", "'"));
3248         assertEquals("'\"abcd\"'", StringUtils.wrap("\"abcd\"", "'"));
3249         assertEquals("\"'abcd'\"", StringUtils.wrap("'abcd'", "\""));
3250     }
3251 
3252     @Test
3253     void testWrapIfMissing_StringChar() {
3254         assertNull(StringUtils.wrapIfMissing(null, CharUtils.NUL));
3255         assertNull(StringUtils.wrapIfMissing(null, '1'));
3256 
3257         assertEquals("", StringUtils.wrapIfMissing("", CharUtils.NUL));
3258         assertEquals("xabx", StringUtils.wrapIfMissing("ab", 'x'));
3259         assertEquals("\"ab\"", StringUtils.wrapIfMissing("ab", '\"'));
3260         assertEquals("\"ab\"", StringUtils.wrapIfMissing("\"ab\"", '\"'));
3261         assertEquals("'ab'", StringUtils.wrapIfMissing("ab", '\''));
3262         assertEquals("'abcd'", StringUtils.wrapIfMissing("'abcd'", '\''));
3263         assertEquals("'\"abcd\"'", StringUtils.wrapIfMissing("\"abcd\"", '\''));
3264         assertEquals("\"'abcd'\"", StringUtils.wrapIfMissing("'abcd'", '\"'));
3265         assertEquals("/x/", StringUtils.wrapIfMissing("x", '/'));
3266         assertEquals("/x/y/z/", StringUtils.wrapIfMissing("x/y/z", '/'));
3267         assertEquals("/x/y/z/", StringUtils.wrapIfMissing("/x/y/z", '/'));
3268         assertEquals("/x/y/z/", StringUtils.wrapIfMissing("x/y/z/", '/'));
3269 
3270         assertSame("/", StringUtils.wrapIfMissing("/", '/'));
3271         assertSame("/x/", StringUtils.wrapIfMissing("/x/", '/'));
3272     }
3273 
3274     @Test
3275     void testWrapIfMissing_StringString() {
3276         assertNull(StringUtils.wrapIfMissing(null, "\0"));
3277         assertNull(StringUtils.wrapIfMissing(null, "1"));
3278 
3279         assertEquals("", StringUtils.wrapIfMissing("", "\0"));
3280         assertEquals("xabx", StringUtils.wrapIfMissing("ab", "x"));
3281         assertEquals("\"ab\"", StringUtils.wrapIfMissing("ab", "\""));
3282         assertEquals("\"ab\"", StringUtils.wrapIfMissing("\"ab\"", "\""));
3283         assertEquals("'ab'", StringUtils.wrapIfMissing("ab", "\'"));
3284         assertEquals("'abcd'", StringUtils.wrapIfMissing("'abcd'", "\'"));
3285         assertEquals("'\"abcd\"'", StringUtils.wrapIfMissing("\"abcd\"", "\'"));
3286         assertEquals("\"'abcd'\"", StringUtils.wrapIfMissing("'abcd'", "\""));
3287         assertEquals("/x/", StringUtils.wrapIfMissing("x", "/"));
3288         assertEquals("/x/y/z/", StringUtils.wrapIfMissing("x/y/z", "/"));
3289         assertEquals("/x/y/z/", StringUtils.wrapIfMissing("/x/y/z", "/"));
3290         assertEquals("/x/y/z/", StringUtils.wrapIfMissing("x/y/z/", "/"));
3291         assertEquals("/", StringUtils.wrapIfMissing("/", "/"));
3292         assertEquals("ab/ab", StringUtils.wrapIfMissing("/", "ab"));
3293 
3294         assertSame("ab/ab", StringUtils.wrapIfMissing("ab/ab", "ab"));
3295         assertSame("//x//", StringUtils.wrapIfMissing("//x//", "//"));
3296     }
3297 }