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  
18  package org.apache.commons.text;
19  
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.assertNotSame;
26  import static org.junit.jupiter.api.Assertions.assertNull;
27  import static org.junit.jupiter.api.Assertions.assertSame;
28  import static org.junit.jupiter.api.Assertions.assertThrows;
29  import static org.junit.jupiter.api.Assertions.assertTrue;
30  import static org.junit.jupiter.api.Assertions.fail;
31  
32  import java.io.IOException;
33  import java.io.Reader;
34  import java.io.StringReader;
35  import java.io.StringWriter;
36  import java.io.Writer;
37  import java.nio.ByteBuffer;
38  import java.nio.CharBuffer;
39  import java.nio.charset.Charset;
40  
41  import org.junit.jupiter.api.Test;
42  
43  /**
44   * Tests {@link StrBuilder}.
45   *
46   * @deprecated This class will be removed in 2.0.
47   */
48  @Deprecated
49  class StrBuilderTest {
50  
51      private static final class MockReadable implements Readable {
52  
53          private final CharBuffer src;
54  
55          MockReadable(final String src) {
56              this.src = CharBuffer.wrap(src);
57          }
58  
59          @Override
60          public int read(final CharBuffer cb) throws IOException {
61              return src.read(cb);
62          }
63      }
64  
65      static final StrMatcher A_NUMBER_MATCHER = new StrMatcher() {
66  
67          @Override
68          public int isMatch(final char[] buffer, int pos, final int bufferStart, final int bufferEnd) {
69              if (buffer[pos] == 'A') {
70                  pos++;
71                  if (pos < bufferEnd && buffer[pos] >= '0' && buffer[pos] <= '9') {
72                      return 2;
73                  }
74              }
75              return 0;
76          }
77      };
78  
79      @Test
80      void test_LANG_1131_EqualsWithNullStrBuilder() throws Exception {
81          final StrBuilder sb = new StrBuilder();
82          final StrBuilder other = null;
83          assertNotEquals(sb, other);
84      }
85  
86      @Test
87      void testAppendCharBuffer() {
88          final StrBuilder sb1 = new StrBuilder();
89          final CharBuffer buf = CharBuffer.allocate(10);
90          buf.append("0123456789");
91          buf.flip();
92          sb1.append(buf);
93          assertEquals("0123456789", sb1.toString());
94  
95          final StrBuilder sb2 = new StrBuilder();
96          sb2.append(buf, 1, 8);
97          assertEquals("12345678", sb2.toString());
98      }
99  
100     @Test
101     void testAppendCharBufferException() throws Exception {
102         final StrBuilder sb = new StrBuilder("1234567890");
103         final String text = "Test";
104         final CharBuffer buffer = CharBuffer.allocate(sb.size() + text.length());
105         buffer.put(text);
106         buffer.flip();
107         try {
108             sb.append(buffer, -1, 12);
109         } catch (final StringIndexOutOfBoundsException e) {
110             assertEquals("startIndex must be valid", e.getMessage());
111         }
112 
113         try {
114             sb.append(buffer, 0, -1);
115         } catch (final StringIndexOutOfBoundsException e) {
116             assertEquals("length must be valid", e.getMessage());
117         }
118 
119         sb.append(buffer);
120         assertEquals("1234567890Test", sb.toString());
121     }
122 
123     @Test
124     void testAppendCharBufferNull() throws Exception {
125         final StrBuilder sb = new StrBuilder("1234567890");
126         final CharBuffer buffer = null;
127         sb.append(buffer);
128         assertEquals("1234567890", sb.toString());
129 
130         final StrBuilder sb1 = new StrBuilder("1234567890");
131         final CharBuffer buffer1 = null;
132         sb.append(buffer1, 0, 0);
133         assertEquals("1234567890", sb1.toString());
134     }
135 
136     @Test
137     void testAppendCharSequence() {
138         final CharSequence obj0 = null;
139         final CharSequence obj1 = new StrBuilder("test1");
140         final CharSequence obj2 = new StringBuilder("test2");
141         final CharSequence obj3 = new StringBuffer("test3");
142         final CharBuffer obj4 = CharBuffer.wrap("test4".toCharArray());
143 
144         final StrBuilder sb0 = new StrBuilder();
145         assertEquals("", sb0.append(obj0).toString());
146 
147         final StrBuilder sb1 = new StrBuilder();
148         assertEquals("test1", sb1.append(obj1).toString());
149 
150         final StrBuilder sb2 = new StrBuilder();
151         assertEquals("test2", sb2.append(obj2).toString());
152 
153         final StrBuilder sb3 = new StrBuilder();
154         assertEquals("test3", sb3.append(obj3).toString());
155 
156         final StrBuilder sb4 = new StrBuilder();
157         assertEquals("test4", sb4.append(obj4).toString());
158 
159         final StrBuilder sb5 = new StrBuilder();
160         assertEquals("", sb5.append(obj0, 0, 0).toString());
161     }
162 
163     @Test
164     void testAppendln() {
165         final StrBuilder sb1 = new StrBuilder();
166         final char ch = 'c';
167         assertEquals("c" + System.lineSeparator(), sb1.appendln(ch).toString());
168     }
169 
170     @Test
171     void testAppendStringBuilderNull() {
172         final StrBuilder sb1 = new StrBuilder();
173         final StringBuilder b = null;
174         assertEquals("", sb1.append(b).toString());
175 
176         final StrBuilder sb2 = new StrBuilder();
177         assertEquals("", sb2.append(b, 0, 0).toString());
178     }
179 
180     @Test
181     void testAppendTakingTwoIntsWithIndexOutOfBoundsThrowsStringIndexOutOfBoundsExceptionTwo() {
182         assertThrows(StringIndexOutOfBoundsException.class, () -> {
183             final Charset charset = Charset.defaultCharset();
184             final ByteBuffer byteBuffer = charset.encode("asdf");
185             final CharBuffer charBuffer = charset.decode(byteBuffer);
186             new StrBuilder().append(charBuffer, 933, 654);
187         });
188     }
189 
190     @Test
191     void testAppendTakingTwoIntsWithZeroThrowsStringIndexOutOfBoundsException() {
192         assertThrows(StringIndexOutOfBoundsException.class, () -> {
193             final Charset charset = Charset.defaultCharset();
194             final ByteBuffer byteBuffer = charset.encode("end < start");
195             final CharBuffer charBuffer = charset.decode(byteBuffer);
196             new StrBuilder(630).append(charBuffer, 0, 630);
197         });
198     }
199 
200     @Test
201     void testAppendToCharBuffer() throws Exception {
202         final StrBuilder sb = new StrBuilder("1234567890");
203         final String text = "Test ";
204         final CharBuffer buffer = CharBuffer.allocate(sb.size() + text.length());
205         buffer.put(text);
206 
207         sb.appendTo(buffer);
208 
209         buffer.flip();
210         assertEquals("Test 1234567890", buffer.toString());
211     }
212 
213     @Test
214     void testAppendToStringBuffer() throws Exception {
215         final StrBuilder sb = new StrBuilder("1234567890");
216         final StringBuilder buffer = new StringBuilder("Test ");
217 
218         sb.appendTo(buffer);
219 
220         assertEquals("Test 1234567890", buffer.toString());
221     }
222 
223     @Test
224     void testAppendToStringBuilder() throws Exception {
225         final StrBuilder sb = new StrBuilder("1234567890");
226         final StringBuilder builder = new StringBuilder("Test ");
227 
228         sb.appendTo(builder);
229 
230         assertEquals("Test 1234567890", builder.toString());
231     }
232 
233     @Test
234     void testAppendToWriter() throws Exception {
235         final StrBuilder sb = new StrBuilder("1234567890");
236         final StringWriter writer = new StringWriter();
237         writer.append("Test ");
238 
239         sb.appendTo(writer);
240 
241         assertEquals("Test 1234567890", writer.toString());
242     }
243 
244     @Test
245     void testAsBuilder() {
246         final StrBuilder sb = new StrBuilder().appendAll("Lorem", " ", "ipsum", " ", "dolor");
247         assertEquals(sb.toString(), sb.build());
248     }
249 
250     @Test
251     void testAsReader() throws Exception {
252         final StrBuilder sb = new StrBuilder("some text");
253         try (Reader reader = sb.asReader()) {
254             assertTrue(reader.ready());
255             final char[] buf = new char[40];
256             assertEquals(9, reader.read(buf));
257             assertEquals("some text", new String(buf, 0, 9));
258 
259             assertEquals(-1, reader.read());
260             assertFalse(reader.ready());
261             assertEquals(0, reader.skip(2));
262             assertEquals(0, reader.skip(-1));
263 
264             assertTrue(reader.markSupported());
265         }
266         try (Reader reader = sb.asReader()) {
267             assertEquals('s', reader.read());
268             reader.mark(-1);
269             final char[] array = new char[3];
270             assertEquals(3, reader.read(array, 0, 3));
271             assertEquals('o', array[0]);
272             assertEquals('m', array[1]);
273             assertEquals('e', array[2]);
274             reader.reset();
275             assertEquals(1, reader.read(array, 1, 1));
276             assertEquals('o', array[0]);
277             assertEquals('o', array[1]);
278             assertEquals('e', array[2]);
279             assertEquals(2, reader.skip(2));
280             assertEquals(' ', reader.read());
281 
282             assertTrue(reader.ready());
283             reader.close();
284             assertTrue(reader.ready());
285         }
286         try (Reader reader = sb.asReader()) {
287             char[] array = new char[3];
288             try {
289                 reader.read(array, -1, 0);
290                 fail("Exception expected.");
291             } catch (final IndexOutOfBoundsException ex) {
292                 // expected
293             }
294             try {
295                 reader.read(array, 0, -1);
296                 fail("Exception expected.");
297             } catch (final IndexOutOfBoundsException ex) {
298                 // expected
299             }
300             try {
301                 reader.read(array, 100, 1);
302                 fail("Exception expected.");
303             } catch (final IndexOutOfBoundsException ex) {
304                 // expected
305             }
306             try {
307                 reader.read(array, 0, 100);
308                 fail("Exception expected.");
309             } catch (final IndexOutOfBoundsException ex) {
310                 // expected
311             }
312             try {
313                 reader.read(array, Integer.MAX_VALUE, Integer.MAX_VALUE);
314                 fail("Exception expected.");
315             } catch (final IndexOutOfBoundsException ex) {
316                 // expected
317             }
318 
319             assertEquals(0, reader.read(array, 0, 0));
320             assertEquals(0, array[0]);
321             assertEquals(0, array[1]);
322             assertEquals(0, array[2]);
323 
324             reader.skip(9);
325             assertEquals(-1, reader.read(array, 0, 1));
326 
327             reader.reset();
328             array = new char[30];
329             assertEquals(9, reader.read(array, 0, 30));
330         }
331     }
332 
333     @Test
334     void testAsTokenizer() throws Exception {
335         // from Javadoc
336         final StrBuilder b = new StrBuilder();
337         b.append("a b ");
338         final StrTokenizer t = b.asTokenizer();
339 
340         final String[] tokens1 = t.getTokenArray();
341         assertEquals(2, tokens1.length);
342         assertEquals("a", tokens1[0]);
343         assertEquals("b", tokens1[1]);
344         assertEquals(2, t.size());
345 
346         b.append("c d ");
347         final String[] tokens2 = t.getTokenArray();
348         assertEquals(2, tokens2.length);
349         assertEquals("a", tokens2[0]);
350         assertEquals("b", tokens2[1]);
351         assertEquals(2, t.size());
352         assertEquals("a", t.next());
353         assertEquals("b", t.next());
354 
355         t.reset();
356         final String[] tokens3 = t.getTokenArray();
357         assertEquals(4, tokens3.length);
358         assertEquals("a", tokens3[0]);
359         assertEquals("b", tokens3[1]);
360         assertEquals("c", tokens3[2]);
361         assertEquals("d", tokens3[3]);
362         assertEquals(4, t.size());
363         assertEquals("a", t.next());
364         assertEquals("b", t.next());
365         assertEquals("c", t.next());
366         assertEquals("d", t.next());
367 
368         assertEquals("a b c d ", t.getContent());
369     }
370 
371     @Test
372     void testAsWriter() throws Exception {
373         final StrBuilder sb = new StrBuilder("base");
374         try (Writer writer = sb.asWriter()) {
375 
376             writer.write('l');
377             assertEquals("basel", sb.toString());
378 
379             writer.write(new char[] { 'i', 'n' });
380             assertEquals("baselin", sb.toString());
381 
382             writer.write(new char[] { 'n', 'e', 'r' }, 1, 2);
383             assertEquals("baseliner", sb.toString());
384 
385             writer.write(" rout");
386             assertEquals("baseliner rout", sb.toString());
387 
388             writer.write("ping that server", 1, 3);
389             assertEquals("baseliner routing", sb.toString());
390 
391             writer.flush(); // no effect
392             assertEquals("baseliner routing", sb.toString());
393 
394             writer.close(); // no effect
395             assertEquals("baseliner routing", sb.toString());
396 
397             writer.write(" hi"); // works after close
398             assertEquals("baseliner routing hi", sb.toString());
399 
400             sb.setLength(4); // mix and match
401             writer.write('d');
402             assertEquals("based", sb.toString());
403         }
404     }
405 
406     @Test
407     void testCapacity() {
408         final StrBuilder sb = new StrBuilder();
409         assertEquals(sb.buffer.length, sb.capacity());
410 
411         sb.append("HelloWorldHelloWorldHelloWorldHelloWorld");
412         assertEquals(sb.buffer.length, sb.capacity());
413     }
414 
415     @Test
416     void testCapacityAndLength() {
417         final StrBuilder sb = new StrBuilder();
418         assertEquals(32, sb.capacity());
419         assertEquals(0, sb.length());
420         assertEquals(0, sb.size());
421         assertTrue(sb.isEmpty());
422 
423         sb.minimizeCapacity();
424         assertEquals(0, sb.capacity());
425         assertEquals(0, sb.length());
426         assertEquals(0, sb.size());
427         assertTrue(sb.isEmpty());
428 
429         sb.ensureCapacity(32);
430         assertTrue(sb.capacity() >= 32);
431         assertEquals(0, sb.length());
432         assertEquals(0, sb.size());
433         assertTrue(sb.isEmpty());
434 
435         sb.append("foo");
436         assertTrue(sb.capacity() >= 32);
437         assertEquals(3, sb.length());
438         assertEquals(3, sb.size());
439         assertFalse(sb.isEmpty());
440 
441         sb.clear();
442         assertTrue(sb.capacity() >= 32);
443         assertEquals(0, sb.length());
444         assertEquals(0, sb.size());
445         assertTrue(sb.isEmpty());
446 
447         sb.append("123456789012345678901234567890123");
448         assertTrue(sb.capacity() > 32);
449         assertEquals(33, sb.length());
450         assertEquals(33, sb.size());
451         assertFalse(sb.isEmpty());
452 
453         sb.ensureCapacity(16);
454         assertTrue(sb.capacity() > 16);
455         assertEquals(33, sb.length());
456         assertEquals(33, sb.size());
457         assertFalse(sb.isEmpty());
458 
459         sb.minimizeCapacity();
460         assertEquals(33, sb.capacity());
461         assertEquals(33, sb.length());
462         assertEquals(33, sb.size());
463         assertFalse(sb.isEmpty());
464 
465         assertThrows(IndexOutOfBoundsException.class, () -> sb.setLength(-1));
466 
467         sb.setLength(33);
468         assertEquals(33, sb.capacity());
469         assertEquals(33, sb.length());
470         assertEquals(33, sb.size());
471         assertFalse(sb.isEmpty());
472 
473         sb.setLength(16);
474         assertTrue(sb.capacity() >= 16);
475         assertEquals(16, sb.length());
476         assertEquals(16, sb.size());
477         assertEquals("1234567890123456", sb.toString());
478         assertFalse(sb.isEmpty());
479 
480         sb.setLength(32);
481         assertTrue(sb.capacity() >= 32);
482         assertEquals(32, sb.length());
483         assertEquals(32, sb.size());
484         assertEquals("1234567890123456\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sb.toString());
485         assertFalse(sb.isEmpty());
486 
487         sb.setLength(0);
488         assertTrue(sb.capacity() >= 32);
489         assertEquals(0, sb.length());
490         assertEquals(0, sb.size());
491         assertTrue(sb.isEmpty());
492     }
493 
494     @Test
495     void testChaining() {
496         final StrBuilder sb = new StrBuilder();
497         assertSame(sb, sb.setNewLineText(null));
498         assertSame(sb, sb.setNullText(null));
499         assertSame(sb, sb.setLength(1));
500         assertSame(sb, sb.setCharAt(0, 'a'));
501         assertSame(sb, sb.ensureCapacity(0));
502         assertSame(sb, sb.minimizeCapacity());
503         assertSame(sb, sb.clear());
504         assertSame(sb, sb.reverse());
505         assertSame(sb, sb.trim());
506     }
507 
508     @Test
509     void testCharAt() {
510         final StrBuilder sb = new StrBuilder();
511         assertThrows(IndexOutOfBoundsException.class, () -> sb.charAt(0));
512         assertThrows(IndexOutOfBoundsException.class, () -> sb.charAt(-1));
513         sb.append("foo");
514         assertEquals('f', sb.charAt(0));
515         assertEquals('o', sb.charAt(1));
516         assertEquals('o', sb.charAt(2));
517         assertThrows(IndexOutOfBoundsException.class, () -> sb.charAt(-1));
518         assertThrows(IndexOutOfBoundsException.class, () -> sb.charAt(3));
519     }
520 
521     @Test
522     void testClear() {
523         final StrBuilder sb = new StrBuilder();
524         sb.append("Hello");
525         sb.clear();
526         assertEquals(0, sb.length());
527         assertTrue(sb.buffer.length >= 5);
528     }
529 
530     @Test
531     void testConstructors() {
532         final StrBuilder sb0 = new StrBuilder();
533         assertEquals(32, sb0.capacity());
534         assertEquals(0, sb0.length());
535         assertEquals(0, sb0.size());
536 
537         final StrBuilder sb1 = new StrBuilder(32);
538         assertEquals(32, sb1.capacity());
539         assertEquals(0, sb1.length());
540         assertEquals(0, sb1.size());
541 
542         final StrBuilder sb2 = new StrBuilder(0);
543         assertEquals(32, sb2.capacity());
544         assertEquals(0, sb2.length());
545         assertEquals(0, sb2.size());
546 
547         final StrBuilder sb3 = new StrBuilder(-1);
548         assertEquals(32, sb3.capacity());
549         assertEquals(0, sb3.length());
550         assertEquals(0, sb3.size());
551 
552         final StrBuilder sb4 = new StrBuilder(1);
553         assertEquals(1, sb4.capacity());
554         assertEquals(0, sb4.length());
555         assertEquals(0, sb4.size());
556 
557         final StrBuilder sb5 = new StrBuilder((String) null);
558         assertEquals(32, sb5.capacity());
559         assertEquals(0, sb5.length());
560         assertEquals(0, sb5.size());
561 
562         final StrBuilder sb6 = new StrBuilder("");
563         assertEquals(32, sb6.capacity());
564         assertEquals(0, sb6.length());
565         assertEquals(0, sb6.size());
566 
567         final StrBuilder sb7 = new StrBuilder("foo");
568         assertEquals(35, sb7.capacity());
569         assertEquals(3, sb7.length());
570         assertEquals(3, sb7.size());
571     }
572 
573     @Test
574     void testContains_char() {
575         final StrBuilder sb = new StrBuilder("abcdefghijklmnopqrstuvwxyz");
576         assertTrue(sb.contains('a'));
577         assertTrue(sb.contains('o'));
578         assertTrue(sb.contains('z'));
579         assertFalse(sb.contains('1'));
580     }
581 
582     @Test
583     void testContains_String() {
584         final StrBuilder sb = new StrBuilder("abcdefghijklmnopqrstuvwxyz");
585         assertTrue(sb.contains("a"));
586         assertTrue(sb.contains("pq"));
587         assertTrue(sb.contains("z"));
588         assertFalse(sb.contains("zyx"));
589         assertFalse(sb.contains((String) null));
590     }
591 
592     @Test
593     void testContains_StrMatcher() {
594         StrBuilder sb = new StrBuilder("abcdefghijklmnopqrstuvwxyz");
595         assertTrue(sb.contains(StrMatcher.charMatcher('a')));
596         assertTrue(sb.contains(StrMatcher.stringMatcher("pq")));
597         assertTrue(sb.contains(StrMatcher.charMatcher('z')));
598         assertFalse(sb.contains(StrMatcher.stringMatcher("zy")));
599         assertFalse(sb.contains((StrMatcher) null));
600 
601         sb = new StrBuilder();
602         assertFalse(sb.contains(A_NUMBER_MATCHER));
603         sb.append("B A1 C");
604         assertTrue(sb.contains(A_NUMBER_MATCHER));
605     }
606 
607     @Test
608     void testDeleteAll_char() {
609         StrBuilder sb = new StrBuilder("abcbccba");
610         sb.deleteAll('X');
611         assertEquals("abcbccba", sb.toString());
612         sb.deleteAll('a');
613         assertEquals("bcbccb", sb.toString());
614         sb.deleteAll('c');
615         assertEquals("bbb", sb.toString());
616         sb.deleteAll('b');
617         assertEquals("", sb.toString());
618 
619         sb = new StrBuilder("");
620         sb.deleteAll('b');
621         assertEquals("", sb.toString());
622     }
623 
624     @Test
625     void testDeleteAll_String() {
626         StrBuilder sb = new StrBuilder("abcbccba");
627         sb.deleteAll((String) null);
628         assertEquals("abcbccba", sb.toString());
629         sb.deleteAll("");
630         assertEquals("abcbccba", sb.toString());
631 
632         sb.deleteAll("X");
633         assertEquals("abcbccba", sb.toString());
634         sb.deleteAll("a");
635         assertEquals("bcbccb", sb.toString());
636         sb.deleteAll("c");
637         assertEquals("bbb", sb.toString());
638         sb.deleteAll("b");
639         assertEquals("", sb.toString());
640 
641         sb = new StrBuilder("abcbccba");
642         sb.deleteAll("bc");
643         assertEquals("acba", sb.toString());
644 
645         sb = new StrBuilder("");
646         sb.deleteAll("bc");
647         assertEquals("", sb.toString());
648     }
649 
650     @Test
651     void testDeleteAll_StrMatcher() {
652         StrBuilder sb = new StrBuilder("A0xA1A2yA3");
653         sb.deleteAll((StrMatcher) null);
654         assertEquals("A0xA1A2yA3", sb.toString());
655         sb.deleteAll(A_NUMBER_MATCHER);
656         assertEquals("xy", sb.toString());
657 
658         sb = new StrBuilder("Ax1");
659         sb.deleteAll(A_NUMBER_MATCHER);
660         assertEquals("Ax1", sb.toString());
661 
662         sb = new StrBuilder("");
663         sb.deleteAll(A_NUMBER_MATCHER);
664         assertEquals("", sb.toString());
665     }
666 
667     @Test
668     void testDeleteCharAt() {
669         final StrBuilder sb = new StrBuilder("abc");
670         sb.deleteCharAt(0);
671         assertEquals("bc", sb.toString());
672 
673         assertThrows(IndexOutOfBoundsException.class, () -> sb.deleteCharAt(1000));
674     }
675 
676     @Test
677     void testDeleteCharAtWithNegative() {
678         assertThrows(StringIndexOutOfBoundsException.class, () -> new StrBuilder().deleteCharAt(-1258));
679     }
680 
681     @Test
682     void testDeleteFirst_char() {
683         StrBuilder sb = new StrBuilder("abcba");
684         sb.deleteFirst('X');
685         assertEquals("abcba", sb.toString());
686         sb.deleteFirst('a');
687         assertEquals("bcba", sb.toString());
688         sb.deleteFirst('c');
689         assertEquals("bba", sb.toString());
690         sb.deleteFirst('b');
691         assertEquals("ba", sb.toString());
692 
693         sb = new StrBuilder("");
694         sb.deleteFirst('b');
695         assertEquals("", sb.toString());
696     }
697 
698     @Test
699     void testDeleteFirst_String() {
700         StrBuilder sb = new StrBuilder("abcbccba");
701         sb.deleteFirst((String) null);
702         assertEquals("abcbccba", sb.toString());
703         sb.deleteFirst("");
704         assertEquals("abcbccba", sb.toString());
705 
706         sb.deleteFirst("X");
707         assertEquals("abcbccba", sb.toString());
708         sb.deleteFirst("a");
709         assertEquals("bcbccba", sb.toString());
710         sb.deleteFirst("c");
711         assertEquals("bbccba", sb.toString());
712         sb.deleteFirst("b");
713         assertEquals("bccba", sb.toString());
714 
715         sb = new StrBuilder("abcbccba");
716         sb.deleteFirst("bc");
717         assertEquals("abccba", sb.toString());
718 
719         sb = new StrBuilder("");
720         sb.deleteFirst("bc");
721         assertEquals("", sb.toString());
722     }
723 
724     @Test
725     void testDeleteFirst_StrMatcher() {
726         StrBuilder sb = new StrBuilder("A0xA1A2yA3");
727         sb.deleteFirst((StrMatcher) null);
728         assertEquals("A0xA1A2yA3", sb.toString());
729         sb.deleteFirst(A_NUMBER_MATCHER);
730         assertEquals("xA1A2yA3", sb.toString());
731 
732         sb = new StrBuilder("Ax1");
733         sb.deleteFirst(A_NUMBER_MATCHER);
734         assertEquals("Ax1", sb.toString());
735 
736         sb = new StrBuilder("");
737         sb.deleteFirst(A_NUMBER_MATCHER);
738         assertEquals("", sb.toString());
739     }
740 
741     @Test
742     void testDeleteIntInt() {
743         final StrBuilder sb = new StrBuilder("abc");
744         sb.delete(0, 1);
745         assertEquals("bc", sb.toString());
746         sb.delete(1, 2);
747         assertEquals("b", sb.toString());
748         sb.delete(0, 1);
749         assertEquals("", sb.toString());
750         sb.delete(0, 1000);
751         assertEquals("", sb.toString());
752 
753         assertThrows(IndexOutOfBoundsException.class, () -> sb.delete(1, 2));
754         assertThrows(IndexOutOfBoundsException.class, () -> sb.delete(-1, 1));
755 
756         assertThrows(IndexOutOfBoundsException.class, () -> new StrBuilder("anything").delete(2, 1));
757     }
758 
759     @Test
760     void testEndsWith() {
761         final StrBuilder sb = new StrBuilder();
762         assertFalse(sb.endsWith("a"));
763         assertFalse(sb.endsWith("c"));
764         assertTrue(sb.endsWith(""));
765         assertFalse(sb.endsWith(null));
766         sb.append("abc");
767         assertTrue(sb.endsWith("c"));
768         assertTrue(sb.endsWith("bc"));
769         assertTrue(sb.endsWith("abc"));
770         assertFalse(sb.endsWith("cba"));
771         assertFalse(sb.endsWith("abcd"));
772         assertFalse(sb.endsWith(" abc"));
773         assertFalse(sb.endsWith("abc "));
774     }
775 
776     @Test
777     void testEnsureCapacity() {
778         final StrBuilder sb = new StrBuilder();
779         sb.ensureCapacity(2);
780         assertTrue(sb.capacity() >= 2);
781 
782         sb.ensureCapacity(-1);
783         assertTrue(sb.capacity() >= 0);
784 
785         sb.append("HelloWorld");
786         sb.ensureCapacity(40);
787         assertTrue(sb.capacity() >= 40);
788     }
789 
790     @Test
791     void testEquals() {
792         final StrBuilder sb1 = new StrBuilder();
793         final StrBuilder sb2 = new StrBuilder();
794         assertEquals(sb1, sb2);
795         assertEquals(sb1, sb1);
796         assertEquals(sb2, sb2);
797         assertEquals(sb1, (Object) sb2);
798 
799         sb1.append("abc");
800         assertNotEquals(sb1, sb2);
801         assertNotEquals(sb1, (Object) sb2);
802 
803         sb2.append("ABC");
804         assertNotEquals(sb1, sb2);
805         assertNotEquals(sb1, (Object) sb2);
806 
807         sb2.clear().append("abc");
808         assertEquals(sb1, sb2);
809         assertEquals(sb1, (Object) sb2);
810 
811         assertNotEquals(sb1, Integer.valueOf(1));
812         assertNotEquals("abc", sb1);
813     }
814 
815     @Test
816     void testEqualsIgnoreCase() {
817         final StrBuilder sb1 = new StrBuilder();
818         final StrBuilder sb2 = new StrBuilder();
819         assertTrue(sb1.equalsIgnoreCase(sb1));
820         assertTrue(sb1.equalsIgnoreCase(sb2));
821         assertTrue(sb2.equalsIgnoreCase(sb2));
822 
823         sb1.append("abc");
824         assertFalse(sb1.equalsIgnoreCase(sb2));
825 
826         sb2.append("ABC");
827         assertTrue(sb1.equalsIgnoreCase(sb2));
828 
829         sb2.clear().append("abc");
830         assertTrue(sb1.equalsIgnoreCase(sb2));
831         assertTrue(sb1.equalsIgnoreCase(sb1));
832         assertTrue(sb2.equalsIgnoreCase(sb2));
833 
834         sb2.clear().append("aBc");
835         assertTrue(sb1.equalsIgnoreCase(sb2));
836     }
837 
838     @Test
839     void testErrorMessageShowsCorrectVariable() {
840         final StrBuilder sb = new StrBuilder("Hello");
841         final char[] chars = { 'a', 'b', 'c' };
842         StringIndexOutOfBoundsException ex = assertThrows(StringIndexOutOfBoundsException.class, () -> sb.append(chars, 1, 4));
843         assertTrue(ex.getMessage().contains("length: 4"));
844         ex = assertThrows(StringIndexOutOfBoundsException.class, () -> sb.append(chars, 7, 3));
845         assertTrue(ex.getMessage().contains("startIndex: 7"));
846     }
847 
848     @Test
849     void testGetChars() {
850         final StrBuilder sb = new StrBuilder();
851 
852         char[] input = new char[10];
853         char[] a = sb.getChars(input);
854         assertSame(input, a);
855         assertArrayEquals(new char[10], a);
856 
857         sb.append("junit");
858         a = sb.getChars(input);
859         assertSame(input, a);
860         assertArrayEquals(new char[] { 'j', 'u', 'n', 'i', 't', 0, 0, 0, 0, 0 }, a);
861 
862         a = sb.getChars(null);
863         assertNotSame(input, a);
864         assertEquals(5, a.length);
865         assertArrayEquals("junit".toCharArray(), a);
866 
867         input = new char[5];
868         a = sb.getChars(input);
869         assertSame(input, a);
870 
871         input = new char[4];
872         a = sb.getChars(input);
873         assertNotSame(input, a);
874     }
875 
876     @Test
877     void testGetCharsIntIntCharArrayInt() {
878         final StrBuilder sb = new StrBuilder();
879 
880         sb.append("junit");
881         char[] a = new char[5];
882         sb.getChars(0, 5, a, 0);
883         assertArrayEquals(new char[] { 'j', 'u', 'n', 'i', 't' }, a);
884 
885         a = new char[5];
886         sb.getChars(0, 2, a, 3);
887         assertArrayEquals(new char[] { 0, 0, 0, 'j', 'u' }, a);
888 
889         try {
890             sb.getChars(-1, 0, a, 0);
891             fail("no exception");
892         } catch (final IndexOutOfBoundsException e) {
893             // expected
894         }
895 
896         try {
897             sb.getChars(0, -1, a, 0);
898             fail("no exception");
899         } catch (final IndexOutOfBoundsException e) {
900             // expected
901         }
902 
903         try {
904             sb.getChars(0, 20, a, 0);
905             fail("no exception");
906         } catch (final IndexOutOfBoundsException e) {
907             // expected
908         }
909 
910         try {
911             sb.getChars(4, 2, a, 0);
912             fail("no exception");
913         } catch (final IndexOutOfBoundsException e) {
914             // expected
915         }
916     }
917 
918     @Test
919     void testGetSetNewLineText() {
920         final StrBuilder sb = new StrBuilder();
921         assertNull(sb.getNewLineText());
922 
923         sb.setNewLineText("#");
924         assertEquals("#", sb.getNewLineText());
925 
926         sb.setNewLineText("");
927         assertEquals("", sb.getNewLineText());
928 
929         sb.setNewLineText((String) null);
930         assertNull(sb.getNewLineText());
931     }
932 
933     @Test
934     void testGetSetNullText() {
935         final StrBuilder sb = new StrBuilder();
936         assertNull(sb.getNullText());
937 
938         sb.setNullText("null");
939         assertEquals("null", sb.getNullText());
940 
941         sb.setNullText("");
942         assertNull(sb.getNullText());
943 
944         sb.setNullText("NULL");
945         assertEquals("NULL", sb.getNullText());
946 
947         sb.setNullText((String) null);
948         assertNull(sb.getNullText());
949     }
950 
951     @Test
952     void testHashCode() {
953         final StrBuilder sb = new StrBuilder();
954         final int hc1a = sb.hashCode();
955         final int hc1b = sb.hashCode();
956         assertEquals(0, hc1a);
957         assertEquals(hc1a, hc1b);
958 
959         sb.append("abc");
960         final int hc2a = sb.hashCode();
961         final int hc2b = sb.hashCode();
962         assertTrue(hc2a != 0);
963         assertEquals(hc2a, hc2b);
964     }
965 
966     @Test
967     void testIndexOf_char() {
968         final StrBuilder sb = new StrBuilder("abab");
969         assertEquals(0, sb.indexOf('a'));
970 
971         // should work like String#indexOf
972         assertEquals("abab".indexOf('a'), sb.indexOf('a'));
973 
974         assertEquals(1, sb.indexOf('b'));
975         assertEquals("abab".indexOf('b'), sb.indexOf('b'));
976 
977         assertEquals(-1, sb.indexOf('z'));
978     }
979 
980     @Test
981     void testIndexOf_char_int() {
982         StrBuilder sb = new StrBuilder("abab");
983         assertEquals(0, sb.indexOf('a', -1));
984         assertEquals(0, sb.indexOf('a', 0));
985         assertEquals(2, sb.indexOf('a', 1));
986         assertEquals(-1, sb.indexOf('a', 4));
987         assertEquals(-1, sb.indexOf('a', 5));
988 
989         // should work like String#indexOf
990         assertEquals("abab".indexOf('a', 1), sb.indexOf('a', 1));
991 
992         assertEquals(3, sb.indexOf('b', 2));
993         assertEquals("abab".indexOf('b', 2), sb.indexOf('b', 2));
994 
995         assertEquals(-1, sb.indexOf('z', 2));
996 
997         sb = new StrBuilder("xyzabc");
998         assertEquals(2, sb.indexOf('z', 0));
999         assertEquals(-1, sb.indexOf('z', 3));
1000     }
1001 
1002     @Test
1003     void testIndexOf_String() {
1004         final StrBuilder sb = new StrBuilder("abab");
1005 
1006         assertEquals(0, sb.indexOf("a"));
1007         // should work like String#indexOf
1008         assertEquals("abab".indexOf("a"), sb.indexOf("a"));
1009 
1010         assertEquals(0, sb.indexOf("ab"));
1011         // should work like String#indexOf
1012         assertEquals("abab".indexOf("ab"), sb.indexOf("ab"));
1013 
1014         assertEquals(1, sb.indexOf("b"));
1015         assertEquals("abab".indexOf("b"), sb.indexOf("b"));
1016 
1017         assertEquals(1, sb.indexOf("ba"));
1018         assertEquals("abab".indexOf("ba"), sb.indexOf("ba"));
1019 
1020         assertEquals(-1, sb.indexOf("z"));
1021 
1022         assertEquals(-1, sb.indexOf((String) null));
1023     }
1024 
1025     @Test
1026     void testIndexOf_String_int() {
1027         StrBuilder sb = new StrBuilder("abab");
1028         assertEquals(0, sb.indexOf("a", -1));
1029         assertEquals(0, sb.indexOf("a", 0));
1030         assertEquals(2, sb.indexOf("a", 1));
1031         assertEquals(2, sb.indexOf("a", 2));
1032         assertEquals(-1, sb.indexOf("a", 3));
1033         assertEquals(-1, sb.indexOf("a", 4));
1034         assertEquals(-1, sb.indexOf("a", 5));
1035 
1036         assertEquals(-1, sb.indexOf("abcdef", 0));
1037         assertEquals(0, sb.indexOf("", 0));
1038         assertEquals(1, sb.indexOf("", 1));
1039 
1040         // should work like String#indexOf
1041         assertEquals("abab".indexOf("a", 1), sb.indexOf("a", 1));
1042 
1043         assertEquals(2, sb.indexOf("ab", 1));
1044         // should work like String#indexOf
1045         assertEquals("abab".indexOf("ab", 1), sb.indexOf("ab", 1));
1046 
1047         assertEquals(3, sb.indexOf("b", 2));
1048         assertEquals("abab".indexOf("b", 2), sb.indexOf("b", 2));
1049 
1050         assertEquals(1, sb.indexOf("ba", 1));
1051         assertEquals("abab".indexOf("ba", 2), sb.indexOf("ba", 2));
1052 
1053         assertEquals(-1, sb.indexOf("z", 2));
1054 
1055         sb = new StrBuilder("xyzabc");
1056         assertEquals(2, sb.indexOf("za", 0));
1057         assertEquals(-1, sb.indexOf("za", 3));
1058 
1059         assertEquals(-1, sb.indexOf((String) null, 2));
1060     }
1061 
1062     @Test
1063     void testIndexOf_StrMatcher() {
1064         final StrBuilder sb = new StrBuilder();
1065         assertEquals(-1, sb.indexOf((StrMatcher) null));
1066         assertEquals(-1, sb.indexOf(StrMatcher.charMatcher('a')));
1067 
1068         sb.append("ab bd");
1069         assertEquals(0, sb.indexOf(StrMatcher.charMatcher('a')));
1070         assertEquals(1, sb.indexOf(StrMatcher.charMatcher('b')));
1071         assertEquals(2, sb.indexOf(StrMatcher.spaceMatcher()));
1072         assertEquals(4, sb.indexOf(StrMatcher.charMatcher('d')));
1073         assertEquals(-1, sb.indexOf(StrMatcher.noneMatcher()));
1074         assertEquals(-1, sb.indexOf((StrMatcher) null));
1075 
1076         sb.append(" A1 junction");
1077         assertEquals(6, sb.indexOf(A_NUMBER_MATCHER));
1078     }
1079 
1080     @Test
1081     void testIndexOf_StrMatcher_int() {
1082         final StrBuilder sb = new StrBuilder();
1083         assertEquals(-1, sb.indexOf((StrMatcher) null, 2));
1084         assertEquals(-1, sb.indexOf(StrMatcher.charMatcher('a'), 2));
1085         assertEquals(-1, sb.indexOf(StrMatcher.charMatcher('a'), 0));
1086 
1087         sb.append("ab bd");
1088         assertEquals(0, sb.indexOf(StrMatcher.charMatcher('a'), -2));
1089         assertEquals(0, sb.indexOf(StrMatcher.charMatcher('a'), 0));
1090         assertEquals(-1, sb.indexOf(StrMatcher.charMatcher('a'), 2));
1091         assertEquals(-1, sb.indexOf(StrMatcher.charMatcher('a'), 20));
1092 
1093         assertEquals(1, sb.indexOf(StrMatcher.charMatcher('b'), -1));
1094         assertEquals(1, sb.indexOf(StrMatcher.charMatcher('b'), 0));
1095         assertEquals(1, sb.indexOf(StrMatcher.charMatcher('b'), 1));
1096         assertEquals(3, sb.indexOf(StrMatcher.charMatcher('b'), 2));
1097         assertEquals(3, sb.indexOf(StrMatcher.charMatcher('b'), 3));
1098         assertEquals(-1, sb.indexOf(StrMatcher.charMatcher('b'), 4));
1099         assertEquals(-1, sb.indexOf(StrMatcher.charMatcher('b'), 5));
1100         assertEquals(-1, sb.indexOf(StrMatcher.charMatcher('b'), 6));
1101 
1102         assertEquals(2, sb.indexOf(StrMatcher.spaceMatcher(), -2));
1103         assertEquals(2, sb.indexOf(StrMatcher.spaceMatcher(), 0));
1104         assertEquals(2, sb.indexOf(StrMatcher.spaceMatcher(), 2));
1105         assertEquals(-1, sb.indexOf(StrMatcher.spaceMatcher(), 4));
1106         assertEquals(-1, sb.indexOf(StrMatcher.spaceMatcher(), 20));
1107 
1108         assertEquals(-1, sb.indexOf(StrMatcher.noneMatcher(), 0));
1109         assertEquals(-1, sb.indexOf((StrMatcher) null, 0));
1110 
1111         sb.append(" A1 junction with A2");
1112         assertEquals(6, sb.indexOf(A_NUMBER_MATCHER, 5));
1113         assertEquals(6, sb.indexOf(A_NUMBER_MATCHER, 6));
1114         assertEquals(23, sb.indexOf(A_NUMBER_MATCHER, 7));
1115         assertEquals(23, sb.indexOf(A_NUMBER_MATCHER, 22));
1116         assertEquals(23, sb.indexOf(A_NUMBER_MATCHER, 23));
1117         assertEquals(-1, sb.indexOf(A_NUMBER_MATCHER, 24));
1118     }
1119 
1120     @Test
1121     void testIndexOfLang294() {
1122         final StrBuilder sb = new StrBuilder("onetwothree");
1123         sb.deleteFirst("three");
1124         assertEquals(-1, sb.indexOf("three"));
1125     }
1126 
1127     @Test
1128     void testIsEmpty() {
1129         final StrBuilder sb = new StrBuilder();
1130         assertTrue(sb.isEmpty());
1131 
1132         sb.append("Hello");
1133         assertFalse(sb.isEmpty());
1134 
1135         sb.clear();
1136         assertTrue(sb.isEmpty());
1137     }
1138 
1139     @Test
1140     void testLang294() {
1141         final StrBuilder sb = new StrBuilder("\n%BLAH%\nDo more stuff\neven more stuff\n%BLAH%\n");
1142         sb.deleteAll("\n%BLAH%");
1143         assertEquals("\nDo more stuff\neven more stuff\n", sb.toString());
1144     }
1145 
1146     @Test
1147     void testLang295() {
1148         final StrBuilder sb = new StrBuilder("onetwothree");
1149         sb.deleteFirst("three");
1150         assertFalse(sb.contains('h'), "The contains(char) method is looking beyond the end of the string");
1151         assertEquals(-1, sb.indexOf('h'), "The indexOf(char) method is looking beyond the end of the string");
1152     }
1153 
1154     @Test
1155     void testLang412Left() {
1156         final StrBuilder sb = new StrBuilder();
1157         sb.appendFixedWidthPadLeft(null, 10, '*');
1158         assertEquals("**********", sb.toString(), "Failed to invoke appendFixedWidthPadLeft correctly");
1159     }
1160 
1161     @Test
1162     void testLang412Right() {
1163         final StrBuilder sb = new StrBuilder();
1164         sb.appendFixedWidthPadRight(null, 10, '*');
1165         assertEquals("**********", sb.toString(), "Failed to invoke appendFixedWidthPadRight correctly");
1166     }
1167 
1168     @Test
1169     void testLastIndexOf_char() {
1170         final StrBuilder sb = new StrBuilder("abab");
1171 
1172         assertEquals(2, sb.lastIndexOf('a'));
1173         // should work like String#lastIndexOf
1174         assertEquals("abab".lastIndexOf('a'), sb.lastIndexOf('a'));
1175 
1176         assertEquals(3, sb.lastIndexOf('b'));
1177         assertEquals("abab".lastIndexOf('b'), sb.lastIndexOf('b'));
1178 
1179         assertEquals(-1, sb.lastIndexOf('z'));
1180     }
1181 
1182     @Test
1183     void testLastIndexOf_char_int() {
1184         StrBuilder sb = new StrBuilder("abab");
1185         assertEquals(-1, sb.lastIndexOf('a', -1));
1186         assertEquals(0, sb.lastIndexOf('a', 0));
1187         assertEquals(0, sb.lastIndexOf('a', 1));
1188 
1189         // should work like String#lastIndexOf
1190         assertEquals("abab".lastIndexOf('a', 1), sb.lastIndexOf('a', 1));
1191 
1192         assertEquals(1, sb.lastIndexOf('b', 2));
1193         assertEquals("abab".lastIndexOf('b', 2), sb.lastIndexOf('b', 2));
1194 
1195         assertEquals(-1, sb.lastIndexOf('z', 2));
1196 
1197         sb = new StrBuilder("xyzabc");
1198         assertEquals(2, sb.lastIndexOf('z', sb.length()));
1199         assertEquals(-1, sb.lastIndexOf('z', 1));
1200     }
1201 
1202     @Test
1203     void testLastIndexOf_String() {
1204         final StrBuilder sb = new StrBuilder("abab");
1205 
1206         assertEquals(2, sb.lastIndexOf("a"));
1207         // should work like String#lastIndexOf
1208         assertEquals("abab".lastIndexOf("a"), sb.lastIndexOf("a"));
1209 
1210         assertEquals(2, sb.lastIndexOf("ab"));
1211         // should work like String#lastIndexOf
1212         assertEquals("abab".lastIndexOf("ab"), sb.lastIndexOf("ab"));
1213 
1214         assertEquals(3, sb.lastIndexOf("b"));
1215         assertEquals("abab".lastIndexOf("b"), sb.lastIndexOf("b"));
1216 
1217         assertEquals(1, sb.lastIndexOf("ba"));
1218         assertEquals("abab".lastIndexOf("ba"), sb.lastIndexOf("ba"));
1219 
1220         assertEquals(-1, sb.lastIndexOf("z"));
1221 
1222         assertEquals(-1, sb.lastIndexOf((String) null));
1223 
1224         assertEquals(4, sb.lastIndexOf(""));
1225         assertEquals("".lastIndexOf(""), new StringBuilder().lastIndexOf(""));
1226     }
1227 
1228     @Test
1229     void testLastIndexOf_String_int() {
1230         StrBuilder sb = new StrBuilder("abab");
1231         assertEquals(-1, sb.lastIndexOf("a", -1));
1232         assertEquals(0, sb.lastIndexOf("a", 0));
1233         assertEquals(0, sb.lastIndexOf("a", 1));
1234         assertEquals(2, sb.lastIndexOf("a", 2));
1235         assertEquals(2, sb.lastIndexOf("a", 3));
1236         assertEquals(2, sb.lastIndexOf("a", 4));
1237         assertEquals(2, sb.lastIndexOf("a", 5));
1238 
1239         assertEquals(-1, sb.lastIndexOf("abcdef", 3));
1240         assertEquals("abab".lastIndexOf("", 3), sb.lastIndexOf("", 3));
1241         assertEquals("abab".lastIndexOf("", 1), sb.lastIndexOf("", 1));
1242 
1243         // should work like String#lastIndexOf
1244         assertEquals("abab".lastIndexOf("a", 1), sb.lastIndexOf("a", 1));
1245 
1246         assertEquals(0, sb.lastIndexOf("ab", 1));
1247         // should work like String#lastIndexOf
1248         assertEquals("abab".lastIndexOf("ab", 1), sb.lastIndexOf("ab", 1));
1249 
1250         assertEquals(1, sb.lastIndexOf("b", 2));
1251         assertEquals("abab".lastIndexOf("b", 2), sb.lastIndexOf("b", 2));
1252 
1253         assertEquals(1, sb.lastIndexOf("ba", 2));
1254         assertEquals("abab".lastIndexOf("ba", 2), sb.lastIndexOf("ba", 2));
1255 
1256         assertEquals(-1, sb.lastIndexOf("z", 2));
1257 
1258         sb = new StrBuilder("xyzabc");
1259         assertEquals(2, sb.lastIndexOf("za", sb.length()));
1260         assertEquals(-1, sb.lastIndexOf("za", 1));
1261 
1262         assertEquals(-1, sb.lastIndexOf((String) null, 2));
1263     }
1264 
1265     @Test
1266     void testLastIndexOf_StrMatcher() {
1267         final StrBuilder sb = new StrBuilder();
1268         assertEquals(-1, sb.lastIndexOf((StrMatcher) null));
1269         assertEquals(-1, sb.lastIndexOf(StrMatcher.charMatcher('a')));
1270 
1271         sb.append("ab bd");
1272         assertEquals(0, sb.lastIndexOf(StrMatcher.charMatcher('a')));
1273         assertEquals(3, sb.lastIndexOf(StrMatcher.charMatcher('b')));
1274         assertEquals(2, sb.lastIndexOf(StrMatcher.spaceMatcher()));
1275         assertEquals(4, sb.lastIndexOf(StrMatcher.charMatcher('d')));
1276         assertEquals(-1, sb.lastIndexOf(StrMatcher.noneMatcher()));
1277         assertEquals(-1, sb.lastIndexOf((StrMatcher) null));
1278 
1279         sb.append(" A1 junction");
1280         assertEquals(6, sb.lastIndexOf(A_NUMBER_MATCHER));
1281     }
1282 
1283     @Test
1284     void testLastIndexOf_StrMatcher_int() {
1285         final StrBuilder sb = new StrBuilder();
1286         assertEquals(-1, sb.lastIndexOf((StrMatcher) null, 2));
1287         assertEquals(-1, sb.lastIndexOf(StrMatcher.charMatcher('a'), 2));
1288         assertEquals(-1, sb.lastIndexOf(StrMatcher.charMatcher('a'), 0));
1289         assertEquals(-1, sb.lastIndexOf(StrMatcher.charMatcher('a'), -1));
1290 
1291         sb.append("ab bd");
1292         assertEquals(-1, sb.lastIndexOf(StrMatcher.charMatcher('a'), -2));
1293         assertEquals(0, sb.lastIndexOf(StrMatcher.charMatcher('a'), 0));
1294         assertEquals(0, sb.lastIndexOf(StrMatcher.charMatcher('a'), 2));
1295         assertEquals(0, sb.lastIndexOf(StrMatcher.charMatcher('a'), 20));
1296 
1297         assertEquals(-1, sb.lastIndexOf(StrMatcher.charMatcher('b'), -1));
1298         assertEquals(-1, sb.lastIndexOf(StrMatcher.charMatcher('b'), 0));
1299         assertEquals(1, sb.lastIndexOf(StrMatcher.charMatcher('b'), 1));
1300         assertEquals(1, sb.lastIndexOf(StrMatcher.charMatcher('b'), 2));
1301         assertEquals(3, sb.lastIndexOf(StrMatcher.charMatcher('b'), 3));
1302         assertEquals(3, sb.lastIndexOf(StrMatcher.charMatcher('b'), 4));
1303         assertEquals(3, sb.lastIndexOf(StrMatcher.charMatcher('b'), 5));
1304         assertEquals(3, sb.lastIndexOf(StrMatcher.charMatcher('b'), 6));
1305 
1306         assertEquals(-1, sb.lastIndexOf(StrMatcher.spaceMatcher(), -2));
1307         assertEquals(-1, sb.lastIndexOf(StrMatcher.spaceMatcher(), 0));
1308         assertEquals(2, sb.lastIndexOf(StrMatcher.spaceMatcher(), 2));
1309         assertEquals(2, sb.lastIndexOf(StrMatcher.spaceMatcher(), 4));
1310         assertEquals(2, sb.lastIndexOf(StrMatcher.spaceMatcher(), 20));
1311 
1312         assertEquals(-1, sb.lastIndexOf(StrMatcher.noneMatcher(), 0));
1313         assertEquals(-1, sb.lastIndexOf((StrMatcher) null, 0));
1314 
1315         sb.append(" A1 junction with A2");
1316         assertEquals(-1, sb.lastIndexOf(A_NUMBER_MATCHER, 5));
1317         assertEquals(-1, sb.lastIndexOf(A_NUMBER_MATCHER, 6)); // A matches, 1
1318                                                                // is outside
1319                                                                // bounds
1320         assertEquals(6, sb.lastIndexOf(A_NUMBER_MATCHER, 7));
1321         assertEquals(6, sb.lastIndexOf(A_NUMBER_MATCHER, 22));
1322         assertEquals(6, sb.lastIndexOf(A_NUMBER_MATCHER, 23)); // A matches, 2
1323                                                                // is outside
1324                                                                // bounds
1325         assertEquals(23, sb.lastIndexOf(A_NUMBER_MATCHER, 24));
1326     }
1327 
1328     @Test
1329     void testLeftString() {
1330         final StrBuilder sb = new StrBuilder("left right");
1331         assertEquals("left", sb.leftString(4));
1332         assertEquals("", sb.leftString(0));
1333         assertEquals("", sb.leftString(-5));
1334         assertEquals("left right", sb.leftString(15));
1335     }
1336 
1337     @Test
1338     void testLength() {
1339         final StrBuilder sb = new StrBuilder();
1340         assertEquals(0, sb.length());
1341 
1342         sb.append("Hello");
1343         assertEquals(5, sb.length());
1344     }
1345 
1346     @Test
1347     void testMidString() {
1348         final StrBuilder sb = new StrBuilder("hello goodbye hello");
1349         assertEquals("goodbye", sb.midString(6, 7));
1350         assertEquals("hello", sb.midString(0, 5));
1351         assertEquals("hello", sb.midString(-5, 5));
1352         assertEquals("", sb.midString(0, -1));
1353         assertEquals("", sb.midString(20, 2));
1354         assertEquals("hello", sb.midString(14, 22));
1355     }
1356 
1357     @Test
1358     void testMinimizeCapacity() {
1359         final StrBuilder sb = new StrBuilder();
1360         sb.minimizeCapacity();
1361         assertEquals(0, sb.capacity());
1362 
1363         sb.append("HelloWorld");
1364         sb.minimizeCapacity();
1365         assertEquals(10, sb.capacity());
1366     }
1367 
1368     @Test
1369     void testReadFromCharBuffer() throws Exception {
1370         String s = "";
1371         for (int i = 0; i < 100; ++i) {
1372             final StrBuilder sb = new StrBuilder();
1373             final int len = sb.readFrom(CharBuffer.wrap(s));
1374 
1375             assertEquals(s.length(), len);
1376             assertEquals(s, sb.toString());
1377 
1378             s += Integer.toString(i);
1379         }
1380     }
1381 
1382     @Test
1383     void testReadFromCharBufferAppendsToEnd() throws Exception {
1384         final StrBuilder sb = new StrBuilder("Test");
1385         sb.readFrom(CharBuffer.wrap(" 123"));
1386         assertEquals("Test 123", sb.toString());
1387     }
1388 
1389     @Test
1390     void testReadFromReadable() throws Exception {
1391         String s = "";
1392         for (int i = 0; i < 100; ++i) {
1393             final StrBuilder sb = new StrBuilder();
1394             final int len = sb.readFrom(new MockReadable(s));
1395 
1396             assertEquals(s.length(), len);
1397             assertEquals(s, sb.toString());
1398 
1399             s += Integer.toString(i);
1400         }
1401     }
1402 
1403     @Test
1404     void testReadFromReadableAppendsToEnd() throws Exception {
1405         final StrBuilder sb = new StrBuilder("Test");
1406         sb.readFrom(new MockReadable(" 123"));
1407         assertEquals("Test 123", sb.toString());
1408     }
1409 
1410     @Test
1411     void testReadFromReader() throws Exception {
1412         String s = "";
1413         for (int i = 0; i < 100; ++i) {
1414             final StrBuilder sb = new StrBuilder();
1415             final int len = sb.readFrom(new StringReader(s));
1416 
1417             assertEquals(s.length(), len);
1418             assertEquals(s, sb.toString());
1419 
1420             s += Integer.toString(i);
1421         }
1422     }
1423 
1424     @Test
1425     void testReadFromReaderAppendsToEnd() throws Exception {
1426         final StrBuilder sb = new StrBuilder("Test");
1427         sb.readFrom(new StringReader(" 123"));
1428         assertEquals("Test 123", sb.toString());
1429     }
1430 
1431     @Test
1432     void testReplace_int_int_String() {
1433         StrBuilder sb = new StrBuilder("abc");
1434         sb.replace(0, 1, "d");
1435         assertEquals("dbc", sb.toString());
1436         sb.replace(0, 1, "aaa");
1437         assertEquals("aaabc", sb.toString());
1438         sb.replace(0, 3, "");
1439         assertEquals("bc", sb.toString());
1440         sb.replace(1, 2, (String) null);
1441         assertEquals("b", sb.toString());
1442         sb.replace(1, 1000, "text");
1443         assertEquals("btext", sb.toString());
1444         sb.replace(0, 1000, "text");
1445         assertEquals("text", sb.toString());
1446 
1447         sb = new StrBuilder("atext");
1448         sb.replace(1, 1, "ny");
1449         assertEquals("anytext", sb.toString());
1450         try {
1451             sb.replace(2, 1, "anything");
1452             fail("Expected IndexOutOfBoundsException");
1453         } catch (final IndexOutOfBoundsException e) {
1454             // expected
1455         }
1456 
1457         sb = new StrBuilder();
1458         try {
1459             sb.replace(1, 2, "anything");
1460             fail("Expected IndexOutOfBoundsException");
1461         } catch (final IndexOutOfBoundsException e) {
1462             // expected
1463         }
1464         try {
1465             sb.replace(-1, 1, "anything");
1466             fail("Expected IndexOutOfBoundsException");
1467         } catch (final IndexOutOfBoundsException e) {
1468             // expected
1469         }
1470     }
1471 
1472     @Test
1473     void testReplace_StrMatcher_String_int_int_int_VaryCount() {
1474         StrBuilder sb = new StrBuilder("aaxaaaayaa");
1475         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 10, -1);
1476         assertEquals("-x--y-", sb.toString());
1477 
1478         sb = new StrBuilder("aaxaaaayaa");
1479         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 10, 0);
1480         assertEquals("aaxaaaayaa", sb.toString());
1481 
1482         sb = new StrBuilder("aaxaaaayaa");
1483         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 10, 1);
1484         assertEquals("-xaaaayaa", sb.toString());
1485 
1486         sb = new StrBuilder("aaxaaaayaa");
1487         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 10, 2);
1488         assertEquals("-x-aayaa", sb.toString());
1489 
1490         sb = new StrBuilder("aaxaaaayaa");
1491         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 10, 3);
1492         assertEquals("-x--yaa", sb.toString());
1493 
1494         sb = new StrBuilder("aaxaaaayaa");
1495         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 10, 4);
1496         assertEquals("-x--y-", sb.toString());
1497 
1498         sb = new StrBuilder("aaxaaaayaa");
1499         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 10, 5);
1500         assertEquals("-x--y-", sb.toString());
1501     }
1502 
1503     @Test
1504     void testReplace_StrMatcher_String_int_int_int_VaryEndIndex() {
1505         StrBuilder sb = new StrBuilder("aaxaaaayaa");
1506         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 0, -1);
1507         assertEquals("aaxaaaayaa", sb.toString());
1508 
1509         sb = new StrBuilder("aaxaaaayaa");
1510         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 2, -1);
1511         assertEquals("-xaaaayaa", sb.toString());
1512 
1513         sb = new StrBuilder("aaxaaaayaa");
1514         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 3, -1);
1515         assertEquals("-xaaaayaa", sb.toString());
1516 
1517         sb = new StrBuilder("aaxaaaayaa");
1518         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 4, -1);
1519         assertEquals("-xaaaayaa", sb.toString());
1520 
1521         sb = new StrBuilder("aaxaaaayaa");
1522         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 5, -1);
1523         assertEquals("-x-aayaa", sb.toString());
1524 
1525         sb = new StrBuilder("aaxaaaayaa");
1526         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 6, -1);
1527         assertEquals("-x-aayaa", sb.toString());
1528 
1529         sb = new StrBuilder("aaxaaaayaa");
1530         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 7, -1);
1531         assertEquals("-x--yaa", sb.toString());
1532 
1533         sb = new StrBuilder("aaxaaaayaa");
1534         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 8, -1);
1535         assertEquals("-x--yaa", sb.toString());
1536 
1537         sb = new StrBuilder("aaxaaaayaa");
1538         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 9, -1);
1539         assertEquals("-x--yaa", sb.toString());
1540 
1541         sb = new StrBuilder("aaxaaaayaa");
1542         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 10, -1);
1543         assertEquals("-x--y-", sb.toString());
1544 
1545         sb = new StrBuilder("aaxaaaayaa");
1546         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, 1000, -1);
1547         assertEquals("-x--y-", sb.toString());
1548 
1549         sb = new StrBuilder("aaxaaaayaa");
1550         try {
1551             sb.replace(StrMatcher.stringMatcher("aa"), "-", 2, 1, -1);
1552             fail("Exception expected.");
1553         } catch (final IndexOutOfBoundsException ex) {
1554             // expected
1555         }
1556         assertEquals("aaxaaaayaa", sb.toString());
1557     }
1558 
1559     @Test
1560     void testReplace_StrMatcher_String_int_int_int_VaryMatcher() {
1561         StrBuilder sb = new StrBuilder("abcbccba");
1562         sb.replace((StrMatcher) null, "x", 0, sb.length(), -1);
1563         assertEquals("abcbccba", sb.toString());
1564 
1565         sb.replace(StrMatcher.charMatcher('a'), "x", 0, sb.length(), -1);
1566         assertEquals("xbcbccbx", sb.toString());
1567 
1568         sb.replace(StrMatcher.stringMatcher("cb"), "x", 0, sb.length(), -1);
1569         assertEquals("xbxcxx", sb.toString());
1570 
1571         sb = new StrBuilder("A1-A2A3-A4");
1572         sb.replace(A_NUMBER_MATCHER, "***", 0, sb.length(), -1);
1573         assertEquals("***-******-***", sb.toString());
1574 
1575         sb = new StrBuilder();
1576         sb.replace(A_NUMBER_MATCHER, "***", 0, sb.length(), -1);
1577         assertEquals("", sb.toString());
1578     }
1579 
1580     @Test
1581     void testReplace_StrMatcher_String_int_int_int_VaryReplace() {
1582         StrBuilder sb = new StrBuilder("abcbccba");
1583         sb.replace(StrMatcher.stringMatcher("cb"), "cb", 0, sb.length(), -1);
1584         assertEquals("abcbccba", sb.toString());
1585 
1586         sb = new StrBuilder("abcbccba");
1587         sb.replace(StrMatcher.stringMatcher("cb"), "-", 0, sb.length(), -1);
1588         assertEquals("ab-c-a", sb.toString());
1589 
1590         sb = new StrBuilder("abcbccba");
1591         sb.replace(StrMatcher.stringMatcher("cb"), "+++", 0, sb.length(), -1);
1592         assertEquals("ab+++c+++a", sb.toString());
1593 
1594         sb = new StrBuilder("abcbccba");
1595         sb.replace(StrMatcher.stringMatcher("cb"), "", 0, sb.length(), -1);
1596         assertEquals("abca", sb.toString());
1597 
1598         sb = new StrBuilder("abcbccba");
1599         sb.replace(StrMatcher.stringMatcher("cb"), null, 0, sb.length(), -1);
1600         assertEquals("abca", sb.toString());
1601     }
1602 
1603     @Test
1604     void testReplace_StrMatcher_String_int_int_int_VaryStartIndex() {
1605         StrBuilder sb = new StrBuilder("aaxaaaayaa");
1606         sb.replace(StrMatcher.stringMatcher("aa"), "-", 0, sb.length(), -1);
1607         assertEquals("-x--y-", sb.toString());
1608 
1609         sb = new StrBuilder("aaxaaaayaa");
1610         sb.replace(StrMatcher.stringMatcher("aa"), "-", 1, sb.length(), -1);
1611         assertEquals("aax--y-", sb.toString());
1612 
1613         sb = new StrBuilder("aaxaaaayaa");
1614         sb.replace(StrMatcher.stringMatcher("aa"), "-", 2, sb.length(), -1);
1615         assertEquals("aax--y-", sb.toString());
1616 
1617         sb = new StrBuilder("aaxaaaayaa");
1618         sb.replace(StrMatcher.stringMatcher("aa"), "-", 3, sb.length(), -1);
1619         assertEquals("aax--y-", sb.toString());
1620 
1621         sb = new StrBuilder("aaxaaaayaa");
1622         sb.replace(StrMatcher.stringMatcher("aa"), "-", 4, sb.length(), -1);
1623         assertEquals("aaxa-ay-", sb.toString());
1624 
1625         sb = new StrBuilder("aaxaaaayaa");
1626         sb.replace(StrMatcher.stringMatcher("aa"), "-", 5, sb.length(), -1);
1627         assertEquals("aaxaa-y-", sb.toString());
1628 
1629         sb = new StrBuilder("aaxaaaayaa");
1630         sb.replace(StrMatcher.stringMatcher("aa"), "-", 6, sb.length(), -1);
1631         assertEquals("aaxaaaay-", sb.toString());
1632 
1633         sb = new StrBuilder("aaxaaaayaa");
1634         sb.replace(StrMatcher.stringMatcher("aa"), "-", 7, sb.length(), -1);
1635         assertEquals("aaxaaaay-", sb.toString());
1636 
1637         sb = new StrBuilder("aaxaaaayaa");
1638         sb.replace(StrMatcher.stringMatcher("aa"), "-", 8, sb.length(), -1);
1639         assertEquals("aaxaaaay-", sb.toString());
1640 
1641         sb = new StrBuilder("aaxaaaayaa");
1642         sb.replace(StrMatcher.stringMatcher("aa"), "-", 9, sb.length(), -1);
1643         assertEquals("aaxaaaayaa", sb.toString());
1644 
1645         sb = new StrBuilder("aaxaaaayaa");
1646         sb.replace(StrMatcher.stringMatcher("aa"), "-", 10, sb.length(), -1);
1647         assertEquals("aaxaaaayaa", sb.toString());
1648 
1649         sb = new StrBuilder("aaxaaaayaa");
1650         try {
1651             sb.replace(StrMatcher.stringMatcher("aa"), "-", 11, sb.length(), -1);
1652             fail("Exception expected.");
1653         } catch (final IndexOutOfBoundsException ex) {
1654             // expected
1655         }
1656         assertEquals("aaxaaaayaa", sb.toString());
1657 
1658         sb = new StrBuilder("aaxaaaayaa");
1659         try {
1660             sb.replace(StrMatcher.stringMatcher("aa"), "-", -1, sb.length(), -1);
1661             fail("Exception expected.");
1662         } catch (final IndexOutOfBoundsException ex) {
1663             // expected
1664         }
1665         assertEquals("aaxaaaayaa", sb.toString());
1666     }
1667 
1668     @Test
1669     void testReplaceAll_char_char() {
1670         final StrBuilder sb = new StrBuilder("abcbccba");
1671         sb.replaceAll('x', 'y');
1672         assertEquals("abcbccba", sb.toString());
1673         sb.replaceAll('a', 'd');
1674         assertEquals("dbcbccbd", sb.toString());
1675         sb.replaceAll('b', 'e');
1676         assertEquals("dececced", sb.toString());
1677         sb.replaceAll('c', 'f');
1678         assertEquals("defeffed", sb.toString());
1679         sb.replaceAll('d', 'd');
1680         assertEquals("defeffed", sb.toString());
1681     }
1682 
1683     @Test
1684     void testReplaceAll_String_String() {
1685         StrBuilder sb = new StrBuilder("abcbccba");
1686         sb.replaceAll((String) null, null);
1687         assertEquals("abcbccba", sb.toString());
1688         sb.replaceAll((String) null, "anything");
1689         assertEquals("abcbccba", sb.toString());
1690         sb.replaceAll("", null);
1691         assertEquals("abcbccba", sb.toString());
1692         sb.replaceAll("", "anything");
1693         assertEquals("abcbccba", sb.toString());
1694 
1695         sb.replaceAll("x", "y");
1696         assertEquals("abcbccba", sb.toString());
1697         sb.replaceAll("a", "d");
1698         assertEquals("dbcbccbd", sb.toString());
1699         sb.replaceAll("d", null);
1700         assertEquals("bcbccb", sb.toString());
1701         sb.replaceAll("cb", "-");
1702         assertEquals("b-c-", sb.toString());
1703 
1704         sb = new StrBuilder("abcba");
1705         sb.replaceAll("b", "xbx");
1706         assertEquals("axbxcxbxa", sb.toString());
1707 
1708         sb = new StrBuilder("bb");
1709         sb.replaceAll("b", "xbx");
1710         assertEquals("xbxxbx", sb.toString());
1711     }
1712 
1713     @Test
1714     void testReplaceAll_StrMatcher_String() {
1715         StrBuilder sb = new StrBuilder("abcbccba");
1716         sb.replaceAll((StrMatcher) null, null);
1717         assertEquals("abcbccba", sb.toString());
1718         sb.replaceAll((StrMatcher) null, "anything");
1719         assertEquals("abcbccba", sb.toString());
1720         sb.replaceAll(StrMatcher.noneMatcher(), null);
1721         assertEquals("abcbccba", sb.toString());
1722         sb.replaceAll(StrMatcher.noneMatcher(), "anything");
1723         assertEquals("abcbccba", sb.toString());
1724 
1725         sb.replaceAll(StrMatcher.charMatcher('x'), "y");
1726         assertEquals("abcbccba", sb.toString());
1727         sb.replaceAll(StrMatcher.charMatcher('a'), "d");
1728         assertEquals("dbcbccbd", sb.toString());
1729         sb.replaceAll(StrMatcher.charMatcher('d'), null);
1730         assertEquals("bcbccb", sb.toString());
1731         sb.replaceAll(StrMatcher.stringMatcher("cb"), "-");
1732         assertEquals("b-c-", sb.toString());
1733 
1734         sb = new StrBuilder("abcba");
1735         sb.replaceAll(StrMatcher.charMatcher('b'), "xbx");
1736         assertEquals("axbxcxbxa", sb.toString());
1737 
1738         sb = new StrBuilder("bb");
1739         sb.replaceAll(StrMatcher.charMatcher('b'), "xbx");
1740         assertEquals("xbxxbx", sb.toString());
1741 
1742         sb = new StrBuilder("A1-A2A3-A4");
1743         sb.replaceAll(A_NUMBER_MATCHER, "***");
1744         assertEquals("***-******-***", sb.toString());
1745 
1746         sb = new StrBuilder("Dear X, hello X.");
1747         sb.replaceAll(StrMatcher.stringMatcher("X"), "012345678901234567");
1748         assertEquals("Dear 012345678901234567, hello 012345678901234567.", sb.toString());
1749     }
1750 
1751     @Test
1752     void testReplaceFirst_char_char() {
1753         final StrBuilder sb = new StrBuilder("abcbccba");
1754         sb.replaceFirst('x', 'y');
1755         assertEquals("abcbccba", sb.toString());
1756         sb.replaceFirst('a', 'd');
1757         assertEquals("dbcbccba", sb.toString());
1758         sb.replaceFirst('b', 'e');
1759         assertEquals("decbccba", sb.toString());
1760         sb.replaceFirst('c', 'f');
1761         assertEquals("defbccba", sb.toString());
1762         sb.replaceFirst('d', 'd');
1763         assertEquals("defbccba", sb.toString());
1764     }
1765 
1766     @Test
1767     void testReplaceFirst_String_String() {
1768         StrBuilder sb = new StrBuilder("abcbccba");
1769         sb.replaceFirst((String) null, null);
1770         assertEquals("abcbccba", sb.toString());
1771         sb.replaceFirst((String) null, "anything");
1772         assertEquals("abcbccba", sb.toString());
1773         sb.replaceFirst("", null);
1774         assertEquals("abcbccba", sb.toString());
1775         sb.replaceFirst("", "anything");
1776         assertEquals("abcbccba", sb.toString());
1777 
1778         sb.replaceFirst("x", "y");
1779         assertEquals("abcbccba", sb.toString());
1780         sb.replaceFirst("a", "d");
1781         assertEquals("dbcbccba", sb.toString());
1782         sb.replaceFirst("d", null);
1783         assertEquals("bcbccba", sb.toString());
1784         sb.replaceFirst("cb", "-");
1785         assertEquals("b-ccba", sb.toString());
1786 
1787         sb = new StrBuilder("abcba");
1788         sb.replaceFirst("b", "xbx");
1789         assertEquals("axbxcba", sb.toString());
1790 
1791         sb = new StrBuilder("bb");
1792         sb.replaceFirst("b", "xbx");
1793         assertEquals("xbxb", sb.toString());
1794     }
1795 
1796     @Test
1797     void testReplaceFirst_StrMatcher_String() {
1798         StrBuilder sb = new StrBuilder("abcbccba");
1799         sb.replaceFirst((StrMatcher) null, null);
1800         assertEquals("abcbccba", sb.toString());
1801         sb.replaceFirst((StrMatcher) null, "anything");
1802         assertEquals("abcbccba", sb.toString());
1803         sb.replaceFirst(StrMatcher.noneMatcher(), null);
1804         assertEquals("abcbccba", sb.toString());
1805         sb.replaceFirst(StrMatcher.noneMatcher(), "anything");
1806         assertEquals("abcbccba", sb.toString());
1807 
1808         sb.replaceFirst(StrMatcher.charMatcher('x'), "y");
1809         assertEquals("abcbccba", sb.toString());
1810         sb.replaceFirst(StrMatcher.charMatcher('a'), "d");
1811         assertEquals("dbcbccba", sb.toString());
1812         sb.replaceFirst(StrMatcher.charMatcher('d'), null);
1813         assertEquals("bcbccba", sb.toString());
1814         sb.replaceFirst(StrMatcher.stringMatcher("cb"), "-");
1815         assertEquals("b-ccba", sb.toString());
1816 
1817         sb = new StrBuilder("abcba");
1818         sb.replaceFirst(StrMatcher.charMatcher('b'), "xbx");
1819         assertEquals("axbxcba", sb.toString());
1820 
1821         sb = new StrBuilder("bb");
1822         sb.replaceFirst(StrMatcher.charMatcher('b'), "xbx");
1823         assertEquals("xbxb", sb.toString());
1824 
1825         sb = new StrBuilder("A1-A2A3-A4");
1826         sb.replaceFirst(A_NUMBER_MATCHER, "***");
1827         assertEquals("***-A2A3-A4", sb.toString());
1828     }
1829 
1830     @Test
1831     void testReverse() {
1832         final StrBuilder sb = new StrBuilder();
1833         assertEquals("", sb.reverse().toString());
1834 
1835         sb.clear().append(true);
1836         assertEquals("eurt", sb.reverse().toString());
1837         assertEquals("true", sb.reverse().toString());
1838     }
1839 
1840     @Test
1841     void testRightString() {
1842         final StrBuilder sb = new StrBuilder("left right");
1843         assertEquals("right", sb.rightString(5));
1844         assertEquals("", sb.rightString(0));
1845         assertEquals("", sb.rightString(-5));
1846         assertEquals("left right", sb.rightString(15));
1847     }
1848 
1849     @Test
1850     void testSetCharAt() {
1851         final StrBuilder sb = new StrBuilder();
1852         assertThrows(IndexOutOfBoundsException.class, () -> sb.setCharAt(0, 'f'));
1853         assertThrows(IndexOutOfBoundsException.class, () -> sb.setCharAt(-1, 'f'));
1854         sb.append("foo");
1855         sb.setCharAt(0, 'b');
1856         sb.setCharAt(1, 'a');
1857         sb.setCharAt(2, 'r');
1858         assertThrows(IndexOutOfBoundsException.class, () -> sb.setCharAt(3, '!'));
1859         assertEquals("bar", sb.toString());
1860     }
1861 
1862     @Test
1863     void testSetLength() {
1864         final StrBuilder sb = new StrBuilder();
1865         sb.append("Hello");
1866         sb.setLength(2); // shorten
1867         assertEquals("He", sb.toString());
1868         sb.setLength(2); // no change
1869         assertEquals("He", sb.toString());
1870         sb.setLength(3); // lengthen
1871         assertEquals("He\0", sb.toString());
1872 
1873         assertThrows(IndexOutOfBoundsException.class, () -> sb.setLength(-1));
1874     }
1875 
1876     @Test
1877     void testSize() {
1878         final StrBuilder sb = new StrBuilder();
1879         assertEquals(0, sb.size());
1880 
1881         sb.append("Hello");
1882         assertEquals(5, sb.size());
1883     }
1884 
1885     @Test
1886     void testStartsWith() {
1887         final StrBuilder sb = new StrBuilder();
1888         assertFalse(sb.startsWith("a"));
1889         assertFalse(sb.startsWith(null));
1890         assertTrue(sb.startsWith(""));
1891         sb.append("abc");
1892         assertTrue(sb.startsWith("a"));
1893         assertTrue(sb.startsWith("ab"));
1894         assertTrue(sb.startsWith("abc"));
1895         assertFalse(sb.startsWith("cba"));
1896     }
1897 
1898     @Test
1899     void testSubSequenceIntInt() {
1900         final StrBuilder sb = new StrBuilder("hello goodbye");
1901         // Start index is negative
1902         assertThrows(IndexOutOfBoundsException.class, () -> sb.subSequence(-1, 5));
1903 
1904         // End index is negative
1905         assertThrows(IndexOutOfBoundsException.class, () -> sb.subSequence(2, -1));
1906 
1907         // End index greater than length()
1908         assertThrows(IndexOutOfBoundsException.class, () -> sb.subSequence(2, sb.length() + 1));
1909 
1910         // Start index greater than end index
1911         assertThrows(IndexOutOfBoundsException.class, () -> sb.subSequence(3, 2));
1912 
1913         // Normal cases
1914         assertEquals("hello", sb.subSequence(0, 5));
1915         assertEquals("hello goodbye".subSequence(0, 6), sb.subSequence(0, 6));
1916         assertEquals("goodbye", sb.subSequence(6, 13));
1917         assertEquals("hello goodbye".subSequence(6, 13), sb.subSequence(6, 13));
1918     }
1919 
1920     @Test
1921     void testSubstringInt() {
1922         final StrBuilder sb = new StrBuilder("hello goodbye");
1923         assertEquals("goodbye", sb.substring(6));
1924         assertEquals("hello goodbye".substring(6), sb.substring(6));
1925         assertEquals("hello goodbye", sb.substring(0));
1926         assertEquals("hello goodbye".substring(0), sb.substring(0));
1927         assertThrows(IndexOutOfBoundsException.class, () -> sb.substring(-1));
1928         assertThrows(IndexOutOfBoundsException.class, () -> sb.substring(15));
1929 
1930     }
1931 
1932     @Test
1933     void testSubstringIntInt() {
1934         final StrBuilder sb = new StrBuilder("hello goodbye");
1935         assertEquals("hello", sb.substring(0, 5));
1936         assertEquals("hello goodbye".substring(0, 6), sb.substring(0, 6));
1937 
1938         assertEquals("goodbye", sb.substring(6, 13));
1939         assertEquals("hello goodbye".substring(6, 13), sb.substring(6, 13));
1940 
1941         assertEquals("goodbye", sb.substring(6, 20));
1942 
1943         assertThrows(IndexOutOfBoundsException.class, () -> sb.substring(-1, 5));
1944 
1945         assertThrows(IndexOutOfBoundsException.class, () -> sb.substring(15, 20));
1946     }
1947 
1948     @Test
1949     void testToCharArray() {
1950         final StrBuilder sb = new StrBuilder();
1951         assertEquals(0, sb.toCharArray().length);
1952 
1953         char[] a = sb.toCharArray();
1954         assertNotNull(a, "toCharArray() result is null");
1955         assertEquals(0, a.length, "toCharArray() result is too large");
1956 
1957         sb.append("junit");
1958         a = sb.toCharArray();
1959         assertEquals(5, a.length, "toCharArray() result incorrect length");
1960         assertArrayEquals("junit".toCharArray(), a, "toCharArray() result does not match");
1961     }
1962 
1963     @Test
1964     void testToCharArrayIntInt() {
1965         final StrBuilder sb = new StrBuilder();
1966         assertEquals(0, sb.toCharArray(0, 0).length);
1967 
1968         sb.append("junit");
1969         char[] a = sb.toCharArray(0, 20); // too large test
1970         assertEquals(5, a.length, "toCharArray(int,int) result incorrect length");
1971         assertArrayEquals("junit".toCharArray(), a, "toCharArray(int,int) result does not match");
1972 
1973         a = sb.toCharArray(0, 4);
1974         assertEquals(4, a.length, "toCharArray(int,int) result incorrect length");
1975         assertArrayEquals("juni".toCharArray(), a, "toCharArray(int,int) result does not match");
1976 
1977         a = sb.toCharArray(0, 4);
1978         assertEquals(4, a.length, "toCharArray(int,int) result incorrect length");
1979         assertArrayEquals("juni".toCharArray(), a, "toCharArray(int,int) result does not match");
1980 
1981         a = sb.toCharArray(0, 1);
1982         assertNotNull(a, "toCharArray(int,int) result is null");
1983 
1984         assertThrows(IndexOutOfBoundsException.class, () -> sb.toCharArray(-1, 5));
1985 
1986         assertThrows(IndexOutOfBoundsException.class, () -> sb.toCharArray(6, 5));
1987     }
1988 
1989     @Test
1990     void testToString() {
1991         final StrBuilder sb = new StrBuilder("abc");
1992         assertEquals("abc", sb.toString());
1993     }
1994 
1995     @Test
1996     void testToStringBuffer() {
1997         final StrBuilder sb = new StrBuilder();
1998         assertEquals(new StringBuffer().toString(), sb.toStringBuffer().toString());
1999 
2000         sb.append("junit");
2001         assertEquals(new StringBuffer("junit").toString(), sb.toStringBuffer().toString());
2002     }
2003 
2004     @Test
2005     void testToStringBuilder() {
2006         final StrBuilder sb = new StrBuilder();
2007         assertEquals(new StringBuilder().toString(), sb.toStringBuilder().toString());
2008 
2009         sb.append("junit");
2010         assertEquals(new StringBuilder("junit").toString(), sb.toStringBuilder().toString());
2011     }
2012 
2013     @Test
2014     void testTrim() {
2015         final StrBuilder sb = new StrBuilder();
2016         assertEquals("", sb.reverse().toString());
2017 
2018         sb.clear().append(" \u0000 ");
2019         assertEquals("", sb.trim().toString());
2020 
2021         sb.clear().append(" \u0000 a b c");
2022         assertEquals("a b c", sb.trim().toString());
2023 
2024         sb.clear().append("a b c \u0000 ");
2025         assertEquals("a b c", sb.trim().toString());
2026 
2027         sb.clear().append(" \u0000 a b c \u0000 ");
2028         assertEquals("a b c", sb.trim().toString());
2029 
2030         sb.clear().append("a b c");
2031         assertEquals("a b c", sb.trim().toString());
2032     }
2033 }