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