1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package android.text;
18
19import static android.text.Layout.Alignment.*;
20
21import android.text.DynamicLayout;
22
23import junit.framework.TestCase;
24
25/**
26 * Tests DynamciLayout updateBlocks method.
27 *
28 * Requires disabling access checks in the vm since this calls package-private APIs.
29 *
30 * @Suppress
31 */
32public class DynamicLayoutBlocksTest extends TestCase {
33    private DynamicLayout dl = new DynamicLayout("", new TextPaint(), 0, ALIGN_NORMAL, 0, 0, false);
34    private static final int ___ = DynamicLayout.INVALID_BLOCK_INDEX;
35
36    private int[] initialBlockEnds;
37    private int[] initialBlockIndices;
38
39    private void defineInitialState(int[] ends, int[] indices) {
40        initialBlockEnds = ends;
41        initialBlockIndices = indices;
42        assertEquals(initialBlockEnds.length, initialBlockIndices.length);
43    }
44
45    public void printBlocks(String message) {
46        System.out.print(message);
47        for (int i = 0; i < dl.getNumberOfBlocks(); i++) {
48            System.out.print("  " + Integer.toString(dl.getBlockEndLines()[i]));
49        }
50        System.out.println();
51    }
52
53    public void checkInvariants() {
54        assertTrue(dl.getNumberOfBlocks() > 0);
55        assertTrue(dl.getNumberOfBlocks() <= dl.getBlockEndLines().length);
56        assertEquals(dl.getBlockEndLines().length, dl.getBlockIndices().length);
57
58        for (int i = 1; i < dl.getNumberOfBlocks(); i++) {
59            assertTrue(dl.getBlockEndLines()[i] > dl.getBlockEndLines()[i-1]);
60        }
61    }
62
63    private void update(int startLine, int endLine, int newLineCount) {
64        dl.setBlocksDataForTest(initialBlockEnds, initialBlockIndices, initialBlockEnds.length);
65        checkInvariants();
66        dl.updateBlocks(startLine, endLine, newLineCount);
67    }
68
69    private void assertState(int[] sizes, int[] indices) {
70        checkInvariants();
71
72        assertEquals(sizes.length, dl.getNumberOfBlocks());
73        assertEquals(indices.length, dl.getNumberOfBlocks());
74
75        int[] ends = new int[sizes.length];
76        for (int i = 0; i < ends.length; i++) {
77            ends[i] = i == 0 ? (sizes[0] == 0 ? 0 : sizes[0] - 1) : ends[i - 1] + sizes[i];
78        }
79
80        for (int i = 0; i < dl.getNumberOfBlocks(); i++) {
81            assertEquals(ends[i], dl.getBlockEndLines()[i]);
82            assertEquals(indices[i], dl.getBlockIndices()[i]);
83        }
84    }
85
86    private void assertState(int[] sizes) {
87        int[] ids = new int[sizes.length];
88        for (int i = 0; i < sizes.length; i++) {
89            ids[i] = DynamicLayout.INVALID_BLOCK_INDEX;
90        }
91        assertState(sizes, ids);
92    }
93
94    public void testFrom0() {
95        defineInitialState( new int[] { 0 }, new int[] { 123 });
96
97        update(0, 0, 0);
98        assertState( new int[] { 0 } );
99
100        update(0, 0, 1);
101        assertState( new int[] { 0 } );
102
103        update(0, 0, 10);
104        assertState( new int[] { 10 } );
105    }
106
107    public void testFrom1ReplaceByEmpty() {
108        defineInitialState( new int[] { 100 }, new int[] { 123 });
109
110        update(0, 0, 0);
111        assertState( new int[] { 100 } );
112
113        update(0, 10, 0);
114        assertState( new int[] { 90 } );
115
116        update(0, 100, 0);
117        assertState( new int[] { 0 } );
118
119        update(20, 30, 0);
120        assertState( new int[] { 20, 70 } );
121
122        update(20, 20, 0);
123        assertState( new int[] { 20, 80 } );
124
125        update(40, 100, 0);
126        assertState( new int[] { 40 } );
127
128        update(100, 100, 0);
129        assertState( new int[] { 100 } );
130    }
131
132    public void testFrom1ReplaceFromFirstLine() {
133        defineInitialState( new int[] { 100 }, new int[] { 123 });
134
135        update(0, 0, 1);
136        assertState( new int[] { 0, 100 } );
137
138        update(0, 0, 10);
139        assertState( new int[] { 10, 100 } );
140
141        update(0, 30, 31);
142        assertState( new int[] { 31, 70 } );
143
144        update(0, 100, 20);
145        assertState( new int[] { 20 } );
146    }
147
148    public void testFrom1ReplaceFromCenter() {
149        defineInitialState( new int[] { 100 }, new int[] { 123 });
150
151        update(20, 20, 1);
152        assertState( new int[] { 20, 1, 80 } );
153
154        update(20, 20, 10);
155        assertState( new int[] { 20, 10, 80 } );
156
157        update(20, 30, 50);
158        assertState( new int[] { 20, 50, 70 } );
159
160        update(20, 100, 50);
161        assertState( new int[] { 20, 50 } );
162    }
163
164    public void testFrom1ReplaceFromEnd() {
165        defineInitialState( new int[] { 100 }, new int[] { 123 });
166
167        update(100, 100, 0);
168        assertState( new int[] { 100 } );
169
170        update(100, 100, 1);
171        assertState( new int[] { 100, 1 } );
172
173        update(100, 100, 10);
174        assertState( new int[] { 100, 10 } );
175    }
176
177    public void testFrom2ReplaceFromFirstLine() {
178        defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
179
180        update(0, 4, 50);
181        assertState( new int[] { 50, 10-4, 20-10 }, new int[] { ___, ___, 456 } );
182
183        update(0, 10, 50);
184        assertState( new int[] { 50, 20-10 }, new int[] { ___, 456 } );
185
186        update(0, 15, 50);
187        assertState( new int[] { 50, 20-15 }, new int[] { ___, ___ } );
188
189        update(0, 20, 50);
190        assertState( new int[] { 50 }, new int[] { ___ } );
191    }
192
193    public void testFrom2ReplaceFromFirstBlock() {
194        defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
195
196        update(3, 7, 50);
197        assertState( new int[] { 3, 50, 10-7, 20-10 }, new int[] { ___, ___, ___, 456 } );
198
199        update(3, 10, 50);
200        assertState( new int[] { 3, 50, 20-10 }, new int[] { ___, ___, 456 } );
201
202        update(3, 14, 50);
203        assertState( new int[] { 3, 50, 20-14 }, new int[] { ___, ___, ___ } );
204
205        update(3, 20, 50);
206        assertState( new int[] { 3, 50 }, new int[] { ___, ___ } );
207    }
208
209    public void testFrom2ReplaceFromBottomBoundary() {
210        defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
211
212        update(10, 10, 50);
213        assertState( new int[] { 10, 50, 20-10 }, new int[] { ___, ___, 456 } );
214
215        update(10, 14, 50);
216        assertState( new int[] { 10, 50, 20-14 }, new int[] { ___, ___, ___ } );
217
218        update(10, 20, 50);
219        assertState( new int[] { 10, 50 }, new int[] { ___, ___ } );
220    }
221
222    public void testFrom2ReplaceFromTopBoundary() {
223        defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
224
225        update(11, 11, 50);
226        assertState( new int[] { 11, 50, 20-11 }, new int[] { 123, ___, ___ } );
227
228        update(11, 14, 50);
229        assertState( new int[] { 11, 50, 20-14 }, new int[] { 123, ___, ___ } );
230
231        update(11, 20, 50);
232        assertState( new int[] { 11, 50 }, new int[] { 123, ___ } );
233    }
234
235    public void testFrom2ReplaceFromSecondBlock() {
236        defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
237
238        update(14, 14, 50);
239        assertState( new int[] { 11, 14-11, 50, 20-14 }, new int[] { 123, ___, ___, ___ } );
240
241        update(14, 17, 50);
242        assertState( new int[] { 11, 14-11, 50, 20-17 }, new int[] { 123, ___, ___, ___ } );
243
244        update(14, 20, 50);
245        assertState( new int[] { 11, 14-11, 50 }, new int[] { 123, ___, ___ } );
246    }
247
248    public void testFrom2RemoveFromFirst() {
249        defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
250
251        update(0, 4, 0);
252        assertState( new int[] { 10-4, 20-10 }, new int[] { ___, 456 } );
253
254        update(0, 10, 0);
255        assertState( new int[] { 20-10 }, new int[] { 456 } );
256
257        update(0, 14, 0);
258        assertState( new int[] { 20-14 }, new int[] { ___ } );
259
260        update(0, 20, 0);
261        assertState( new int[] { 0 }, new int[] { ___ } );
262    }
263
264    public void testFrom2RemoveFromFirstBlock() {
265        defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
266
267        update(4, 7, 0);
268        assertState( new int[] { 4, 10-7, 20-10 }, new int[] { ___, ___, 456 } );
269
270        update(4, 10, 0);
271        assertState( new int[] { 4, 20-10 }, new int[] { ___, 456 } );
272
273        update(4, 14, 0);
274        assertState( new int[] { 4, 20-14 }, new int[] { ___, ___ } );
275
276        update(4, 20, 0);
277        assertState( new int[] { 4 }, new int[] { ___ } );
278    }
279
280    public void testFrom2RemoveFromSecondBlock() {
281        defineInitialState( new int[] { 10, 20 }, new int[] { 123, 456 });
282
283        update(14, 17, 0);
284        assertState( new int[] { 11, 14-11, 20-17 }, new int[] { 123, ___, ___ } );
285
286        update(14, 20, 0);
287        assertState( new int[] { 11, 14-11 }, new int[] { 123, ___ } );
288    }
289
290    public void testFrom3ReplaceFromFirstBlock() {
291        defineInitialState( new int[] { 10, 30, 60 }, new int[] { 123, 456, 789 });
292
293        update(3, 7, 50);
294        assertState( new int[] { 3, 50, 10-7, 30-10, 60-30 }, new int[] { ___, ___, ___, 456, 789 } );
295
296        update(3, 10, 50);
297        assertState( new int[] { 3, 50, 30-10, 60-30 }, new int[] { ___, ___, 456, 789 } );
298
299        update(3, 17, 50);
300        assertState( new int[] { 3, 50, 30-17, 60-30 }, new int[] { ___, ___, ___, 789 } );
301
302        update(3, 30, 50);
303        assertState( new int[] { 3, 50, 60-30 }, new int[] { ___, ___, 789 } );
304
305        update(3, 40, 50);
306        assertState( new int[] { 3, 50, 60-40 }, new int[] { ___, ___, ___ } );
307
308        update(3, 60, 50);
309        assertState( new int[] { 3, 50 }, new int[] { ___, ___ } );
310    }
311
312    public void testFrom3ReplaceFromSecondBlock() {
313        defineInitialState( new int[] { 10, 30, 60 }, new int[] { 123, 456, 789 });
314
315        update(13, 17, 50);
316        assertState( new int[] { 11, 2, 50, 30-17, 60-30 }, new int[] { 123, ___, ___, ___, 789 } );
317
318        update(13, 30, 50);
319        assertState( new int[] { 11, 2, 50, 60-30 }, new int[] { 123, ___, ___, 789 } );
320
321        update(13, 40, 50);
322        assertState( new int[] { 11, 2, 50, 60-40 }, new int[] { 123, ___, ___, ___ } );
323
324        update(13, 60, 50);
325        assertState( new int[] { 11, 2, 50 }, new int[] { 123, ___, ___ } );
326    }
327}
328