1cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath/*
2cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * Copyright (C) 2011 The Android Open Source Project
3cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath *
4cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * Licensed under the Apache License, Version 2.0 (the "License");
5cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * you may not use this file except in compliance with the License.
6cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * You may obtain a copy of the License at
7cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath *
8cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath *      http://www.apache.org/licenses/LICENSE-2.0
9cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath *
10cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * Unless required by applicable law or agreed to in writing, software
11cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * distributed under the License is distributed on an "AS IS" BASIS,
12cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * See the License for the specific language governing permissions and
14cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath * limitations under the License.
15cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath */
16cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
17cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamathpackage libcore.java.lang;
18cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
195458546631c65f6d375b6a1780d36d0abb5b95afYi Kongimport java.util.Arrays;
205458546631c65f6d375b6a1780d36d0abb5b95afYi Kong
21cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamathpublic class StringBuilderTest extends junit.framework.TestCase {
22cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    // See https://code.google.com/p/android/issues/detail?id=60639
23cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    public void test_deleteChatAt_lastRange() {
24cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        StringBuilder sb = new StringBuilder("oarFish_");
25cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.append('a');
26cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        String oarFishA = sb.toString();
27cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
28cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.deleteCharAt(sb.length() - 1);
29cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.append('b');
30cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        String oarFishB = sb.toString();
31cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
32cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("oarFish_a", oarFishA);
33cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("oarFish_b", oarFishB);
34cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    }
35cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
36cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    // See https://code.google.com/p/android/issues/detail?id=60639
37cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    public void test_deleteCharAt_lastChar() {
38cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        StringBuilder sb = new StringBuilder();
39cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.append('a');
40cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        String a = sb.toString();
41cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
42cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.deleteCharAt(0);
43cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.append('b');
44cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        String b = sb.toString();
45cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
46cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("a", a);
47cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("b", b);
48cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    }
49cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
50cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    // See https://code.google.com/p/android/issues/detail?id=60639
51cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    public void test_delete_endsAtLastChar() {
52cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        StringBuilder sb = new StringBuilder("newGuineaSinging");
53cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.append("Dog");
54cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        String dog = sb.toString();
55cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
56cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.delete(sb.length() - 3, sb.length());
57cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.append("Cat");
58cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        String cat = sb.toString();
59cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
60cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // NOTE: It's important that these asserts stay at the end of this test.
61cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // We're trying to make sure that replacing chars in the builder does not
62cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // change strings that have already been returned from it.
63cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("newGuineaSingingDog", dog);
64cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("newGuineaSingingCat", cat);
65cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    }
66cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
67cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    public void test_deleteCharAt_boundsChecks() {
68cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        StringBuilder sb = new StringBuilder("yeti");
69cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
70cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        try {
71cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            sb.deleteCharAt(sb.length());
72cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            fail();
73cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        } catch (StringIndexOutOfBoundsException expected) {
74cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        }
75cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
76cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        try {
77cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            sb.deleteCharAt(-1);
78cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            fail();
79cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        } catch (StringIndexOutOfBoundsException expected) {
80cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        }
81cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    }
82cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
83cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    public void test_delete_boundsChecks() throws Exception {
84cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        StringBuilder sb = new StringBuilder("yeti");
85cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
86cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // The cases below ahould not throw (even though they are clearly invalid
87cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // ranges), because we promise not to throw if start == count as long as
88cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // end >= start.
89cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.delete(sb.length(), sb.length() + 2);
90cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.delete(sb.length(), sb.length());
91cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
92cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.delete(2, 2);
93cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("yeti", sb.toString());
94cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
95cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // We must throw if start > count....
96cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        try {
97cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            sb.delete(sb.length() + 2, sb.length() + 3);
98cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            fail();
99cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        } catch (StringIndexOutOfBoundsException expected) {
100cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        }
101cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
102cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // ... even if the length of the range is 0.
103cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        try {
104cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            sb.delete(sb.length() + 2, sb.length() + 2);
105cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            fail();
106cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        } catch (StringIndexOutOfBoundsException expected) {
107cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        }
108cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
109cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // Must throw if start < 0.
110cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        try {
111cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            sb.delete(-1, sb.length() -1);
112cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath            fail();
113cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        } catch (StringIndexOutOfBoundsException expected) {
114cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        }
115cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
116cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // A few commonly used specializations: sb.delete(0, 0) on an empty
117cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        // builder is a particularly common pattern.
118cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        StringBuilder sb2 = new StringBuilder();
119cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb2.delete(0, sb2.length());
120cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb2.delete(0, 12);
121cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    }
122cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
123cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    // We shouldn't throw if the end index is > count, we should clamp it
124cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    // instead.
125cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    public void test_delete_clampsEnd() throws Exception {
126cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        StringBuilder sb = new StringBuilder("mogwai");
127cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
128cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.delete(sb.length() - 1 , sb.length() + 2);
129cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("mogwa", sb.toString());
130cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath
131cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        sb.delete(sb.length() - 1, sb.length());
132cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath        assertEquals("mogw", sb.toString());
133cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath    }
1345458546631c65f6d375b6a1780d36d0abb5b95afYi Kong
1355458546631c65f6d375b6a1780d36d0abb5b95afYi Kong    public void testChars() {
1365458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        StringBuilder s = new StringBuilder("Hello\n\tworld");
1375458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        int[] expected = new int[s.length()];
1385458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        for (int i = 0; i < s.length(); ++i) {
1395458546631c65f6d375b6a1780d36d0abb5b95afYi Kong            expected[i] = (int) s.charAt(i);
1405458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        }
1415458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        assertTrue(Arrays.equals(expected, s.chars().toArray()));
1425458546631c65f6d375b6a1780d36d0abb5b95afYi Kong
1435458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        // Surrogate code point
1445458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        char high = '\uD83D', low = '\uDE02';
1455458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        StringBuilder surrogateCP = new StringBuilder().append(new char[]{high, low, low});
1465458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        assertTrue(Arrays.equals(new int[]{high, low, low}, surrogateCP.chars().toArray()));
1475458546631c65f6d375b6a1780d36d0abb5b95afYi Kong    }
1485458546631c65f6d375b6a1780d36d0abb5b95afYi Kong
1495458546631c65f6d375b6a1780d36d0abb5b95afYi Kong    public void testCodePoints() {
1505458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        StringBuilder s = new StringBuilder("Hello\n\tworld");
1515458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        int[] expected = new int[s.length()];
1525458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        for (int i = 0; i < s.length(); ++i) {
1535458546631c65f6d375b6a1780d36d0abb5b95afYi Kong            expected[i] = (int) s.charAt(i);
1545458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        }
1555458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        assertTrue(Arrays.equals(expected, s.codePoints().toArray()));
1565458546631c65f6d375b6a1780d36d0abb5b95afYi Kong
1575458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        // Surrogate code point
1585458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        char high = '\uD83D', low = '\uDE02';
1595458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        StringBuilder surrogateCP = new StringBuilder().append(new char[]{high, low, low, '0'});
1605458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        assertEquals(Character.toCodePoint(high, low), surrogateCP.codePoints().toArray()[0]);
1615458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        assertEquals((int) low, surrogateCP.codePoints().toArray()[1]); // Unmatched surrogate.
1625458546631c65f6d375b6a1780d36d0abb5b95afYi Kong        assertEquals((int) '0', surrogateCP.codePoints().toArray()[2]);
1635458546631c65f6d375b6a1780d36d0abb5b95afYi Kong    }
164cb3a4d2fd82759b64c13f60643b4450a5236885fNarayan Kamath}
165