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.text;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTimeout;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.lang.reflect.Constructor;
28  import java.lang.reflect.Modifier;
29  import java.time.Duration;
30  import java.util.stream.IntStream;
31  
32  import org.apache.commons.lang3.ArrayUtils;
33  import org.apache.commons.lang3.StringUtils;
34  import org.junit.jupiter.api.Test;
35  import org.junitpioneer.jupiter.DefaultLocale;
36  
37  /**
38   * Tests {@link WordUtils}.
39   */
40  class WordUtilsTest {
41  
42      private static final String WHITESPACE = IntStream.rangeClosed(Character.MIN_CODE_POINT, Character.MAX_CODE_POINT).filter(Character::isWhitespace)
43              .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();
44  
45      @Test
46      void testAbbreviateForLowerThanMinusOneValues() {
47          assertThrows(IllegalArgumentException.class, () -> WordUtils.abbreviate("01 23 45 67 89", 9, -10, null));
48      }
49  
50      @Test
51      void testAbbreviateForLowerValue() {
52          assertEquals("012", WordUtils.abbreviate("012 3456789", 0, 5, null));
53          assertEquals("01234", WordUtils.abbreviate("01234 56789", 5, 10, null));
54          assertEquals("01 23 45 67", WordUtils.abbreviate("01 23 45 67 89", 9, -1, null));
55          assertEquals("01 23 45 6", WordUtils.abbreviate("01 23 45 67 89", 9, 10, null));
56          assertEquals("0123456789", WordUtils.abbreviate("0123456789", 15, 20, null));
57      }
58  
59      @Test
60      void testAbbreviateForLowerValueAndAppendedString() {
61          assertEquals("012", WordUtils.abbreviate("012 3456789", 0, 5, null));
62          assertEquals("01234-", WordUtils.abbreviate("01234 56789", 5, 10, "-"));
63          assertEquals("01 23 45 67abc", WordUtils.abbreviate("01 23 45 67 89", 9, -1, "abc"));
64          assertEquals("01 23 45 6", WordUtils.abbreviate("01 23 45 67 89", 9, 10, ""));
65      }
66  
67      @Test
68      void testAbbreviateForNullAndEmptyString() {
69          assertNull(WordUtils.abbreviate(null, 1, -1, ""));
70          assertEquals(StringUtils.EMPTY, WordUtils.abbreviate("", 1, -1, ""));
71          assertEquals("", WordUtils.abbreviate("0123456790", 0, 0, ""));
72          assertEquals("", WordUtils.abbreviate(" 0123456790", 0, -1, ""));
73      }
74  
75      @Test
76      void testAbbreviateForUpperLimit() {
77          assertEquals("01234", WordUtils.abbreviate("0123456789", 0, 5, ""));
78          assertEquals("012", WordUtils.abbreviate("012 3456789", 2, 5, ""));
79          assertEquals("0123456789", WordUtils.abbreviate("0123456789", 0, -1, ""));
80      }
81  
82      @Test
83      void testAbbreviateForUpperLimitAndAppendedString() {
84          assertEquals("01234-", WordUtils.abbreviate("0123456789", 0, 5, "-"));
85          assertEquals("012", WordUtils.abbreviate("012 3456789", 2, 5, null));
86          assertEquals("0123456789", WordUtils.abbreviate("0123456789", 0, -1, ""));
87      }
88  
89      @Test
90      void testAbbreviateUpperLessThanLowerValues() {
91          assertThrows(IllegalArgumentException.class, () -> WordUtils.abbreviate("0123456789", 5, 2, ""));
92      }
93  
94      @Test
95      void testCapitalize_String() {
96          assertNull(WordUtils.capitalize(null));
97          assertEquals("", WordUtils.capitalize(""));
98          assertEquals("  ", WordUtils.capitalize("  "));
99  
100         assertEquals("I", WordUtils.capitalize("I"));
101         assertEquals("I", WordUtils.capitalize("i"));
102         assertEquals("I Am Here 123", WordUtils.capitalize("i am here 123"));
103         assertEquals("I Am Here 123", WordUtils.capitalize("I Am Here 123"));
104         assertEquals("I Am HERE 123", WordUtils.capitalize("i am HERE 123"));
105         assertEquals("I AM HERE 123", WordUtils.capitalize("I AM HERE 123"));
106     }
107 
108     @Test
109     @DefaultLocale(language = "tr", country = "TR")
110     void testCapitalizeFully_LocaleIndependent() {
111         // Turkish lower-cases 'I' (U+0049) to dotless 'i' (U+0131), which would otherwise leak into the result.
112         assertEquals("Heli World", WordUtils.capitalizeFully("HELI WORLD"));
113         assertEquals("I Am Here 123", WordUtils.capitalizeFully("I AM HERE 123"));
114     }
115 
116     @Test
117     void testCapitalizeFully_String() {
118         assertNull(WordUtils.capitalizeFully(null));
119         assertEquals("", WordUtils.capitalizeFully(""));
120         assertEquals("  ", WordUtils.capitalizeFully("  "));
121         assertEquals("I", WordUtils.capitalizeFully("I"));
122         assertEquals("I", WordUtils.capitalizeFully("i"));
123         assertEquals("I Am Here 123", WordUtils.capitalizeFully("i am here 123"));
124         assertEquals("I Am Here 123", WordUtils.capitalizeFully("I Am Here 123"));
125         assertEquals("I Am Here 123", WordUtils.capitalizeFully("i am HERE 123"));
126         assertEquals("I Am Here 123", WordUtils.capitalizeFully("I AM HERE 123"));
127         assertEquals("Alphabet", WordUtils.capitalizeFully("alphabet")); // single word
128         assertEquals("A\tB\nC D", WordUtils.capitalizeFully("a\tb\nc d"));
129         assertEquals("And \tBut \nCleat  Dome", WordUtils.capitalizeFully("and \tbut \ncleat  dome"));
130         // All whitespace
131         assertEquals(WHITESPACE, WordUtils.capitalizeFully(WHITESPACE));
132         assertEquals("A" + WHITESPACE + "B", WordUtils.capitalizeFully("a" + WHITESPACE + "b"));
133 
134     }
135 
136     @Test
137     void testCapitalizeFully_Text88() {
138         assertEquals("I am fine now", WordUtils.capitalizeFully("i am fine now", new char[] {}));
139     }
140 
141     @Test
142     void testCapitalizeFullyWithDelimiters_String() {
143         assertNull(WordUtils.capitalizeFully(null, null));
144         assertEquals("", WordUtils.capitalizeFully("", ArrayUtils.EMPTY_CHAR_ARRAY));
145         assertEquals("  ", WordUtils.capitalizeFully("  ", ArrayUtils.EMPTY_CHAR_ARRAY));
146 
147         char[] chars = { '-', '+', ' ', '@' };
148         assertEquals("I", WordUtils.capitalizeFully("I", chars));
149         assertEquals("I", WordUtils.capitalizeFully("i", chars));
150         assertEquals("I-Am Here+123", WordUtils.capitalizeFully("i-am here+123", chars));
151         assertEquals("I Am+Here-123", WordUtils.capitalizeFully("I Am+Here-123", chars));
152         assertEquals("I+Am-Here 123", WordUtils.capitalizeFully("i+am-HERE 123", chars));
153         assertEquals("I-Am Here+123", WordUtils.capitalizeFully("I-AM HERE+123", chars));
154         chars = new char[] { '.' };
155         assertEquals("I am.Fine", WordUtils.capitalizeFully("i aM.fine", chars));
156         assertEquals("I Am.fine", WordUtils.capitalizeFully("i am.fine", null));
157         assertEquals("Alphabet", WordUtils.capitalizeFully("alphabet", null)); // single word
158         assertEquals("Alphabet", WordUtils.capitalizeFully("alphabet", new char[] { '!' })); // no matching delim
159     }
160 
161     @Test
162     void testCapitalizeWithDelimiters_String() {
163         assertNull(WordUtils.capitalize(null, null));
164         assertEquals("", WordUtils.capitalize("", ArrayUtils.EMPTY_CHAR_ARRAY));
165         assertEquals("  ", WordUtils.capitalize("  ", ArrayUtils.EMPTY_CHAR_ARRAY));
166 
167         char[] chars = { '-', '+', ' ', '@' };
168         assertEquals("I", WordUtils.capitalize("I", chars));
169         assertEquals("I", WordUtils.capitalize("i", chars));
170         assertEquals("I-Am Here+123", WordUtils.capitalize("i-am here+123", chars));
171         assertEquals("I Am+Here-123", WordUtils.capitalize("I Am+Here-123", chars));
172         assertEquals("I+Am-HERE 123", WordUtils.capitalize("i+am-HERE 123", chars));
173         assertEquals("I-AM HERE+123", WordUtils.capitalize("I-AM HERE+123", chars));
174         chars = new char[] { '.' };
175         assertEquals("I aM.Fine", WordUtils.capitalize("i aM.fine", chars));
176         assertEquals("I Am.fine", WordUtils.capitalize("i am.fine", null));
177     }
178 
179     @Test
180     void testConstructor() {
181         assertNotNull(new WordUtils());
182         final Constructor<?>[] cons = WordUtils.class.getDeclaredConstructors();
183         assertEquals(1, cons.length);
184         assertTrue(Modifier.isPublic(cons[0].getModifiers()));
185         assertTrue(Modifier.isPublic(WordUtils.class.getModifiers()));
186         assertFalse(Modifier.isFinal(WordUtils.class.getModifiers()));
187     }
188 
189     @Test
190     void testContainsAllWords_StringString() {
191         assertFalse(WordUtils.containsAllWords(null));
192         assertFalse(WordUtils.containsAllWords(null, ""));
193         assertFalse(WordUtils.containsAllWords(null, "ab"));
194 
195         assertFalse(WordUtils.containsAllWords(""));
196         assertFalse(WordUtils.containsAllWords("", (String) null));
197         assertFalse(WordUtils.containsAllWords("", ""));
198         assertFalse(WordUtils.containsAllWords("", "ab"));
199 
200         assertFalse(WordUtils.containsAllWords("foo"));
201         assertFalse(WordUtils.containsAllWords("foo", (String) null));
202         assertFalse(WordUtils.containsAllWords("bar", ""));
203         assertFalse(WordUtils.containsAllWords("zzabyycdxx", "by"));
204         assertTrue(WordUtils.containsAllWords("lorem ipsum dolor sit amet", "ipsum", "lorem", "dolor"));
205         assertFalse(WordUtils.containsAllWords("lorem ipsum dolor sit amet", "ipsum", null, "lorem", "dolor"));
206         assertFalse(WordUtils.containsAllWords("lorem ipsum null dolor sit amet", "ipsum", null, "lorem", "dolor"));
207         assertFalse(WordUtils.containsAllWords("ab", "b"));
208         assertFalse(WordUtils.containsAllWords("ab", "z"));
209         assertFalse(WordUtils.containsAllWords("ab", "["));
210         assertFalse(WordUtils.containsAllWords("ab", "]"));
211         assertFalse(WordUtils.containsAllWords("ab", "*"));
212         assertTrue(WordUtils.containsAllWords("ab x", "ab", "x"));
213     }
214 
215     @Test
216     void testContainsAllWordsWithNewline() {
217         assertTrue(WordUtils.containsAllWords("foo\nbar", "bar"));
218         assertTrue(WordUtils.containsAllWords("foo\nbar", "foo"));
219         assertTrue(WordUtils.containsAllWords("lorem ipsum\ndolor sit\namet", "ipsum", "amet", "lorem"));
220         assertFalse(WordUtils.containsAllWords("foo\nbar", "baz"));
221     }
222 
223     @Test
224     void testContainsAllWordsWithNull() {
225         assertFalse(WordUtils.containsAllWords("M", (CharSequence) null));
226     }
227 
228     @Test
229     void testInitials_String() {
230         assertNull(WordUtils.initials(null));
231         assertEquals("", WordUtils.initials(""));
232         assertEquals("", WordUtils.initials("  "));
233 
234         assertEquals("I", WordUtils.initials("I"));
235         assertEquals("i", WordUtils.initials("i"));
236         assertEquals("BJL", WordUtils.initials("Ben John Lee"));
237         assertEquals("BJL", WordUtils.initials("   Ben \n   John\tLee\t"));
238         assertEquals("BJ", WordUtils.initials("Ben J.Lee"));
239         assertEquals("BJ.L", WordUtils.initials(" Ben   John  . Lee"));
240         assertEquals("iah1", WordUtils.initials("i am here 123"));
241     }
242 
243     @Test
244     void testInitials_String_charArray() {
245         char[] array = null;
246         assertNull(WordUtils.initials(null, array));
247         assertEquals("", WordUtils.initials("", array));
248         assertEquals("", WordUtils.initials("  ", array));
249         assertEquals("I", WordUtils.initials("I", array));
250         assertEquals("i", WordUtils.initials("i", array));
251         assertEquals("S", WordUtils.initials("SJC", array));
252         assertEquals("BJL", WordUtils.initials("Ben John Lee", array));
253         assertEquals("BJL", WordUtils.initials("   Ben \n   John\tLee\t", array));
254         assertEquals("BJ", WordUtils.initials("Ben J.Lee", array));
255         assertEquals("BJ.L", WordUtils.initials(" Ben   John  . Lee", array));
256         assertEquals("KO", WordUtils.initials("Kay O'Murphy", array));
257         assertEquals("iah1", WordUtils.initials("i am here 123", array));
258 
259         array = ArrayUtils.EMPTY_CHAR_ARRAY;
260         assertNull(WordUtils.initials(null, array));
261         assertEquals("", WordUtils.initials("", array));
262         assertEquals("", WordUtils.initials("  ", array));
263         assertEquals("", WordUtils.initials("I", array));
264         assertEquals("", WordUtils.initials("i", array));
265         assertEquals("", WordUtils.initials("SJC", array));
266         assertEquals("", WordUtils.initials("Ben John Lee", array));
267         assertEquals("", WordUtils.initials("   Ben \n   John\tLee\t", array));
268         assertEquals("", WordUtils.initials("Ben J.Lee", array));
269         assertEquals("", WordUtils.initials(" Ben   John  . Lee", array));
270         assertEquals("", WordUtils.initials("Kay O'Murphy", array));
271         assertEquals("", WordUtils.initials("i am here 123", array));
272 
273         array = " ".toCharArray();
274         assertNull(WordUtils.initials(null, array));
275         assertEquals("", WordUtils.initials("", array));
276         assertEquals("", WordUtils.initials("  ", array));
277         assertEquals("I", WordUtils.initials("I", array));
278         assertEquals("i", WordUtils.initials("i", array));
279         assertEquals("S", WordUtils.initials("SJC", array));
280         assertEquals("BJL", WordUtils.initials("Ben John Lee", array));
281         assertEquals("BJ", WordUtils.initials("Ben J.Lee", array));
282         assertEquals("B\nJ", WordUtils.initials("   Ben \n   John\tLee\t", array));
283         assertEquals("BJ.L", WordUtils.initials(" Ben   John  . Lee", array));
284         assertEquals("KO", WordUtils.initials("Kay O'Murphy", array));
285         assertEquals("iah1", WordUtils.initials("i am here 123", array));
286 
287         array = " .".toCharArray();
288         assertNull(WordUtils.initials(null, array));
289         assertEquals("", WordUtils.initials("", array));
290         assertEquals("", WordUtils.initials("  ", array));
291         assertEquals("I", WordUtils.initials("I", array));
292         assertEquals("i", WordUtils.initials("i", array));
293         assertEquals("S", WordUtils.initials("SJC", array));
294         assertEquals("BJL", WordUtils.initials("Ben John Lee", array));
295         assertEquals("BJL", WordUtils.initials("Ben J.Lee", array));
296         assertEquals("BJL", WordUtils.initials(" Ben   John  . Lee", array));
297         assertEquals("KO", WordUtils.initials("Kay O'Murphy", array));
298         assertEquals("iah1", WordUtils.initials("i am here 123", array));
299 
300         array = " .'".toCharArray();
301         assertNull(WordUtils.initials(null, array));
302         assertEquals("", WordUtils.initials("", array));
303         assertEquals("", WordUtils.initials("  ", array));
304         assertEquals("I", WordUtils.initials("I", array));
305         assertEquals("i", WordUtils.initials("i", array));
306         assertEquals("S", WordUtils.initials("SJC", array));
307         assertEquals("BJL", WordUtils.initials("Ben John Lee", array));
308         assertEquals("BJL", WordUtils.initials("Ben J.Lee", array));
309         assertEquals("BJL", WordUtils.initials(" Ben   John  . Lee", array));
310         assertEquals("KOM", WordUtils.initials("Kay O'Murphy", array));
311         assertEquals("iah1", WordUtils.initials("i am here 123", array));
312 
313         array = "SIJo1".toCharArray();
314         assertNull(WordUtils.initials(null, array));
315         assertEquals("", WordUtils.initials("", array));
316         assertEquals(" ", WordUtils.initials("  ", array));
317         assertEquals("", WordUtils.initials("I", array));
318         assertEquals("i", WordUtils.initials("i", array));
319         assertEquals("C", WordUtils.initials("SJC", array));
320         assertEquals("Bh", WordUtils.initials("Ben John Lee", array));
321         assertEquals("B.", WordUtils.initials("Ben J.Lee", array));
322         assertEquals(" h", WordUtils.initials(" Ben   John  . Lee", array));
323         assertEquals("K", WordUtils.initials("Kay O'Murphy", array));
324         assertEquals("i2", WordUtils.initials("i am here 123", array));
325     }
326 
327     @Test
328     void testInitialsSurrogatePairs() {
329         // Tests with space as default delimiter
330         assertEquals("\uD800\uDF00\uD800\uDF02", WordUtils.initials("\uD800\uDF00\uD800\uDF01 \uD800\uDF02\uD800\uDF03"));
331         assertEquals("\uD800\uDF00\uD800\uDF02", WordUtils.initials("\uD800\uDF00\uD800\uDF01 \uD800\uDF02\uD800\uDF03", null));
332         assertEquals("\uD800\uDF00\uD800\uDF02", WordUtils.initials("\uD800\uDF00 \uD800\uDF02 ", null));
333 
334         // Tests with UTF-16 as delimiters
335         assertEquals("\uD800\uDF00\uD800\uDF02", WordUtils.initials("\uD800\uDF00\uD800\uDF01.\uD800\uDF02\uD800\uDF03", new char[] { '.' }));
336         assertEquals("\uD800\uDF00\uD800\uDF02", WordUtils.initials("\uD800\uDF00\uD800\uDF01A\uD800\uDF02\uD800\uDF03", new char[] { 'A' }));
337 
338         // Tests with UTF-32 as delimiters
339         assertEquals("\uD800\uDF00\uD800\uDF02",
340                 WordUtils.initials("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03", new char[] { '\uD800', '\uDF14' }));
341         assertEquals("\uD800\uDF00\uD800\uDF02", WordUtils.initials("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF18\uD800\uDF02\uD800\uDF03",
342                 new char[] { '\uD800', '\uDF14', '\uD800', '\uDF18' }));
343     }
344 
345     @Test
346     void testIsDelimiter() {
347         assertFalse(WordUtils.isDelimiter('.', null));
348         assertTrue(WordUtils.isDelimiter(' ', null));
349 
350         assertFalse(WordUtils.isDelimiter(' ', new char[] { '.' }));
351         assertTrue(WordUtils.isDelimiter('.', new char[] { '.' }));
352 
353         assertFalse(WordUtils.isDelimiter(' ', new char[] { '.', '_', 'a' }));
354         assertTrue(WordUtils.isDelimiter('.', new char[] { '.', '_', 'a', '.' }));
355     }
356 
357     @Test
358     void testIsDelimiterCodePoint() {
359         assertFalse(WordUtils.isDelimiter((int) '.', null));
360         assertTrue(WordUtils.isDelimiter((int) ' ', null));
361 
362         assertFalse(WordUtils.isDelimiter((int) ' ', new char[] { '.' }));
363         assertTrue(WordUtils.isDelimiter((int) '.', new char[] { '.' }));
364 
365         assertFalse(WordUtils.isDelimiter((int) ' ', new char[] { '.', '_', 'a' }));
366         assertTrue(WordUtils.isDelimiter((int) '.', new char[] { '.', '_', 'a', '.' }));
367     }
368 
369     @Test
370     void testLANG1292() {
371         // Prior to fix, this was throwing StringIndexOutOfBoundsException
372         WordUtils.wrap("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
373                 70);
374     }
375 
376     @Test
377     void testLANG673() {
378         assertEquals("01", WordUtils.abbreviate("01 23 45 67 89", 0, 40, ""));
379         assertEquals("01 23 45 67", WordUtils.abbreviate("01 23 45 67 89", 10, 40, ""));
380         assertEquals("01 23 45 67 89", WordUtils.abbreviate("01 23 45 67 89", 40, 40, ""));
381     }
382 
383     @Test
384     void testSwapCase_String() {
385         assertNull(WordUtils.swapCase(null));
386         assertEquals("", WordUtils.swapCase(""));
387         assertEquals("  ", WordUtils.swapCase("  "));
388 
389         assertEquals("i", WordUtils.swapCase("I"));
390         assertEquals("I", WordUtils.swapCase("i"));
391         assertEquals("I AM HERE 123", WordUtils.swapCase("i am here 123"));
392         assertEquals("i aM hERE 123", WordUtils.swapCase("I Am Here 123"));
393         assertEquals("I AM here 123", WordUtils.swapCase("i am HERE 123"));
394         assertEquals("i am here 123", WordUtils.swapCase("I AM HERE 123"));
395 
396         final String test = "This String contains a TitleCase character: \u01C8";
397         final String expect = "tHIS sTRING CONTAINS A tITLEcASE CHARACTER: \u01C9";
398         assertEquals(expect, WordUtils.swapCase(test));
399     }
400 
401     @Test
402     void testText123() throws Exception {
403         // Prior to fix, this was throwing StringIndexOutOfBoundsException
404         WordUtils.wrap("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
405                 Integer.MAX_VALUE);
406     }
407 
408     @Test
409     void testUncapitalize_String() {
410         assertNull(WordUtils.uncapitalize(null));
411         assertEquals("", WordUtils.uncapitalize(""));
412         assertEquals("  ", WordUtils.uncapitalize("  "));
413         assertEquals("i", WordUtils.uncapitalize("I"));
414         assertEquals("i", WordUtils.uncapitalize("i"));
415         assertEquals("i am here 123", WordUtils.uncapitalize("i am here 123"));
416         assertEquals("i am here 123", WordUtils.uncapitalize("I Am Here 123"));
417         assertEquals("i am hERE 123", WordUtils.uncapitalize("i am HERE 123"));
418         assertEquals("i aM hERE 123", WordUtils.uncapitalize("I AM HERE 123"));
419         assertEquals("a\tb\nc d", WordUtils.uncapitalize("A\tB\nC D"));
420         assertEquals("and \tbut \ncLEAT  dome", WordUtils.uncapitalize("And \tBut \nCLEAT  Dome"));
421         // All whitespace
422         assertEquals(WHITESPACE, WordUtils.capitalizeFully(WHITESPACE));
423         assertEquals("A" + WHITESPACE + "B", WordUtils.capitalizeFully("a" + WHITESPACE + "b"));
424     }
425 
426     @Test
427     void testUnCapitalize_Text88() {
428         assertEquals("i am fine now", WordUtils.uncapitalize("I am fine now", new char[] {}));
429     }
430 
431     @Test
432     void testUncapitalizeWithDelimiters_String() {
433         assertNull(WordUtils.uncapitalize(null, null));
434         assertEquals("", WordUtils.uncapitalize("", ArrayUtils.EMPTY_CHAR_ARRAY));
435         assertEquals("  ", WordUtils.uncapitalize("  ", ArrayUtils.EMPTY_CHAR_ARRAY));
436 
437         char[] chars = { '-', '+', ' ', '@' };
438         assertEquals("i", WordUtils.uncapitalize("I", chars));
439         assertEquals("i", WordUtils.uncapitalize("i", chars));
440         assertEquals("i am-here+123", WordUtils.uncapitalize("i am-here+123", chars));
441         assertEquals("i+am here-123", WordUtils.uncapitalize("I+Am Here-123", chars));
442         assertEquals("i-am+hERE 123", WordUtils.uncapitalize("i-am+HERE 123", chars));
443         assertEquals("i aM-hERE+123", WordUtils.uncapitalize("I AM-HERE+123", chars));
444         chars = new char[] { '.' };
445         assertEquals("i AM.fINE", WordUtils.uncapitalize("I AM.FINE", chars));
446         assertEquals("i aM.FINE", WordUtils.uncapitalize("I AM.FINE", null));
447     }
448 
449     @Test
450     void testWrap_StringInt() {
451         assertNull(WordUtils.wrap(null, 20));
452         assertNull(WordUtils.wrap(null, -1));
453 
454         assertEquals("", WordUtils.wrap("", 20));
455         assertEquals("", WordUtils.wrap("", -1));
456 
457         // normal
458         final String systemNewLine = System.lineSeparator();
459         String input = "Here is one line of text that is going to be wrapped after 20 columns.";
460         String expected = "Here is one line of" + systemNewLine + "text that is going" + systemNewLine + "to be wrapped after" + systemNewLine + "20 columns.";
461         assertEquals(expected, WordUtils.wrap(input, 20));
462 
463         // long word at end
464         input = "Click here to jump to the commons website - https://commons.apache.org";
465         expected = "Click here to jump" + systemNewLine + "to the commons" + systemNewLine + "website -" + systemNewLine + "https://commons.apache.org";
466         assertEquals(expected, WordUtils.wrap(input, 20));
467 
468         // long word in middle
469         input = "Click here, https://commons.apache.org, to jump to the commons website";
470         expected = "Click here," + systemNewLine + "https://commons.apache.org," + systemNewLine + "to jump to the" + systemNewLine + "commons website";
471         assertEquals(expected, WordUtils.wrap(input, 20));
472 
473         // leading spaces on a new line are stripped
474         // trailing spaces are not stripped
475         input = "word1             word2                        word3";
476         expected = "word1  " + systemNewLine + "word2  " + systemNewLine + "word3";
477         assertEquals(expected, WordUtils.wrap(input, 7));
478     }
479 
480     @Test
481     void testWrap_StringIntStringBoolean() {
482         assertNull(WordUtils.wrap(null, 20, "\n", false));
483         assertNull(WordUtils.wrap(null, 20, "\n", true));
484         assertNull(WordUtils.wrap(null, 20, null, true));
485         assertNull(WordUtils.wrap(null, 20, null, false));
486         assertNull(WordUtils.wrap(null, -1, null, true));
487         assertNull(WordUtils.wrap(null, -1, null, false));
488 
489         assertEquals("", WordUtils.wrap("", 20, "\n", false));
490         assertEquals("", WordUtils.wrap("", 20, "\n", true));
491         assertEquals("", WordUtils.wrap("", 20, null, false));
492         assertEquals("", WordUtils.wrap("", 20, null, true));
493         assertEquals("", WordUtils.wrap("", -1, null, false));
494         assertEquals("", WordUtils.wrap("", -1, null, true));
495 
496         // normal
497         String input = "Here is one line of text that is going to be wrapped after 20 columns.";
498         String expected = "Here is one line of\ntext that is going\nto be wrapped after\n20 columns.";
499         assertEquals(expected, WordUtils.wrap(input, 20, "\n", false));
500         assertEquals(expected, WordUtils.wrap(input, 20, "\n", true));
501 
502         // unusual newline char
503         input = "Here is one line of text that is going to be wrapped after 20 columns.";
504         expected = "Here is one line of<br />text that is going<br />to be wrapped after<br />20 columns.";
505         assertEquals(expected, WordUtils.wrap(input, 20, "<br />", false));
506         assertEquals(expected, WordUtils.wrap(input, 20, "<br />", true));
507 
508         // short line length
509         input = "Here is one line";
510         expected = "Here\nis one\nline";
511         assertEquals(expected, WordUtils.wrap(input, 6, "\n", false));
512         expected = "Here\nis\none\nline";
513         assertEquals(expected, WordUtils.wrap(input, 2, "\n", false));
514         assertEquals(expected, WordUtils.wrap(input, -1, "\n", false));
515 
516         // system newline char
517         final String systemNewLine = System.lineSeparator();
518         input = "Here is one line of text that is going to be wrapped after 20 columns.";
519         expected = "Here is one line of" + systemNewLine + "text that is going" + systemNewLine + "to be wrapped after" + systemNewLine + "20 columns.";
520         assertEquals(expected, WordUtils.wrap(input, 20, null, false));
521         assertEquals(expected, WordUtils.wrap(input, 20, null, true));
522 
523         // with extra spaces
524         input = " Here:  is  one  line  of  text  that  is  going  to  be  wrapped  after  20  columns.";
525         expected = "Here:  is  one  line\nof  text  that  is \ngoing  to  be \nwrapped  after  20 \ncolumns.";
526         assertEquals(expected, WordUtils.wrap(input, 20, "\n", false));
527         assertEquals(expected, WordUtils.wrap(input, 20, "\n", true));
528 
529         // with tab
530         input = "Here is\tone line of text that is going to be wrapped after 20 columns.";
531         expected = "Here is\tone line of\ntext that is going\nto be wrapped after\n20 columns.";
532         assertEquals(expected, WordUtils.wrap(input, 20, "\n", false));
533         assertEquals(expected, WordUtils.wrap(input, 20, "\n", true));
534 
535         // with tab at wrapColumn
536         input = "Here is one line of\ttext that is going to be wrapped after 20 columns.";
537         expected = "Here is one line\nof\ttext that is\ngoing to be wrapped\nafter 20 columns.";
538         assertEquals(expected, WordUtils.wrap(input, 20, "\n", false));
539         assertEquals(expected, WordUtils.wrap(input, 20, "\n", true));
540 
541         // difference because of long word
542         input = "Click here to jump to the commons website - https://commons.apache.org";
543         expected = "Click here to jump\nto the commons\nwebsite -\nhttps://commons.apache.org";
544         assertEquals(expected, WordUtils.wrap(input, 20, "\n", false));
545         expected = "Click here to jump\nto the commons\nwebsite -\nhttps://commons.apac\nhe.org";
546         assertEquals(expected, WordUtils.wrap(input, 20, "\n", true));
547 
548         // difference because of long word in middle
549         input = "Click here, https://commons.apache.org, to jump to the commons website";
550         expected = "Click here,\nhttps://commons.apache.org,\nto jump to the\ncommons website";
551         assertEquals(expected, WordUtils.wrap(input, 20, "\n", false));
552         expected = "Click here,\nhttps://commons.apac\nhe.org, to jump to\nthe commons website";
553         assertEquals(expected, WordUtils.wrap(input, 20, "\n", true));
554 
555         // a hard break for a long word must not split a surrogate pair across the new line
556         input = "a\uD83D\uDE00\uD83D\uDE00\uD83D\uDE00\uD83D\uDE00";
557         expected = "a\uD83D\uDE00\uD83D\uDE00\n\uD83D\uDE00\uD83D\uDE00";
558         assertEquals(expected, WordUtils.wrap(input, 4, "\n", true));
559         input = "\uD83D\uDE00\uD83D\uDE00\uD83D\uDE00";
560         expected = "\uD83D\uDE00\uD83D\uDE00\n\uD83D\uDE00";
561         assertEquals(expected, WordUtils.wrap(input, 3, "\n", true));
562     }
563 
564     @Test
565     void testWrap_StringIntStringBooleanString() {
566 
567         // no changes test
568         String input = "flammable/inflammable";
569         String expected = "flammable/inflammable";
570         assertEquals(expected, WordUtils.wrap(input, 30, "\n", false, "/"));
571 
572         // wrap on / and small width
573         expected = "flammable\ninflammable";
574         assertEquals(expected, WordUtils.wrap(input, 2, "\n", false, "/"));
575 
576         // wrap long words on / 1
577         expected = "flammable\ninflammab\nle";
578         assertEquals(expected, WordUtils.wrap(input, 9, "\n", true, "/"));
579 
580         // wrap long words on / 2
581         expected = "flammable\ninflammable";
582         assertEquals(expected, WordUtils.wrap(input, 15, "\n", true, "/"));
583 
584         // wrap long words on / 3
585         input = "flammableinflammable";
586         expected = "flammableinflam\nmable";
587         assertEquals(expected, WordUtils.wrap(input, 15, "\n", true, "/"));
588     }
589 
590     @Test
591     void testWrapAtMiddleTwice() {
592         assertEquals("abcdef\n\nabcdef", WordUtils.wrap("abcdefggabcdef", 2, "\n", false, "(?=g)"));
593     }
594 
595     @Test
596     void testWrapAtStartAndEnd() {
597         assertEquals("\nabcdefabcdef\n", WordUtils.wrap("nabcdefabcdefn", 2, "\n", false, "(?=n)"));
598     }
599 
600     @Test
601     void testWrapWithMultipleRegexMatchOfLength0() {
602         assertEquals("abc\ndefabc\ndef", WordUtils.wrap("abcdefabcdef", 2, "\n", false, "(?=d)"));
603     }
604 
605     @Test
606     void testWrapWithRegexMatchOfLength0() {
607         assertEquals("abc\ndef", WordUtils.wrap("abcdef", 2, "\n", false, "(?=d)"));
608     }
609 
610     @Test
611     void testZeroWidthWrapOnRegex() {
612         assertTimeout(Duration.ofSeconds(2), () -> assertNotNull(WordUtils.wrap("abcdef", 3, "\n", false, "(?=a)")));
613     }
614 
615 }