1 /*
2  * Copyright (C) 2013 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 com.android.inputmethod.latin;
18 
19 import android.test.AndroidTestCase;
20 import android.test.suitebuilder.annotation.SmallTest;
21 
22 import com.android.inputmethod.latin.utils.CoordinateUtils;
23 import com.android.inputmethod.latin.utils.StringUtils;
24 
25 /**
26  * Unit tests for WordComposer.
27  */
28 @SmallTest
29 public class WordComposerTests extends AndroidTestCase {
testMoveCursor()30     public void testMoveCursor() {
31         final WordComposer wc = new WordComposer();
32         // BMP is the Basic Multilingual Plane, as defined by Unicode. This includes
33         // most characters for most scripts, including all Roman alphabet languages,
34         // CJK, Arabic, Hebrew. Notable exceptions include some emoji and some
35         // very rare Chinese ideograms. BMP characters can be encoded on 2 bytes
36         // in UTF-16, whereas those outside the BMP need 4 bytes.
37         // http://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane
38         final String STR_WITHIN_BMP = "abcdef";
39         final int[] CODEPOINTS_WITHIN_BMP = StringUtils.toCodePointArray(STR_WITHIN_BMP);
40         final int[] COORDINATES_WITHIN_BMP =
41                 CoordinateUtils.newCoordinateArray(CODEPOINTS_WITHIN_BMP.length,
42                         Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
43         wc.setComposingWord(CODEPOINTS_WITHIN_BMP, COORDINATES_WITHIN_BMP);
44         assertEquals(wc.size(), STR_WITHIN_BMP.codePointCount(0, STR_WITHIN_BMP.length()));
45         assertFalse(wc.isCursorFrontOrMiddleOfComposingWord());
46         wc.setCursorPositionWithinWord(2);
47         assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
48         // Move the cursor to after the 'd'
49         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(2));
50         assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
51         // Move the cursor to after the 'e'
52         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(1));
53         assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
54         assertEquals(wc.size(), 6);
55         // Move the cursor to after the 'f'
56         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(1));
57         assertFalse(wc.isCursorFrontOrMiddleOfComposingWord());
58         // Move the cursor past the end of the word
59         assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(1));
60         assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(15));
61         // Do what LatinIME does when the cursor is moved outside of the word,
62         // and check the behavior is correct.
63         wc.reset();
64 
65         // \uD861\uDED7 is ��, a character outside the BMP
66         final String STR_WITH_SUPPLEMENTARY_CHAR = "abcde\uD861\uDED7fgh";
67         final int[] CODEPOINTS_WITH_SUPPLEMENTARY_CHAR =
68                 StringUtils.toCodePointArray(STR_WITH_SUPPLEMENTARY_CHAR);
69         final int[] COORDINATES_WITH_SUPPLEMENTARY_CHAR =
70                 CoordinateUtils.newCoordinateArray(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR.length,
71                         Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
72         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
73                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
74         assertEquals(wc.size(), CODEPOINTS_WITH_SUPPLEMENTARY_CHAR.length);
75         assertFalse(wc.isCursorFrontOrMiddleOfComposingWord());
76         wc.setCursorPositionWithinWord(3);
77         assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
78         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(6));
79         assertTrue(wc.isCursorFrontOrMiddleOfComposingWord());
80         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(1));
81         assertFalse(wc.isCursorFrontOrMiddleOfComposingWord());
82 
83         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
84                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
85         wc.setCursorPositionWithinWord(3);
86         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(7));
87 
88         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
89                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
90         wc.setCursorPositionWithinWord(3);
91         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(7));
92 
93         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
94                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
95         wc.setCursorPositionWithinWord(3);
96         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(-3));
97         assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(-1));
98 
99 
100         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
101                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
102         wc.setCursorPositionWithinWord(3);
103         assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(-9));
104 
105         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
106                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
107         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(-10));
108 
109         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
110                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
111         assertFalse(wc.moveCursorByAndReturnIfInsideComposingWord(-11));
112 
113         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
114                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
115         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(0));
116 
117         wc.setComposingWord(CODEPOINTS_WITH_SUPPLEMENTARY_CHAR,
118                 COORDINATES_WITH_SUPPLEMENTARY_CHAR);
119         wc.setCursorPositionWithinWord(2);
120         assertTrue(wc.moveCursorByAndReturnIfInsideComposingWord(0));
121     }
122 }
123