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