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.Supplementary.CharU20000;
20  import static org.apache.commons.lang3.Supplementary.CharU20001;
21  import static org.apache.commons.lang3.Supplementary.CharU24000;
22  import static org.apache.commons.lang3.Supplementary.CharUSuppCharHigh;
23  import static org.apache.commons.lang3.Supplementary.CharUSuppCharLow;
24  import static org.junit.jupiter.api.Assertions.assertEquals;
25  import static org.junit.jupiter.api.Assertions.assertFalse;
26  import static org.junit.jupiter.api.Assertions.assertNotEquals;
27  import static org.junit.jupiter.api.Assertions.assertTrue;
28  import static org.junit.jupiter.params.provider.Arguments.arguments;
29  
30  import java.nio.CharBuffer;
31  import java.util.Locale;
32  import java.util.stream.Stream;
33  
34  import org.junit.jupiter.api.Test;
35  import org.junit.jupiter.params.ParameterizedTest;
36  import org.junit.jupiter.params.provider.Arguments;
37  import org.junit.jupiter.params.provider.MethodSource;
38  
39  /**
40   * Tests {@link StringUtils} - Equals/IndexOf methods
41   */
42  class StringUtilsEqualsIndexOfTest extends AbstractLangTest {
43  
44      // The purpose of this class is to test StringUtils#equals(CharSequence, CharSequence)
45      // with a CharSequence implementation whose equals(Object) override requires that the
46      // other object be an instance of CustomCharSequence, even though, as char sequences,
47      // `seq` may equal the other object.
48      private static final class CustomCharSequence implements CharSequence {
49          private final CharSequence seq;
50  
51          CustomCharSequence(final CharSequence seq) {
52              this.seq = seq;
53          }
54  
55          @Override
56          public char charAt(final int index) {
57              return seq.charAt(index);
58          }
59  
60          @Override
61          public boolean equals(final Object obj) {
62              if (!(obj instanceof CustomCharSequence)) {
63                  return false;
64              }
65              final CustomCharSequence other = (CustomCharSequence) obj;
66              return seq.equals(other.seq);
67          }
68  
69          @Override
70          public int hashCode() {
71              return seq.hashCode();
72          }
73  
74          @Override
75          public int length() {
76              return seq.length();
77          }
78  
79          @Override
80          public CharSequence subSequence(final int start, final int end) {
81              return new CustomCharSequence(seq.subSequence(start, end));
82          }
83  
84          @Override
85          public String toString() {
86              return seq.toString();
87          }
88      }
89  
90      private static final String BAR = "bar";
91  
92      private static final String FOO = "foo";
93  
94      private static final String FOOBAR = "foobar";
95  
96      private static final String[] FOOBAR_SUB_ARRAY = {"ob", "ba"};
97  
98      static Stream<Arguments> indexOfAnyBut_withSurrogateChars() {
99          // @formatter:off
100         return Stream.of(
101             arguments(CharU20000 + CharU20001,    CharU20000, 2),
102             arguments(CharU20000 + CharU20001,    CharU20001, 0),
103             arguments(CharU20000 + CharU20001,    "abcd" + CharUSuppCharLow, 0),
104             arguments(CharU20000 + CharU20001,    "abcd" + CharUSuppCharHigh, 0),
105             arguments(CharU20000,                 CharU20000, -1),
106             arguments(CharU20000,                 CharU20001, 0),
107             arguments(CharUSuppCharHigh + "aaaa", CharUSuppCharHigh + "abcd", -1),
108             arguments(CharUSuppCharHigh + "baaa", CharUSuppCharHigh + "abcd", -1),
109             arguments(CharUSuppCharHigh + "aaaa", CharU20000 + "abcd", 0),
110             arguments("aaaa" + CharUSuppCharHigh, CharU20000 + "abcd", 4),
111             arguments(CharUSuppCharLow + "aaaa",  CharU20000 + "abcd", 0),
112             arguments("aaaa" + CharUSuppCharLow,  CharU20000 + "abcd", 4),
113             arguments(CharU20000 + "aaaa",        CharUSuppCharLow + "ab" + CharUSuppCharHigh + "cd", 0),
114             arguments(CharU20000 + "aaaa",        "abcd", 0),
115             arguments(CharU20000 + "aaaa",        "abcd" + CharUSuppCharHigh, 0),
116             arguments(CharU20000 + "aaaa",        "abcd" + CharUSuppCharLow, 0),
117             arguments("aaaa" + CharU20000,        CharU20000 + "abcd", -1)
118         );
119         // @formatter:on
120     }
121 
122     @Test
123     void testCompare_StringString() {
124         assertEquals(0, StringUtils.compare(null, null));
125         assertTrue(StringUtils.compare(null, "a") < 0);
126         assertTrue(StringUtils.compare("a", null) > 0);
127         assertEquals(0, StringUtils.compare("abc", "abc"));
128         assertTrue(StringUtils.compare("a", "b") < 0);
129         assertTrue(StringUtils.compare("b", "a") > 0);
130         assertTrue(StringUtils.compare("a", "B") > 0);
131         assertTrue(StringUtils.compare("abc", "abd") < 0);
132         assertTrue(StringUtils.compare("ab", "abc") < 0);
133         assertTrue(StringUtils.compare("ab", "ab ") < 0);
134         assertTrue(StringUtils.compare("abc", "ab ") > 0);
135     }
136 
137     @Test
138     void testCompare_StringStringBoolean() {
139         assertEquals(0, StringUtils.compare(null, null, false));
140         assertTrue(StringUtils.compare(null, "a", true) < 0);
141         assertTrue(StringUtils.compare(null, "a", false) > 0);
142         assertTrue(StringUtils.compare("a", null, true) > 0);
143         assertTrue(StringUtils.compare("a", null, false) < 0);
144         assertEquals(0, StringUtils.compare("abc", "abc", false));
145         assertTrue(StringUtils.compare("a", "b", false) < 0);
146         assertTrue(StringUtils.compare("b", "a", false) > 0);
147         assertTrue(StringUtils.compare("a", "B", false) > 0);
148         assertTrue(StringUtils.compare("abc", "abd", false) < 0);
149         assertTrue(StringUtils.compare("ab", "abc", false) < 0);
150         assertTrue(StringUtils.compare("ab", "ab ", false) < 0);
151         assertTrue(StringUtils.compare("abc", "ab ", false) > 0);
152     }
153 
154     @Test
155     void testCompareIgnoreCase_StringString() {
156         assertEquals(0, StringUtils.compareIgnoreCase(null, null));
157         assertTrue(StringUtils.compareIgnoreCase(null, "a") < 0);
158         assertTrue(StringUtils.compareIgnoreCase("a", null) > 0);
159         assertEquals(0, StringUtils.compareIgnoreCase("abc", "abc"));
160         assertEquals(0, StringUtils.compareIgnoreCase("abc", "ABC"));
161         assertTrue(StringUtils.compareIgnoreCase("a", "b") < 0);
162         assertTrue(StringUtils.compareIgnoreCase("b", "a") > 0);
163         assertTrue(StringUtils.compareIgnoreCase("a", "B") < 0);
164         assertTrue(StringUtils.compareIgnoreCase("A", "b") < 0);
165         assertTrue(StringUtils.compareIgnoreCase("abc", "ABD") < 0);
166         assertTrue(StringUtils.compareIgnoreCase("ab", "ABC") < 0);
167         assertTrue(StringUtils.compareIgnoreCase("ab", "AB ") < 0);
168         assertTrue(StringUtils.compareIgnoreCase("abc", "AB ") > 0);
169     }
170 
171     @Test
172     void testCompareIgnoreCase_StringStringBoolean() {
173         assertEquals(0, StringUtils.compareIgnoreCase(null, null, false));
174         assertTrue(StringUtils.compareIgnoreCase(null, "a", true) < 0);
175         assertTrue(StringUtils.compareIgnoreCase(null, "a", false) > 0);
176         assertTrue(StringUtils.compareIgnoreCase("a", null, true) > 0);
177         assertTrue(StringUtils.compareIgnoreCase("a", null, false) < 0);
178         assertEquals(0, StringUtils.compareIgnoreCase("abc", "abc", false));
179         assertEquals(0, StringUtils.compareIgnoreCase("abc", "ABC", false));
180         assertTrue(StringUtils.compareIgnoreCase("a", "b", false) < 0);
181         assertTrue(StringUtils.compareIgnoreCase("b", "a", false) > 0);
182         assertTrue(StringUtils.compareIgnoreCase("a", "B", false) < 0);
183         assertTrue(StringUtils.compareIgnoreCase("A", "b", false) < 0);
184         assertTrue(StringUtils.compareIgnoreCase("abc", "ABD", false) < 0);
185         assertTrue(StringUtils.compareIgnoreCase("ab", "ABC", false) < 0);
186         assertTrue(StringUtils.compareIgnoreCase("ab", "AB ", false) < 0);
187         assertTrue(StringUtils.compareIgnoreCase("abc", "AB ", false) > 0);
188     }
189 
190     @Test
191     void testCustomCharSequence() {
192         assertNotEquals(FOO, new CustomCharSequence(FOO));
193         assertNotEquals(new CustomCharSequence(FOO), FOO);
194         assertEquals(new CustomCharSequence(FOO), new CustomCharSequence(FOO));
195     }
196 
197     @Test
198     void testEquals() {
199         final CharSequence fooCs = new StringBuilder(FOO);
200         final CharSequence barCs = new StringBuilder(BAR);
201         final CharSequence foobarCs = new StringBuilder(FOOBAR);
202         assertTrue(StringUtils.equals(null, null));
203         assertTrue(StringUtils.equals(fooCs, fooCs));
204         assertTrue(StringUtils.equals(fooCs, new StringBuilder(FOO)));
205         assertTrue(StringUtils.equals(fooCs, new String(new char[] { 'f', 'o', 'o' })));
206         assertTrue(StringUtils.equals(fooCs, new CustomCharSequence(FOO)));
207         assertTrue(StringUtils.equals(new CustomCharSequence(FOO), fooCs));
208         assertFalse(StringUtils.equals(fooCs, new String(new char[] { 'f', 'O', 'O' })));
209         assertFalse(StringUtils.equals(fooCs, barCs));
210         assertFalse(StringUtils.equals(fooCs, null));
211         assertFalse(StringUtils.equals(null, fooCs));
212         assertFalse(StringUtils.equals(fooCs, foobarCs));
213         assertFalse(StringUtils.equals(foobarCs, fooCs));
214     }
215 
216     @Test
217     void testEqualsAny() {
218         assertFalse(StringUtils.equalsAny(FOO));
219         assertFalse(StringUtils.equalsAny(FOO, new String[]{}));
220 
221         assertTrue(StringUtils.equalsAny(FOO, FOO));
222         assertTrue(StringUtils.equalsAny(FOO, BAR, new String(new char[] { 'f', 'o', 'o' })));
223         assertFalse(StringUtils.equalsAny(FOO, BAR, new String(new char[] { 'f', 'O', 'O' })));
224         assertFalse(StringUtils.equalsAny(FOO, BAR));
225         assertFalse(StringUtils.equalsAny(FOO, BAR, null));
226         assertFalse(StringUtils.equalsAny(null, FOO));
227         assertFalse(StringUtils.equalsAny(FOO, FOOBAR));
228         assertFalse(StringUtils.equalsAny(FOOBAR, FOO));
229 
230         assertTrue(StringUtils.equalsAny(null, null, null));
231         assertFalse(StringUtils.equalsAny(null, FOO, BAR, FOOBAR));
232         assertFalse(StringUtils.equalsAny(FOO, null, BAR));
233         assertTrue(StringUtils.equalsAny(FOO, BAR, null, "", FOO, BAR));
234         assertFalse(StringUtils.equalsAny(FOO, FOO.toUpperCase(Locale.ROOT)));
235 
236         assertFalse(StringUtils.equalsAny(null, (CharSequence[]) null));
237         assertTrue(StringUtils.equalsAny(FOO, new CustomCharSequence("foo")));
238         assertTrue(StringUtils.equalsAny(FOO, new StringBuilder("foo")));
239         assertFalse(StringUtils.equalsAny(FOO, new CustomCharSequence("fOo")));
240         assertFalse(StringUtils.equalsAny(FOO, new StringBuilder("fOo")));
241     }
242 
243     @Test
244     void testEqualsAnyIgnoreCase() {
245         assertFalse(StringUtils.equalsAnyIgnoreCase(FOO));
246         assertFalse(StringUtils.equalsAnyIgnoreCase(FOO, new String[]{}));
247 
248         assertTrue(StringUtils.equalsAnyIgnoreCase(FOO, FOO));
249         assertTrue(StringUtils.equalsAnyIgnoreCase(FOO, FOO.toUpperCase(Locale.ROOT)));
250         assertTrue(StringUtils.equalsAnyIgnoreCase(FOO, FOO, new String(new char[]{'f', 'o', 'o'})));
251         assertTrue(StringUtils.equalsAnyIgnoreCase(FOO, BAR, new String(new char[]{'f', 'O', 'O'})));
252         assertFalse(StringUtils.equalsAnyIgnoreCase(FOO, BAR));
253         assertFalse(StringUtils.equalsAnyIgnoreCase(FOO, BAR, null));
254         assertFalse(StringUtils.equalsAnyIgnoreCase(null, FOO));
255         assertFalse(StringUtils.equalsAnyIgnoreCase(FOO, FOOBAR));
256         assertFalse(StringUtils.equalsAnyIgnoreCase(FOOBAR, FOO));
257 
258         assertTrue(StringUtils.equalsAnyIgnoreCase(null, null, null));
259         assertFalse(StringUtils.equalsAnyIgnoreCase(null, FOO, BAR, FOOBAR));
260         assertFalse(StringUtils.equalsAnyIgnoreCase(FOO, null, BAR));
261         assertTrue(StringUtils.equalsAnyIgnoreCase(FOO, BAR, null, "", FOO.toUpperCase(Locale.ROOT), BAR));
262         assertTrue(StringUtils.equalsAnyIgnoreCase(FOO, FOO.toUpperCase(Locale.ROOT)));
263 
264         assertFalse(StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null));
265         assertTrue(StringUtils.equalsAnyIgnoreCase(FOO, new CustomCharSequence("fOo")));
266         assertTrue(StringUtils.equalsAnyIgnoreCase(FOO, new StringBuilder("fOo")));
267     }
268 
269     @Test
270     void testEqualsIgnoreCase() {
271         assertTrue(StringUtils.equalsIgnoreCase(null, null));
272         assertTrue(StringUtils.equalsIgnoreCase(FOO, FOO));
273         assertTrue(StringUtils.equalsIgnoreCase(FOO, new String(new char[] { 'f', 'o', 'o' })));
274         assertTrue(StringUtils.equalsIgnoreCase(FOO, new String(new char[] { 'f', 'O', 'O' })));
275         assertFalse(StringUtils.equalsIgnoreCase(FOO, BAR));
276         assertFalse(StringUtils.equalsIgnoreCase(FOO, null));
277         assertFalse(StringUtils.equalsIgnoreCase(null, FOO));
278         assertTrue(StringUtils.equalsIgnoreCase("", ""));
279         assertFalse(StringUtils.equalsIgnoreCase("abcd", "abcd "));
280     }
281 
282     @Test
283     void testEqualsOnStrings() {
284         assertTrue(StringUtils.equals(null, null));
285         assertTrue(StringUtils.equals(FOO, FOO));
286         assertTrue(StringUtils.equals(FOO, new String(new char[] { 'f', 'o', 'o' })));
287         assertFalse(StringUtils.equals(FOO, new String(new char[] { 'f', 'O', 'O' })));
288         assertFalse(StringUtils.equals(FOO, BAR));
289         assertFalse(StringUtils.equals(FOO, null));
290         assertFalse(StringUtils.equals(null, FOO));
291         assertFalse(StringUtils.equals(FOO, FOOBAR));
292         assertFalse(StringUtils.equals(FOOBAR, FOO));
293     }
294 
295     @Test
296     void testIndexOf_char() {
297         assertEquals(-1, StringUtils.indexOf(null, ' '));
298         assertEquals(-1, StringUtils.indexOf("", ' '));
299         assertEquals(0, StringUtils.indexOf("aabaabaa", 'a'));
300         assertEquals(2, StringUtils.indexOf("aabaabaa", 'b'));
301 
302         assertEquals(2, StringUtils.indexOf(new StringBuilder("aabaabaa"), 'b'));
303         assertEquals(StringUtils.INDEX_NOT_FOUND, StringUtils.indexOf(new StringBuilder("aabaabaa"), -1738));
304     }
305 
306     @Test
307     void testIndexOf_charInt() {
308         assertEquals(-1, StringUtils.indexOf(null, ' ', 0));
309         assertEquals(-1, StringUtils.indexOf(null, ' ', -1));
310         assertEquals(-1, StringUtils.indexOf("", ' ', 0));
311         assertEquals(-1, StringUtils.indexOf("", ' ', -1));
312         assertEquals(0, StringUtils.indexOf("aabaabaa", 'a', 0));
313         assertEquals(2, StringUtils.indexOf("aabaabaa", 'b', 0));
314         assertEquals(5, StringUtils.indexOf("aabaabaa", 'b', 3));
315         assertEquals(-1, StringUtils.indexOf("aabaabaa", 'b', 9));
316         assertEquals(2, StringUtils.indexOf("aabaabaa", 'b', -1));
317 
318         assertEquals(5, StringUtils.indexOf(new StringBuilder("aabaabaa"), 'b', 3));
319 
320         //LANG-1300 tests go here
321         final int CODE_POINT = 0x2070E;
322         StringBuilder builder = new StringBuilder();
323         builder.appendCodePoint(CODE_POINT);
324         assertEquals(0, StringUtils.indexOf(builder, CODE_POINT, 0));
325         assertEquals(0, StringUtils.indexOf(builder.toString(), CODE_POINT, 0));
326         builder.appendCodePoint(CODE_POINT);
327         assertEquals(2, StringUtils.indexOf(builder, CODE_POINT, 1));
328         assertEquals(2, StringUtils.indexOf(builder.toString(), CODE_POINT, 1));
329         // inner branch on the supplementary character block
330         final char[] tmp = { (char) 55361 };
331         builder = new StringBuilder();
332         builder.append(tmp);
333         assertEquals(-1, StringUtils.indexOf(builder, CODE_POINT, 0));
334         assertEquals(-1, StringUtils.indexOf(builder.toString(), CODE_POINT, 0));
335         builder.appendCodePoint(CODE_POINT);
336         assertEquals(1, StringUtils.indexOf(builder, CODE_POINT, 0));
337         assertEquals(1, StringUtils.indexOf(builder.toString(), CODE_POINT, 0));
338         assertEquals(-1, StringUtils.indexOf(builder, CODE_POINT, 2));
339         assertEquals(-1, StringUtils.indexOf(builder.toString(), CODE_POINT, 2));
340     }
341 
342     @Test
343     void testIndexOf_String() {
344         assertEquals(-1, StringUtils.indexOf(null, null));
345         assertEquals(-1, StringUtils.indexOf("", null));
346         assertEquals(0, StringUtils.indexOf("", ""));
347         assertEquals(0, StringUtils.indexOf("aabaabaa", "a"));
348         assertEquals(2, StringUtils.indexOf("aabaabaa", "b"));
349         assertEquals(1, StringUtils.indexOf("aabaabaa", "ab"));
350         assertEquals(0, StringUtils.indexOf("aabaabaa", ""));
351 
352         assertEquals(2, StringUtils.indexOf(new StringBuilder("aabaabaa"), "b"));
353     }
354 
355     @Test
356     void testIndexOf_StringInt() {
357         assertEquals(-1, StringUtils.indexOf(null, null, 0));
358         assertEquals(-1, StringUtils.indexOf(null, null, -1));
359         assertEquals(-1, StringUtils.indexOf(null, "", 0));
360         assertEquals(-1, StringUtils.indexOf(null, "", -1));
361         assertEquals(-1, StringUtils.indexOf("", null, 0));
362         assertEquals(-1, StringUtils.indexOf("", null, -1));
363         assertEquals(0, StringUtils.indexOf("", "", 0));
364         assertEquals(0, StringUtils.indexOf("", "", -1));
365         assertEquals(0, StringUtils.indexOf("", "", 9));
366         assertEquals(0, StringUtils.indexOf("abc", "", 0));
367         assertEquals(0, StringUtils.indexOf("abc", "", -1));
368         assertEquals(3, StringUtils.indexOf("abc", "", 9));
369         assertEquals(3, StringUtils.indexOf("abc", "", 3));
370         assertEquals(0, StringUtils.indexOf("aabaabaa", "a", 0));
371         assertEquals(2, StringUtils.indexOf("aabaabaa", "b", 0));
372         assertEquals(1, StringUtils.indexOf("aabaabaa", "ab", 0));
373         assertEquals(5, StringUtils.indexOf("aabaabaa", "b", 3));
374         assertEquals(-1, StringUtils.indexOf("aabaabaa", "b", 9));
375         assertEquals(2, StringUtils.indexOf("aabaabaa", "b", -1));
376         assertEquals(2, StringUtils.indexOf("aabaabaa", "", 2));
377 
378         // Test that startIndex works correctly, i.e. cannot match before startIndex
379         assertEquals(7, StringUtils.indexOf("12345678", "8", 5));
380         assertEquals(7, StringUtils.indexOf("12345678", "8", 6));
381         assertEquals(7, StringUtils.indexOf("12345678", "8", 7)); // 7 is last index
382         assertEquals(-1, StringUtils.indexOf("12345678", "8", 8));
383 
384         assertEquals(5, StringUtils.indexOf(new StringBuilder("aabaabaa"), "b", 3));
385     }
386 
387     @Test
388     void testIndexOfAny_StringCharArray() {
389         assertEquals(-1, StringUtils.indexOfAny(null, (char[]) null));
390         assertEquals(-1, StringUtils.indexOfAny(null, new char[0]));
391         assertEquals(-1, StringUtils.indexOfAny(null, 'a', 'b'));
392         assertEquals(-1, StringUtils.indexOfAny("", (char[]) null));
393         assertEquals(-1, StringUtils.indexOfAny("", new char[0]));
394         assertEquals(-1, StringUtils.indexOfAny("", 'a', 'b'));
395         assertEquals(-1, StringUtils.indexOfAny("zzabyycdxx", (char[]) null));
396         assertEquals(-1, StringUtils.indexOfAny("zzabyycdxx", new char[0]));
397         assertEquals(0, StringUtils.indexOfAny("zzabyycdxx", 'z', 'a'));
398         assertEquals(3, StringUtils.indexOfAny("zzabyycdxx", 'b', 'y'));
399         assertEquals(-1, StringUtils.indexOfAny("ab", 'z'));
400         // if more than one search char is present, the order of the search chars matters:
401         assertEquals(0, StringUtils.indexOfAny("abcd", 'a', 'b', 'c', 'd'));
402         assertEquals(0, StringUtils.indexOfAny("bcda", 'a', 'b', 'c', 'd'));
403         assertEquals(0, StringUtils.indexOfAny("cbda", 'a', 'b', 'c', 'd'));
404     }
405 
406     /**
407      * A low surrogate that is the low half of a supplementary code point in the search set must not match the low half of a different code point in the input,
408      * otherwise the returned index points inside a surrogate pair. See https://www.oracle.com/technical-resources/articles/javase/supplementary.html
409      */
410     @Test
411     void testIndexOfAny_StringCharArrayWithSharedLowSurrogate() {
412         assertEquals(CharU20000.charAt(1), CharU24000.charAt(1));
413         assertEquals(-1, StringUtils.indexOfAny(CharU20000, CharU24000.toCharArray()));
414         assertEquals(-1, StringUtils.indexOfAny("abc" + CharU20000, CharU24000.toCharArray()));
415         // A genuine occurrence of the same pair is found at the start of the pair.
416         assertEquals(3, StringUtils.indexOfAny("abc" + CharU24000, CharU24000.toCharArray()));
417     }
418 
419     /**
420      * See https://www.oracle.com/technical-resources/articles/javase/supplementary.html
421      */
422     @Test
423     void testIndexOfAny_StringCharArrayWithSupplementaryChars() {
424         assertEquals(0, StringUtils.indexOfAny(CharU20000 + CharU20001, CharU20000.toCharArray()));
425         assertEquals(2, StringUtils.indexOfAny(CharU20000 + CharU20001, CharU20001.toCharArray()));
426         assertEquals(0, StringUtils.indexOfAny(CharU20000, CharU20000.toCharArray()));
427         assertEquals(-1, StringUtils.indexOfAny(CharU20000, CharU20001.toCharArray()));
428         // An unpaired trailing high surrogate must not match a supplementary code point, matching containsAny.
429         assertEquals(-1, StringUtils.indexOfAny(CharUSuppCharHigh, CharU20001.toCharArray()));
430         assertFalse(StringUtils.containsAny(CharUSuppCharHigh, CharU20001.toCharArray()));
431         assertEquals(-1, StringUtils.indexOfAny("abc" + CharUSuppCharHigh, CharU20000.toCharArray()));
432     }
433 
434     @Test
435     void testIndexOfAny_StringIntCharArray() {
436         // default cases
437         assertEquals(-1, StringUtils.indexOfAny(null, 0, (char[]) null));
438         assertEquals(-1, StringUtils.indexOfAny(null, 0, new char[0]));
439         assertEquals(-1, StringUtils.indexOfAny(null, 0, 'a', 'b'));
440         assertEquals(-1, StringUtils.indexOfAny("", 0, (char[]) null));
441         assertEquals(-1, StringUtils.indexOfAny("", 0, new char[0]));
442         assertEquals(-1, StringUtils.indexOfAny("", 0, 'a', 'b'));
443         assertEquals(-1, StringUtils.indexOfAny("zzabyycdxx", 0, (char[]) null));
444         assertEquals(-1, StringUtils.indexOfAny("zzabyycdxx", 0, new char[0]));
445         assertEquals(0, StringUtils.indexOfAny("zzabyycdxx", 0, 'z', 'a'));
446         assertEquals(3, StringUtils.indexOfAny("zzabyycdxx", 0, 'b', 'y'));
447         assertEquals(-1, StringUtils.indexOfAny("ab", 0, 'z'));
448         // if more than one search char is present, the order of the search chars matters:
449         assertEquals(0, StringUtils.indexOfAny("abcd", 0, 'a', 'b', 'c', 'd'));
450         assertEquals(0, StringUtils.indexOfAny("bcda", 0, 'a', 'b', 'c', 'd'));
451         assertEquals(0, StringUtils.indexOfAny("cbda", 0, 'a', 'b', 'c', 'd'));
452         // Actually use the index
453         assertEquals(-1, StringUtils.indexOfAny(null, 1, (char[]) null));
454         assertEquals(-1, StringUtils.indexOfAny(null, 1, new char[0]));
455         assertEquals(-1, StringUtils.indexOfAny(null, 1, 'a', 'b'));
456         assertEquals(-1, StringUtils.indexOfAny("", 1, (char[]) null));
457         assertEquals(-1, StringUtils.indexOfAny("", 1, new char[0]));
458         assertEquals(-1, StringUtils.indexOfAny("", 1, 'a', 'b'));
459         assertEquals(-1, StringUtils.indexOfAny("zzabyycdxx", 1, (char[]) null));
460         assertEquals(-1, StringUtils.indexOfAny("zzabyycdxx", 1, new char[0]));
461         assertEquals(1, StringUtils.indexOfAny("zzabyycdxx", 1, 'z', 'a'));
462         assertEquals(3, StringUtils.indexOfAny("zzabyycdxx", 1, 'b', 'y'));
463         assertEquals(-1, StringUtils.indexOfAny("ab", 1, 'z'));
464         // if more than one search char is present, the order of the search chars matters:
465         assertEquals(1, StringUtils.indexOfAny("abcd", 1, 'a', 'b', 'c', 'd'));
466         assertEquals(1, StringUtils.indexOfAny("bcda", 1, 'a', 'b', 'c', 'd'));
467         assertEquals(1, StringUtils.indexOfAny("cbda", 1, 'a', 'b', 'c', 'd'));
468     }
469 
470     @Test
471     void testIndexOfAny_StringString() {
472         assertEquals(-1, StringUtils.indexOfAny(null, (String) null));
473         assertEquals(-1, StringUtils.indexOfAny(null, ""));
474         assertEquals(-1, StringUtils.indexOfAny(null, "ab"));
475 
476         assertEquals(-1, StringUtils.indexOfAny("", (String) null));
477         assertEquals(-1, StringUtils.indexOfAny("", ""));
478         assertEquals(-1, StringUtils.indexOfAny("", "ab"));
479 
480         assertEquals(-1, StringUtils.indexOfAny("zzabyycdxx", (String) null));
481         assertEquals(-1, StringUtils.indexOfAny("zzabyycdxx", ""));
482         assertEquals(0, StringUtils.indexOfAny("zzabyycdxx", "za"));
483         assertEquals(3, StringUtils.indexOfAny("zzabyycdxx", "by"));
484         assertEquals(-1, StringUtils.indexOfAny("ab", "z"));
485     }
486 
487     @Test
488     void testIndexOfAny_StringStringArray() {
489         assertEquals(-1, StringUtils.indexOfAny(null, (String[]) null));
490         assertEquals(-1, StringUtils.indexOfAny(null, FOOBAR_SUB_ARRAY));
491         assertEquals(-1, StringUtils.indexOfAny(FOOBAR, (String[]) null));
492         assertEquals(2, StringUtils.indexOfAny(FOOBAR, FOOBAR_SUB_ARRAY));
493         assertEquals(-1, StringUtils.indexOfAny(FOOBAR, new String[0]));
494         assertEquals(-1, StringUtils.indexOfAny(null, new String[0]));
495         assertEquals(-1, StringUtils.indexOfAny("", new String[0]));
496         assertEquals(-1, StringUtils.indexOfAny(FOOBAR, new String[] {"llll"}));
497         assertEquals(0, StringUtils.indexOfAny(FOOBAR, new String[] {""}));
498         assertEquals(0, StringUtils.indexOfAny("", new String[] {""}));
499         assertEquals(-1, StringUtils.indexOfAny("", new String[] {"a"}));
500         assertEquals(-1, StringUtils.indexOfAny("", new String[] {null}));
501         assertEquals(-1, StringUtils.indexOfAny(FOOBAR, new String[] {null}));
502         assertEquals(-1, StringUtils.indexOfAny(null, new String[] {null}));
503     }
504 
505     /**
506      * See https://www.oracle.com/technical-resources/articles/javase/supplementary.html
507      */
508     @Test
509     void testIndexOfAny_StringStringWithSupplementaryChars() {
510         assertEquals(0, StringUtils.indexOfAny(CharU20000 + CharU20001, CharU20000));
511         assertEquals(2, StringUtils.indexOfAny(CharU20000 + CharU20001, CharU20001));
512         assertEquals(0, StringUtils.indexOfAny(CharU20000, CharU20000));
513         assertEquals(-1, StringUtils.indexOfAny(CharU20000, CharU20001));
514     }
515 
516     @Test
517     void testIndexOfAnyBut_StringCharArray() {
518         assertEquals(-1, StringUtils.indexOfAnyBut(null, (char[]) null));
519         assertEquals(-1, StringUtils.indexOfAnyBut(null));
520         assertEquals(-1, StringUtils.indexOfAnyBut(null, 'a', 'b'));
521 
522         assertEquals(-1, StringUtils.indexOfAnyBut("", (char[]) null));
523         assertEquals(-1, StringUtils.indexOfAnyBut(""));
524         assertEquals(-1, StringUtils.indexOfAnyBut("", 'a', 'b'));
525 
526         assertEquals(-1, StringUtils.indexOfAnyBut("zzabyycdxx", (char[]) null));
527         assertEquals(-1, StringUtils.indexOfAnyBut("zzabyycdxx"));
528         assertEquals(3, StringUtils.indexOfAnyBut("zzabyycdxx", 'z', 'a'));
529         assertEquals(0, StringUtils.indexOfAnyBut("zzabyycdxx", 'b', 'y'));
530         assertEquals(-1, StringUtils.indexOfAnyBut("aba", 'a', 'b'));
531         assertEquals(0, StringUtils.indexOfAnyBut("aba", 'z'));
532     }
533 
534     @ParameterizedTest
535     @MethodSource("indexOfAnyBut_withSurrogateChars")
536     void testIndexOfAnyBut_StringCharArrayWithSurrogateChars(final CharSequence seq, final String searchChars, final int expected) {
537         assertEquals(expected, StringUtils.indexOfAnyBut(seq, searchChars.toCharArray()));
538     }
539 
540     @Test
541     void testIndexOfAnyBut_StringString() {
542         assertEquals(-1, StringUtils.indexOfAnyBut(null, (String) null));
543         assertEquals(-1, StringUtils.indexOfAnyBut(null, ""));
544         assertEquals(-1, StringUtils.indexOfAnyBut(null, "ab"));
545 
546         assertEquals(-1, StringUtils.indexOfAnyBut("", (String) null));
547         assertEquals(-1, StringUtils.indexOfAnyBut("", ""));
548         assertEquals(-1, StringUtils.indexOfAnyBut("", "ab"));
549 
550         assertEquals(-1, StringUtils.indexOfAnyBut("zzabyycdxx", (String) null));
551         assertEquals(-1, StringUtils.indexOfAnyBut("zzabyycdxx", ""));
552         assertEquals(3, StringUtils.indexOfAnyBut("zzabyycdxx", "za"));
553         assertEquals(0, StringUtils.indexOfAnyBut("zzabyycdxx", "by"));
554         assertEquals(0, StringUtils.indexOfAnyBut("ab", "z"));
555     }
556 
557     @ParameterizedTest
558     @MethodSource("indexOfAnyBut_withSurrogateChars")
559     void testIndexOfAnyBut_StringStringWithSurrogateChars(final CharSequence seq, final CharSequence searchChars, final int expected) {
560         assertEquals(expected, StringUtils.indexOfAnyBut(seq, searchChars));
561     }
562 
563     @Test
564     void testIndexOfIgnoreCase_String() {
565         assertEquals(-1, StringUtils.indexOfIgnoreCase(null, null));
566         assertEquals(-1, StringUtils.indexOfIgnoreCase(null, ""));
567         assertEquals(-1, StringUtils.indexOfIgnoreCase("", null));
568         assertEquals(0, StringUtils.indexOfIgnoreCase("", ""));
569         assertEquals(0, StringUtils.indexOfIgnoreCase("aabaabaa", "a"));
570         assertEquals(0, StringUtils.indexOfIgnoreCase("aabaabaa", "A"));
571         assertEquals(2, StringUtils.indexOfIgnoreCase("aabaabaa", "b"));
572         assertEquals(2, StringUtils.indexOfIgnoreCase("aabaabaa", "B"));
573         assertEquals(1, StringUtils.indexOfIgnoreCase("aabaabaa", "ab"));
574         assertEquals(1, StringUtils.indexOfIgnoreCase("aabaabaa", "AB"));
575         assertEquals(0, StringUtils.indexOfIgnoreCase("aabaabaa", ""));
576     }
577 
578     @Test
579     void testIndexOfIgnoreCase_StringInt() {
580         assertEquals(1, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", -1));
581         assertEquals(1, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0));
582         assertEquals(1, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 1));
583         assertEquals(4, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 2));
584         assertEquals(4, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 3));
585         assertEquals(4, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 4));
586         assertEquals(-1, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 5));
587         assertEquals(-1, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 6));
588         assertEquals(-1, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 7));
589         assertEquals(-1, StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 8));
590         assertEquals(1, StringUtils.indexOfIgnoreCase("aab", "AB", 1));
591         assertEquals(5, StringUtils.indexOfIgnoreCase("aabaabaa", "", 5));
592         assertEquals(-1, StringUtils.indexOfIgnoreCase("ab", "AAB", 0));
593         assertEquals(-1, StringUtils.indexOfIgnoreCase("aab", "AAB", 1));
594         assertEquals(-1, StringUtils.indexOfIgnoreCase("abc", "", 9));
595     }
596 
597     @Test
598     void testLANG1193() {
599         assertEquals(0, StringUtils.ordinalIndexOf("abc", "ab", 1));
600     }
601 
602     @Test
603     // Non-overlapping test
604     void testLANG1241_1() {
605         //                                          0  3  6
606         assertEquals(0, StringUtils.ordinalIndexOf("abaabaab", "ab", 1));
607         assertEquals(3, StringUtils.ordinalIndexOf("abaabaab", "ab", 2));
608         assertEquals(6, StringUtils.ordinalIndexOf("abaabaab", "ab", 3));
609     }
610 
611     @Test
612     // Overlapping matching test
613     void testLANG1241_2() {
614         //                                          0 2 4
615         assertEquals(0, StringUtils.ordinalIndexOf("abababa", "aba", 1));
616         assertEquals(2, StringUtils.ordinalIndexOf("abababa", "aba", 2));
617         assertEquals(4, StringUtils.ordinalIndexOf("abababa", "aba", 3));
618         assertEquals(0, StringUtils.ordinalIndexOf("abababab", "abab", 1));
619         assertEquals(2, StringUtils.ordinalIndexOf("abababab", "abab", 2));
620         assertEquals(4, StringUtils.ordinalIndexOf("abababab", "abab", 3));
621     }
622 
623     @Test
624     void testLastIndexOf_char() {
625         assertEquals(-1, StringUtils.lastIndexOf(null, ' '));
626         assertEquals(-1, StringUtils.lastIndexOf("", ' '));
627         assertEquals(7, StringUtils.lastIndexOf("aabaabaa", 'a'));
628         assertEquals(5, StringUtils.lastIndexOf("aabaabaa", 'b'));
629 
630         assertEquals(5, StringUtils.lastIndexOf(new StringBuilder("aabaabaa"), 'b'));
631 
632         // LANG-1300: supplementary code points searched in a non-String CharSequence must agree with String
633         final int supp = 0x2070E;
634         final String suppStr = new String(Character.toChars(supp));
635         assertEquals(suppStr.lastIndexOf(supp), StringUtils.lastIndexOf(new StringBuilder(suppStr), supp));
636         assertEquals(("x" + suppStr).lastIndexOf(supp), StringUtils.lastIndexOf(new StringBuilder("x" + suppStr), supp));
637         assertEquals((suppStr + "y").lastIndexOf(supp), StringUtils.lastIndexOf(new StringBuilder(suppStr + "y"), supp));
638     }
639 
640     @Test
641     void testLastIndexOf_charInt() {
642         assertEquals(-1, StringUtils.lastIndexOf(null, ' ', 0));
643         assertEquals(-1, StringUtils.lastIndexOf(null, ' ', -1));
644         assertEquals(-1, StringUtils.lastIndexOf("", ' ', 0));
645         assertEquals(-1, StringUtils.lastIndexOf("", ' ', -1));
646         assertEquals(7, StringUtils.lastIndexOf("aabaabaa", 'a', 8));
647         assertEquals(5, StringUtils.lastIndexOf("aabaabaa", 'b', 8));
648         assertEquals(2, StringUtils.lastIndexOf("aabaabaa", 'b', 3));
649         assertEquals(5, StringUtils.lastIndexOf("aabaabaa", 'b', 9));
650         assertEquals(-1, StringUtils.lastIndexOf("aabaabaa", 'b', -1));
651         assertEquals(0, StringUtils.lastIndexOf("aabaabaa", 'a', 0));
652 
653         assertEquals(2, StringUtils.lastIndexOf(new StringBuilder("aabaabaa"), 'b', 2));
654 
655         //LANG-1300 addition test
656         final int CODE_POINT = 0x2070E;
657         StringBuilder builder = new StringBuilder();
658         builder.appendCodePoint(CODE_POINT);
659         assertEquals(0, StringUtils.lastIndexOf(builder, CODE_POINT, 0));
660         builder.appendCodePoint(CODE_POINT);
661         assertEquals(0, StringUtils.lastIndexOf(builder, CODE_POINT, 0));
662         assertEquals(0, StringUtils.lastIndexOf(builder, CODE_POINT, 1));
663         assertEquals(2, StringUtils.lastIndexOf(builder, CODE_POINT, 2));
664 
665         builder.append("aaaaa");
666         assertEquals(2, StringUtils.lastIndexOf(builder, CODE_POINT, 4));
667         // inner branch on the supplementary character block
668         final char[] tmp = { (char) 55361 };
669         builder = new StringBuilder();
670         builder.append(tmp);
671         assertEquals(-1, StringUtils.lastIndexOf(builder, CODE_POINT, 0));
672         builder.appendCodePoint(CODE_POINT);
673         assertEquals(-1, StringUtils.lastIndexOf(builder, CODE_POINT, 0));
674         assertEquals(1, StringUtils.lastIndexOf(builder, CODE_POINT, 1));
675         assertEquals(-1, StringUtils.lastIndexOf(builder.toString(), CODE_POINT, 0));
676         assertEquals(1, StringUtils.lastIndexOf(builder.toString(), CODE_POINT, 1));
677         assertEquals(StringUtils.INDEX_NOT_FOUND, StringUtils.lastIndexOf(CharBuffer.wrap("[%{.c.0rro"), -1738, 982));
678     }
679 
680     @Test
681     void testLastIndexOf_String() {
682         assertEquals(-1, StringUtils.lastIndexOf(null, null));
683         assertEquals(-1, StringUtils.lastIndexOf("", null));
684         assertEquals(-1, StringUtils.lastIndexOf("", "a"));
685         assertEquals(0, StringUtils.lastIndexOf("", ""));
686         assertEquals(8, StringUtils.lastIndexOf("aabaabaa", ""));
687         assertEquals(7, StringUtils.lastIndexOf("aabaabaa", "a"));
688         assertEquals(5, StringUtils.lastIndexOf("aabaabaa", "b"));
689         assertEquals(4, StringUtils.lastIndexOf("aabaabaa", "ab"));
690 
691         assertEquals(4, StringUtils.lastIndexOf(new StringBuilder("aabaabaa"), "ab"));
692     }
693 
694     @Test
695     void testLastIndexOf_StringInt() {
696         assertEquals(-1, StringUtils.lastIndexOf(null, null, 0));
697         assertEquals(-1, StringUtils.lastIndexOf(null, null, -1));
698         assertEquals(-1, StringUtils.lastIndexOf(null, "", 0));
699         assertEquals(-1, StringUtils.lastIndexOf(null, "", -1));
700         assertEquals(-1, StringUtils.lastIndexOf("", null, 0));
701         assertEquals(-1, StringUtils.lastIndexOf("", null, -1));
702         assertEquals(0, StringUtils.lastIndexOf("", "", 0));
703         assertEquals(-1, StringUtils.lastIndexOf("", "", -1));
704         assertEquals(0, StringUtils.lastIndexOf("", "", 9));
705         assertEquals(0, StringUtils.lastIndexOf("abc", "", 0));
706         assertEquals(-1, StringUtils.lastIndexOf("abc", "", -1));
707         assertEquals(3, StringUtils.lastIndexOf("abc", "", 9));
708         assertEquals(7, StringUtils.lastIndexOf("aabaabaa", "a", 8));
709         assertEquals(5, StringUtils.lastIndexOf("aabaabaa", "b", 8));
710         assertEquals(4, StringUtils.lastIndexOf("aabaabaa", "ab", 8));
711         assertEquals(2, StringUtils.lastIndexOf("aabaabaa", "b", 3));
712         assertEquals(5, StringUtils.lastIndexOf("aabaabaa", "b", 9));
713         assertEquals(-1, StringUtils.lastIndexOf("aabaabaa", "b", -1));
714         assertEquals(-1, StringUtils.lastIndexOf("aabaabaa", "b", 0));
715         assertEquals(0, StringUtils.lastIndexOf("aabaabaa", "a", 0));
716         assertEquals(-1, StringUtils.lastIndexOf("aabaabaa", "a", -1));
717 
718         // Test that fromIndex works correctly, i.e. cannot match after fromIndex
719         assertEquals(7, StringUtils.lastIndexOf("12345678", "8", 9));
720         assertEquals(7, StringUtils.lastIndexOf("12345678", "8", 8));
721         assertEquals(7, StringUtils.lastIndexOf("12345678", "8", 7)); // 7 is last index
722         assertEquals(-1, StringUtils.lastIndexOf("12345678", "8", 6));
723 
724         assertEquals(-1, StringUtils.lastIndexOf("aabaabaa", "b", 1));
725         assertEquals(2, StringUtils.lastIndexOf("aabaabaa", "b", 2));
726         assertEquals(2, StringUtils.lastIndexOf("aabaabaa", "ba", 2));
727         assertEquals(2, StringUtils.lastIndexOf("aabaabaa", "ba", 3));
728 
729         assertEquals(2, StringUtils.lastIndexOf(new StringBuilder("aabaabaa"), "b", 3));
730     }
731 
732     @Test
733     void testLastIndexOfAny_StringStringArray() {
734         assertEquals(-1, StringUtils.lastIndexOfAny(null, (CharSequence) null));   // test both types of ...
735         assertEquals(-1, StringUtils.lastIndexOfAny(null, (CharSequence[]) null)); // ... varargs invocation
736         assertEquals(-1, StringUtils.lastIndexOfAny(null)); // Missing varag
737         assertEquals(-1, StringUtils.lastIndexOfAny(null, FOOBAR_SUB_ARRAY));
738         assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR, (CharSequence) null));   // test both types of ...
739         assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR, (CharSequence[]) null)); // ... varargs invocation
740         assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR)); // Missing vararg
741         assertEquals(3, StringUtils.lastIndexOfAny(FOOBAR, FOOBAR_SUB_ARRAY));
742         assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR, new String[0]));
743         assertEquals(-1, StringUtils.lastIndexOfAny(null, new String[0]));
744         assertEquals(-1, StringUtils.lastIndexOfAny("", new String[0]));
745         assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR, new String[] {"llll"}));
746         assertEquals(6, StringUtils.lastIndexOfAny(FOOBAR, new String[] {""}));
747         assertEquals(0, StringUtils.lastIndexOfAny("", new String[] {""}));
748         assertEquals(-1, StringUtils.lastIndexOfAny("", new String[] {"a"}));
749         assertEquals(-1, StringUtils.lastIndexOfAny("", new String[] {null}));
750         assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR, new String[] {null}));
751         assertEquals(-1, StringUtils.lastIndexOfAny(null, new String[] {null}));
752     }
753 
754     @Test
755     void testLastIndexOfIgnoreCase_String() {
756         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase(null, null));
757         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("", null));
758         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase(null, ""));
759         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("", "a"));
760         assertEquals(0, StringUtils.lastIndexOfIgnoreCase("", ""));
761         assertEquals(8, StringUtils.lastIndexOfIgnoreCase("aabaabaa", ""));
762         assertEquals(7, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "a"));
763         assertEquals(7, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A"));
764         assertEquals(5, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "b"));
765         assertEquals(5, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B"));
766         assertEquals(4, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "ab"));
767         assertEquals(4, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB"));
768         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("ab", "AAB"));
769         assertEquals(0, StringUtils.lastIndexOfIgnoreCase("aab", "AAB"));
770     }
771 
772     @Test
773     void testLastIndexOfIgnoreCase_StringInt() {
774         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase(null, null, 0));
775         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase(null, null, -1));
776         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase(null, "", 0));
777         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase(null, "", -1));
778         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("", null, 0));
779         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("", null, -1));
780         assertEquals(0, StringUtils.lastIndexOfIgnoreCase("", "", 0));
781         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("", "", -1));
782         assertEquals(0, StringUtils.lastIndexOfIgnoreCase("", "", 9));
783         assertEquals(0, StringUtils.lastIndexOfIgnoreCase("abc", "", 0));
784         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("abc", "", -1));
785         assertEquals(3, StringUtils.lastIndexOfIgnoreCase("abc", "", 9));
786         assertEquals(7, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8));
787         assertEquals(5, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8));
788         assertEquals(4, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8));
789         assertEquals(2, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 3));
790         assertEquals(5, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9));
791         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1));
792         assertEquals(-1, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0));
793         assertEquals(0, StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0));
794         assertEquals(1, StringUtils.lastIndexOfIgnoreCase("aab", "AB", 1));
795     }
796 
797     @Test
798     void testLastOrdinalIndexOf() {
799         assertEquals(-1, StringUtils.lastOrdinalIndexOf(null, "*", 42));
800         assertEquals(-1, StringUtils.lastOrdinalIndexOf("*", null, 42));
801         assertEquals(0, StringUtils.lastOrdinalIndexOf("", "", 42));
802         assertEquals(7, StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1));
803         assertEquals(6, StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2));
804         assertEquals(5, StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1));
805         assertEquals(2, StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2));
806         assertEquals(4, StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1));
807         assertEquals(1, StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2));
808         assertEquals(8, StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1));
809         assertEquals(8, StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2));
810     }
811 
812     @Test
813     void testOrdinalIndexOf() {
814         assertEquals(-1, StringUtils.ordinalIndexOf(null, null, Integer.MIN_VALUE));
815         assertEquals(-1, StringUtils.ordinalIndexOf("", null, Integer.MIN_VALUE));
816         assertEquals(-1, StringUtils.ordinalIndexOf("", "", Integer.MIN_VALUE));
817         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "a", Integer.MIN_VALUE));
818         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "b", Integer.MIN_VALUE));
819         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "ab", Integer.MIN_VALUE));
820         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "", Integer.MIN_VALUE));
821 
822         assertEquals(-1, StringUtils.ordinalIndexOf(null, null, -1));
823         assertEquals(-1, StringUtils.ordinalIndexOf("", null, -1));
824         assertEquals(-1, StringUtils.ordinalIndexOf("", "", -1));
825         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "a", -1));
826         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "b", -1));
827         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "ab", -1));
828         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "", -1));
829 
830         assertEquals(-1, StringUtils.ordinalIndexOf(null, null, 0));
831         assertEquals(-1, StringUtils.ordinalIndexOf("", null, 0));
832         assertEquals(-1, StringUtils.ordinalIndexOf("", "", 0));
833         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "a", 0));
834         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "b", 0));
835         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "ab", 0));
836         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "", 0));
837 
838         assertEquals(-1, StringUtils.ordinalIndexOf(null, null, 1));
839         assertEquals(-1, StringUtils.ordinalIndexOf("", null, 1));
840         assertEquals(0, StringUtils.ordinalIndexOf("", "", 1));
841         assertEquals(0, StringUtils.ordinalIndexOf("aabaabaa", "a", 1));
842         assertEquals(2, StringUtils.ordinalIndexOf("aabaabaa", "b", 1));
843         assertEquals(1, StringUtils.ordinalIndexOf("aabaabaa", "ab", 1));
844         assertEquals(0, StringUtils.ordinalIndexOf("aabaabaa", "", 1));
845 
846         assertEquals(-1, StringUtils.ordinalIndexOf(null, null, 2));
847         assertEquals(-1, StringUtils.ordinalIndexOf("", null, 2));
848         assertEquals(0, StringUtils.ordinalIndexOf("", "", 2));
849         assertEquals(1, StringUtils.ordinalIndexOf("aabaabaa", "a", 2));
850         assertEquals(5, StringUtils.ordinalIndexOf("aabaabaa", "b", 2));
851         assertEquals(4, StringUtils.ordinalIndexOf("aabaabaa", "ab", 2));
852         assertEquals(0, StringUtils.ordinalIndexOf("aabaabaa", "", 2));
853 
854         assertEquals(-1, StringUtils.ordinalIndexOf(null, null, Integer.MAX_VALUE));
855         assertEquals(-1, StringUtils.ordinalIndexOf("", null, Integer.MAX_VALUE));
856         assertEquals(0, StringUtils.ordinalIndexOf("", "", Integer.MAX_VALUE));
857         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "a", Integer.MAX_VALUE));
858         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "b", Integer.MAX_VALUE));
859         assertEquals(-1, StringUtils.ordinalIndexOf("aabaabaa", "ab", Integer.MAX_VALUE));
860         assertEquals(0, StringUtils.ordinalIndexOf("aabaabaa", "", Integer.MAX_VALUE));
861 
862         assertEquals(-1, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 0));
863         assertEquals(0, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 1));
864         assertEquals(1, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 2));
865         assertEquals(2, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 3));
866         assertEquals(3, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 4));
867         assertEquals(4, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 5));
868         assertEquals(5, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 6));
869         assertEquals(6, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 7));
870         assertEquals(7, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 8));
871         assertEquals(8, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 9));
872         assertEquals(-1, StringUtils.ordinalIndexOf("aaaaaaaaa", "a", 10));
873 
874         // match at each possible position
875         assertEquals(0, StringUtils.ordinalIndexOf("aaaaaa", "aa", 1));
876         assertEquals(1, StringUtils.ordinalIndexOf("aaaaaa", "aa", 2));
877         assertEquals(2, StringUtils.ordinalIndexOf("aaaaaa", "aa", 3));
878         assertEquals(3, StringUtils.ordinalIndexOf("aaaaaa", "aa", 4));
879         assertEquals(4, StringUtils.ordinalIndexOf("aaaaaa", "aa", 5));
880         assertEquals(-1, StringUtils.ordinalIndexOf("aaaaaa", "aa", 6));
881 
882         assertEquals(0, StringUtils.ordinalIndexOf("ababab", "aba", 1));
883         assertEquals(2, StringUtils.ordinalIndexOf("ababab", "aba", 2));
884         assertEquals(-1, StringUtils.ordinalIndexOf("ababab", "aba", 3));
885 
886         assertEquals(0, StringUtils.ordinalIndexOf("abababab", "abab", 1));
887         assertEquals(2, StringUtils.ordinalIndexOf("abababab", "abab", 2));
888         assertEquals(4, StringUtils.ordinalIndexOf("abababab", "abab", 3));
889         assertEquals(-1, StringUtils.ordinalIndexOf("abababab", "abab", 4));
890     }
891 }