CursorAnchorInfoTest.java revision 0b01e7fc58cdde00d8350285a3386c4209b72d78
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of 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,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import android.graphics.Matrix;
20import android.graphics.RectF;
21import android.test.InstrumentationTestCase;
22import android.test.suitebuilder.annotation.SmallTest;
23import android.text.TextUtils;
24import android.view.inputmethod.CursorAnchorInfo;
25import android.view.inputmethod.CursorAnchorInfo.Builder;
26
27import java.util.Objects;
28
29import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE;
30import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE;
31import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_NOT_FEASIBLE;
32import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE;
33import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_UNSPECIFIED;
34
35public class CursorAnchorInfoTest extends InstrumentationTestCase {
36    private static final RectF[] MANY_RECTS = new RectF[] {
37            new RectF(101.0f, 201.0f, 301.0f, 401.0f),
38            new RectF(102.0f, 202.0f, 302.0f, 402.0f),
39            new RectF(103.0f, 203.0f, 303.0f, 403.0f),
40            new RectF(104.0f, 204.0f, 304.0f, 404.0f),
41            new RectF(105.0f, 205.0f, 305.0f, 405.0f),
42            new RectF(106.0f, 206.0f, 306.0f, 406.0f),
43            new RectF(107.0f, 207.0f, 307.0f, 407.0f),
44            new RectF(108.0f, 208.0f, 308.0f, 408.0f),
45            new RectF(109.0f, 209.0f, 309.0f, 409.0f),
46            new RectF(110.0f, 210.0f, 310.0f, 410.0f),
47            new RectF(111.0f, 211.0f, 311.0f, 411.0f),
48            new RectF(112.0f, 212.0f, 312.0f, 412.0f),
49            new RectF(113.0f, 213.0f, 313.0f, 413.0f),
50            new RectF(114.0f, 214.0f, 314.0f, 414.0f),
51            new RectF(115.0f, 215.0f, 315.0f, 415.0f),
52            new RectF(116.0f, 216.0f, 316.0f, 416.0f),
53            new RectF(117.0f, 217.0f, 317.0f, 417.0f),
54            new RectF(118.0f, 218.0f, 318.0f, 418.0f),
55            new RectF(119.0f, 219.0f, 319.0f, 419.0f),
56    };
57    private static final int[] MANY_FLAGS_ARRAY = new int[] {
58        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
59        CHARACTER_RECT_TYPE_INVISIBLE,
60        CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE,
61        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
62        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
63        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
64        CHARACTER_RECT_TYPE_NOT_FEASIBLE,
65        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
66        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
67        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
68        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
69        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
70        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
71        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
72        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
73        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
74        CHARACTER_RECT_TYPE_FULLY_VISIBLE,
75        CHARACTER_RECT_TYPE_NOT_FEASIBLE,
76        CHARACTER_RECT_TYPE_NOT_FEASIBLE,
77    };
78
79    @SmallTest
80    public void testBuilder() throws Exception {
81        final int SELECTION_START = 30;
82        final int SELECTION_END = 40;
83        final int COMPOSING_TEXT_START = 32;
84        final String COMPOSING_TEXT = "test";
85        final boolean INSERTION_MARKER_CLIPPED = true;
86        final float INSERTION_MARKER_HORIZONTAL = 10.5f;
87        final float INSERTION_MARKER_TOP = 100.1f;
88        final float INSERTION_MARKER_BASELINE = 110.4f;
89        final float INSERTION_MARKER_BOTOM = 111.0f;
90        Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
91        TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
92
93        final Builder builder = new Builder();
94        builder.setSelectionRange(SELECTION_START, SELECTION_END)
95                .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT)
96                .setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
97                        INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM,
98                        INSERTION_MARKER_CLIPPED)
99                .setMatrix(TRANSFORM_MATRIX);
100        for (int i = 0; i < MANY_RECTS.length; i++) {
101            final RectF rect = MANY_RECTS[i];
102            final int flags = MANY_FLAGS_ARRAY[i];
103            builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom, flags);
104        }
105
106        final CursorAnchorInfo info = builder.build();
107        assertEquals(SELECTION_START, info.getSelectionStart());
108        assertEquals(SELECTION_END, info.getSelectionEnd());
109        assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart());
110        assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText()));
111        assertTrue(info.isInsertionMarkerClipped());
112        assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal());
113        assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop());
114        assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline());
115        assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom());
116        assertEquals(TRANSFORM_MATRIX, info.getMatrix());
117        for (int i = 0; i < MANY_RECTS.length; i++) {
118            final RectF expectedRect = MANY_RECTS[i];
119            assertEquals(expectedRect, info.getCharacterRect(i));
120        }
121        assertNull(info.getCharacterRect(-1));
122        assertNull(info.getCharacterRect(MANY_RECTS.length + 1));
123        for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
124            final int expectedFlags = MANY_FLAGS_ARRAY[i];
125            assertEquals(expectedFlags, info.getCharacterRectFlags(i));
126        }
127        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
128                info.getCharacterRectFlags(-1));
129        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
130                info.getCharacterRectFlags(MANY_RECTS.length + 1));
131
132        // Make sure that the builder can reproduce the same object.
133        final CursorAnchorInfo info2 = builder.build();
134        assertEquals(SELECTION_START, info2.getSelectionStart());
135        assertEquals(SELECTION_END, info2.getSelectionEnd());
136        assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart());
137        assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText()));
138        assertTrue(info2.isInsertionMarkerClipped());
139        assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal());
140        assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop());
141        assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline());
142        assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom());
143        assertEquals(TRANSFORM_MATRIX, info2.getMatrix());
144        for (int i = 0; i < MANY_RECTS.length; i++) {
145            final RectF expectedRect = MANY_RECTS[i];
146            assertEquals(expectedRect, info2.getCharacterRect(i));
147        }
148        assertNull(info2.getCharacterRect(-1));
149        assertNull(info2.getCharacterRect(MANY_RECTS.length + 1));
150        for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
151            final int expectedFlags = MANY_FLAGS_ARRAY[i];
152            assertEquals(expectedFlags, info2.getCharacterRectFlags(i));
153        }
154        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info2.getCharacterRectFlags(-1));
155        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
156                info2.getCharacterRectFlags(MANY_RECTS.length + 1));
157        assertEquals(info, info2);
158        assertEquals(info.hashCode(), info2.hashCode());
159
160        // Make sure that object can be marshaled via {@link Parsel}.
161        final CursorAnchorInfo info3 = cloneViaParcel(info2);
162        assertEquals(SELECTION_START, info3.getSelectionStart());
163        assertEquals(SELECTION_END, info3.getSelectionEnd());
164        assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart());
165        assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText()));
166        assertTrue(info3.isInsertionMarkerClipped());
167        assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal());
168        assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop());
169        assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline());
170        assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom());
171        assertEquals(TRANSFORM_MATRIX, info3.getMatrix());
172        for (int i = 0; i < MANY_RECTS.length; i++) {
173            final RectF expectedRect = MANY_RECTS[i];
174            assertEquals(expectedRect, info3.getCharacterRect(i));
175        }
176        assertNull(info3.getCharacterRect(-1));
177        assertNull(info3.getCharacterRect(MANY_RECTS.length + 1));
178        for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
179            final int expectedFlags = MANY_FLAGS_ARRAY[i];
180            assertEquals(expectedFlags, info3.getCharacterRectFlags(i));
181        }
182        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info3.getCharacterRectFlags(-1));
183        assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
184                info3.getCharacterRectFlags(MANY_RECTS.length + 1));
185        assertEquals(info.hashCode(), info3.hashCode());
186
187        builder.reset();
188        final CursorAnchorInfo uninitializedInfo = builder.build();
189        assertEquals(-1, uninitializedInfo.getSelectionStart());
190        assertEquals(-1, uninitializedInfo.getSelectionEnd());
191        assertEquals(-1, uninitializedInfo.getComposingTextStart());
192        assertNull(uninitializedInfo.getComposingText());
193        assertFalse(uninitializedInfo.isInsertionMarkerClipped());
194        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal());
195        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop());
196        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline());
197        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBottom());
198        assertEquals(Matrix.IDENTITY_MATRIX, uninitializedInfo.getMatrix());
199    }
200
201    private static void assertNotEquals(final CursorAnchorInfo reference,
202            final CursorAnchorInfo actual) {
203        assertFalse(Objects.equals(reference, actual));
204    }
205
206    @SmallTest
207    public void testEquality() throws Exception {
208        final Matrix MATRIX1 = new Matrix();
209        MATRIX1.setTranslate(10.0f, 20.0f);
210        final Matrix MATRIX2 = new Matrix();
211        MATRIX2.setTranslate(110.0f, 120.0f);
212        final Matrix NAN_MATRIX = new Matrix();
213        NAN_MATRIX.setValues(new float[]{
214                Float.NaN, Float.NaN, Float.NaN,
215                Float.NaN, Float.NaN, Float.NaN,
216                Float.NaN, Float.NaN, Float.NaN});
217        final int SELECTION_START1 = 2;
218        final int SELECTION_END1 = 7;
219        final String COMPOSING_TEXT1 = "0123456789";
220        final int COMPOSING_TEXT_START1 = 0;
221        final boolean INSERTION_MARKER_CLIPPED1 = true;
222        final float INSERTION_MARKER_HORIZONTAL1 = 10.5f;
223        final float INSERTION_MARKER_TOP1 = 100.1f;
224        final float INSERTION_MARKER_BASELINE1 = 110.4f;
225        final float INSERTION_MARKER_BOTOM1 = 111.0f;
226        final int SELECTION_START2 = 4;
227        final int SELECTION_END2 = 8;
228        final String COMPOSING_TEXT2 = "9876543210";
229        final int COMPOSING_TEXT_START2 = 3;
230        final boolean INSERTION_MARKER_CLIPPED2 = false;
231        final float INSERTION_MARKER_HORIZONTAL2 = 14.5f;
232        final float INSERTION_MARKER_TOP2 = 200.1f;
233        final float INSERTION_MARKER_BASELINE2 = 210.4f;
234        final float INSERTION_MARKER_BOTOM2 = 211.0f;
235
236        // Default instance should be equal.
237        assertEquals(new Builder().build(), new Builder().build());
238
239        assertEquals(
240                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
241                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build());
242        assertNotEquals(
243                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
244                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END2).build());
245        assertNotEquals(
246                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
247                new Builder().setSelectionRange(SELECTION_START2, SELECTION_END1).build());
248        assertNotEquals(
249                new Builder().setSelectionRange(SELECTION_START1, SELECTION_END1).build(),
250                new Builder().setSelectionRange(SELECTION_START2, SELECTION_END2).build());
251        assertEquals(
252                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
253                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build());
254        assertNotEquals(
255                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
256                new Builder().setComposingText(COMPOSING_TEXT_START2, COMPOSING_TEXT1).build());
257        assertNotEquals(
258                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
259                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT2).build());
260        assertNotEquals(
261                new Builder().setComposingText(COMPOSING_TEXT_START1, COMPOSING_TEXT1).build(),
262                new Builder().setComposingText(COMPOSING_TEXT_START2, COMPOSING_TEXT2).build());
263
264        // For insertion marker locations, {@link Float#NaN} is treated as if it was a number.
265        assertEquals(
266                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
267                        Float.NaN, Float.NaN, Float.NaN, Float.NaN,
268                        INSERTION_MARKER_CLIPPED1).build(),
269                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
270                        Float.NaN, Float.NaN, Float.NaN, Float.NaN,
271                        INSERTION_MARKER_CLIPPED1).build());
272
273        // Check Matrix.
274        assertEquals(
275                new Builder().setMatrix(MATRIX1).build(),
276                new Builder().setMatrix(MATRIX1).build());
277        assertNotEquals(
278                new Builder().setMatrix(MATRIX1).build(),
279                new Builder().setMatrix(MATRIX2).build());
280        assertNotEquals(
281                new Builder().setMatrix(MATRIX1).build(),
282                new Builder().setMatrix(NAN_MATRIX).build());
283        // Unlike insertion marker locations, {@link Float#NaN} in the matrix is treated as just a
284        // NaN as usual (NaN == NaN -> false).
285        assertNotEquals(
286                new Builder().setMatrix(NAN_MATRIX).build(),
287                new Builder().setMatrix(NAN_MATRIX).build());
288
289        assertEquals(
290                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
291                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
292                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
293                        INSERTION_MARKER_CLIPPED1).build(),
294                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
295                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
296                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
297                        INSERTION_MARKER_CLIPPED1).build());
298        assertNotEquals(
299                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
300                        Float.NaN, INSERTION_MARKER_TOP1,
301                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
302                        INSERTION_MARKER_CLIPPED1).build(),
303                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
304                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
305                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
306                        INSERTION_MARKER_CLIPPED1).build());
307        assertNotEquals(
308                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
309                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
310                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
311                        INSERTION_MARKER_CLIPPED1).build(),
312                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
313                        INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
314                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
315                        INSERTION_MARKER_CLIPPED1).build());
316        assertNotEquals(
317                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
318                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
319                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
320                        INSERTION_MARKER_CLIPPED1).build(),
321                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
322                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2,
323                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
324                        INSERTION_MARKER_CLIPPED1).build());
325        assertNotEquals(
326                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
327                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
328                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
329                        INSERTION_MARKER_CLIPPED1).build(),
330                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
331                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
332                        INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1,
333                        INSERTION_MARKER_CLIPPED1).build());
334        assertNotEquals(
335                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
336                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
337                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
338                        INSERTION_MARKER_CLIPPED1).build(),
339                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
340                        INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
341                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
342                        INSERTION_MARKER_CLIPPED1).build());
343        assertNotEquals(
344                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
345                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
346                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
347                        INSERTION_MARKER_CLIPPED1).build(),
348                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
349                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
350                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2,
351                        INSERTION_MARKER_CLIPPED1).build());
352        assertNotEquals(
353                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
354                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
355                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
356                        INSERTION_MARKER_CLIPPED1).build(),
357                new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
358                        INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
359                        INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
360                        INSERTION_MARKER_CLIPPED2).build());
361    }
362
363    @SmallTest
364    public void testMatrixIsCopied() throws Exception {
365        final Matrix MATRIX1 = new Matrix();
366        MATRIX1.setTranslate(10.0f, 20.0f);
367        final Matrix MATRIX2 = new Matrix();
368        MATRIX2.setTranslate(110.0f, 120.0f);
369        final Matrix MATRIX3 = new Matrix();
370        MATRIX3.setTranslate(210.0f, 220.0f);
371        final Matrix matrix = new Matrix();
372        final Builder builder = new Builder();
373
374        matrix.set(MATRIX1);
375        builder.setMatrix(matrix);
376        matrix.postRotate(90.0f);
377
378        final CursorAnchorInfo firstInstance = builder.build();
379        assertEquals(MATRIX1, firstInstance.getMatrix());
380        matrix.set(MATRIX2);
381        builder.setMatrix(matrix);
382        final CursorAnchorInfo secondInstance = builder.build();
383        assertEquals(MATRIX1, firstInstance.getMatrix());
384        assertEquals(MATRIX2, secondInstance.getMatrix());
385
386        matrix.set(MATRIX3);
387        assertEquals(MATRIX1, firstInstance.getMatrix());
388        assertEquals(MATRIX2, secondInstance.getMatrix());
389    }
390
391    @SmallTest
392    public void testMatrixIsRequired() throws Exception {
393        final int SELECTION_START = 30;
394        final int SELECTION_END = 40;
395        final int COMPOSING_TEXT_START = 32;
396        final String COMPOSING_TEXT = "test";
397        final boolean INSERTION_MARKER_CLIPPED = true;
398        final float INSERTION_MARKER_HORIZONTAL = 10.5f;
399        final float INSERTION_MARKER_TOP = 100.1f;
400        final float INSERTION_MARKER_BASELINE = 110.4f;
401        final float INSERTION_MARKER_BOTOM = 111.0f;
402        Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
403        TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
404
405        final Builder builder = new Builder();
406        // Check twice to make sure if Builder#reset() works as expected.
407        for (int repeatCount = 0; repeatCount < 2; ++repeatCount) {
408            builder.setSelectionRange(SELECTION_START, SELECTION_END)
409                    .setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT);
410            try {
411                // Should succeed as coordinate transformation matrix is not required if no
412                // positional information is specified.
413                builder.build();
414            } catch (IllegalArgumentException ex) {
415                assertTrue(false);
416            }
417
418            builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
419                    INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_CLIPPED);
420            try {
421                // Coordinate transformation matrix is required if no positional information is
422                // specified.
423                builder.build();
424                assertTrue(false);
425            } catch (IllegalArgumentException ex) {
426            }
427
428            builder.setMatrix(TRANSFORM_MATRIX);
429            try {
430                // Should succeed as coordinate transformation matrix is required.
431                builder.build();
432            } catch (IllegalArgumentException ex) {
433                assertTrue(false);
434            }
435
436            builder.reset();
437        }
438    }
439
440    @SmallTest
441    public void testBuilderAddCharacterRect() throws Exception {
442        // A negative index should be rejected.
443        try {
444            new Builder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f,
445                    CHARACTER_RECT_TYPE_FULLY_VISIBLE);
446            assertTrue(false);
447        } catch (IllegalArgumentException ex) {
448        }
449
450        // CHARACTER_RECT_TYPE_UNSPECIFIED is not allowed.
451        try {
452            new Builder().addCharacterRect(0, 0.0f, 0.0f, 0.0f, 0.0f,
453                    CHARACTER_RECT_TYPE_UNSPECIFIED);
454            assertTrue(false);
455        } catch (IllegalArgumentException ex) {
456        }
457    }
458
459    private static CursorAnchorInfo cloneViaParcel(final CursorAnchorInfo src) {
460        Parcel parcel = null;
461        try {
462            parcel = Parcel.obtain();
463            src.writeToParcel(parcel, 0);
464            parcel.setDataPosition(0);
465            return new CursorAnchorInfo(parcel);
466        } finally {
467            if (parcel != null) {
468                parcel.recycle();
469            }
470        }
471    }
472}
473