am 8fff6ae6: Merge "Add the first gesture unit tests."

* commit '8fff6ae68b3c2e31687370fc867d3b6098938be7':
  Add the first gesture unit tests.
diff --git a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
index 30b0881..ae5cc5c 100644
--- a/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
+++ b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java
@@ -28,7 +28,7 @@
         final int EXPECTED_SPAN_START = 0;
         final int EXPECTED_SPAN_END = 4;
         type(STRING_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
         assertEquals("show blue underline, span start", EXPECTED_SPAN_START, span.mStart);
@@ -42,7 +42,7 @@
         final int EXPECTED_SPAN_START = 0;
         final int EXPECTED_SPAN_END = 5;
         type(STRING_1_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         type(STRING_2_TO_TYPE);
         // We haven't have time to look into the dictionary yet, so the line should still be
@@ -51,7 +51,7 @@
         assertEquals("extend blue underline, span start", EXPECTED_SPAN_START, spanBefore.mStart);
         assertEquals("extend blue underline, span end", EXPECTED_SPAN_END, spanBefore.mEnd);
         assertTrue("extend blue underline, span color", spanBefore.isAutoCorrectionIndicator());
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         // Now we have been able to re-evaluate the word, there shouldn't be an auto-correction span
         final SpanGetter spanAfter = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
@@ -65,18 +65,18 @@
         final int EXPECTED_UNDERLINE_SPAN_START = 0;
         final int EXPECTED_UNDERLINE_SPAN_END = 3;
         type(STRING_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         type(Constants.CODE_SPACE);
         // typedLength + 1 because we also typed a space
         mLatinIME.onUpdateSelection(0, 0, typedLength + 1, typedLength + 1, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         type(Constants.CODE_DELETE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         type(Constants.CODE_DELETE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         final SpanGetter suggestionSpan = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
         assertFalse("show no blue underline after backspace, span should not be the auto-"
@@ -93,7 +93,7 @@
         final int typedLength = STRING_TO_TYPE.length();
         final int NEW_CURSOR_POSITION = 0;
         type(STRING_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         // Simulate the onUpdateSelection() event
         mLatinIME.onUpdateSelection(0, 0, typedLength, typedLength, -1, -1);
         runMessages();
@@ -103,7 +103,7 @@
         mInputConnection.setSelection(NEW_CURSOR_POSITION, NEW_CURSOR_POSITION);
         mLatinIME.onUpdateSelection(typedLength, typedLength,
                 NEW_CURSOR_POSITION, NEW_CURSOR_POSITION, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
         assertFalse("blue underline removed when cursor is moved",
@@ -113,7 +113,7 @@
     public void testComposingStopsOnSpace() {
         final String STRING_TO_TYPE = "this ";
         type(STRING_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         // Simulate the onUpdateSelection() event
         mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
         runMessages();
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index ec249da..99dc9a2 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin;
 
+import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.text.TextUtils;
 import android.view.inputmethod.BaseInputConnection;
@@ -487,7 +488,7 @@
     public void testPredictionsAfterSpace() {
         final String WORD_TO_TYPE = "Barack ";
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Test the first prediction is displayed
         final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -499,17 +500,17 @@
         mLatinIME.clearPersonalizedDictionariesForTest();
         final String WORD_TO_TYPE = "Barack ";
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // No need to test here, testPredictionsAfterSpace is testing it already
         type(" ");
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Test the predictions have been cleared
         SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
         assertEquals("predictions cleared after double-space-to-period", suggestedWords.size(), 0);
         type(Constants.CODE_DELETE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Test the first prediction is displayed
         suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -522,7 +523,7 @@
         type(WORD_TO_TYPE);
         // Choose the auto-correction. For "Barack", the auto-correction should be "Barack".
         pickSuggestionManually(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Test the first prediction is displayed
         final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -534,13 +535,13 @@
         mLatinIME.clearPersonalizedDictionariesForTest();
         final String WORD_TO_TYPE = "Barack. ";
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
         assertEquals("No prediction after period after inputting once.", 0, suggestedWords.size());
 
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         suggestedWords = mLatinIME.getSuggestedWordsForTest();
         assertEquals("Beginning-of-Sentence prediction after inputting 2 times.", "Barack",
@@ -565,18 +566,18 @@
         type(" ");
         mLatinIME.onUpdateSelection(endOfSuggestion, endOfSuggestion,
                 endOfSuggestion + 1, endOfSuggestion + 1, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Simulate a manual cursor move
         mInputConnection.setSelection(indexForManualCursor, indexForManualCursor);
         mLatinIME.onUpdateSelection(endOfSuggestion + 1, endOfSuggestion + 1,
                 indexForManualCursor, indexForManualCursor, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         pickSuggestionManually(WORD_TO_TYPE);
         mLatinIME.onUpdateSelection(indexForManualCursor, indexForManualCursor,
                 endOfWord, endOfWord, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Test the first prediction is displayed
         final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
@@ -624,7 +625,7 @@
 
         for (int i = 0; i < WORD_TO_TYPE.length(); ++i) {
             type(WORD_TO_TYPE.substring(i, i+1));
-            sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+            sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
             runMessages();
         }
         assertEquals("type many trailing single quotes one by one", EXPECTED_RESULT,
@@ -636,7 +637,7 @@
         final String EXPECTED_RESULT = WORD_TO_TYPE;
         for (int i = 0; i < WORD_TO_TYPE.length(); ++i) {
             type(WORD_TO_TYPE.substring(i, i+1));
-            sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+            sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
             runMessages();
         }
         assertEquals("type words letter by letter", EXPECTED_RESULT,
@@ -652,10 +653,30 @@
         changeLanguage("fr");
         runMessages();
         type(WORD_TO_TYPE_SECOND_PART);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
         final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
         assertEquals("Suggestions updated after switching languages",
                     EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(1) : null);
     }
+
+    public void testBasicGesture() {
+        gesture("this");
+        assertEquals("gesture \"this\"", "this", mEditText.getText().toString());
+    }
+
+    public void testGestureGesture() {
+        gesture("this");
+        gesture("is");
+        assertEquals("gesture \"this is\"", "this is", mEditText.getText().toString());
+    }
+
+    public void testGestureBackspaceGestureAgain() {
+        gesture("this");
+        type(Constants.CODE_DELETE);
+        assertEquals("gesture then backspace", "", mEditText.getText().toString());
+        gesture("this");
+        MoreAsserts.assertNotEqual("gesture twice the same thing", "this",
+                mEditText.getText().toString());
+    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
index 2560407..c16372a 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsLanguageWithoutSpaces.java
@@ -74,7 +74,7 @@
         mInputConnection.setSelection(CURSOR_POS, CURSOR_POS);
         mLatinIME.onUpdateSelection(typedLength, typedLength,
                 CURSOR_POS, CURSOR_POS, -1, -1);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         assertEquals("start composing inside text", -1,
                 BaseInputConnection.getComposingSpanStart(mEditText.getText()));
@@ -91,7 +91,7 @@
         final String WORD_TO_TYPE = "Barack ";
         changeKeyboardLocaleAndDictLocale("th", "en_US");
         type(WORD_TO_TYPE);
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         // Make sure there is no space
         assertEquals("predictions in lang without spaces", "Barack",
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
index 715d449..842b54f 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTestsNonEnglish.java
@@ -70,7 +70,7 @@
         try {
             changeLanguage("fr");
             type(WORD_TO_TYPE);
-            sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+            sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
             runMessages();
             assertTrue("type word then type space should display punctuation strip",
                     mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
@@ -95,7 +95,7 @@
         try {
             changeLanguage("fr");
             type(WORD_TO_TYPE);
-            sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+            sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
             runMessages();
             final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
             assertEquals("type word then type space yields predictions for French",
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index ee79424..dd900a2 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.graphics.Point;
 import android.os.Looper;
 import android.preference.PreferenceManager;
 import android.test.ServiceTestCase;
@@ -45,6 +46,7 @@
 import com.android.inputmethod.latin.settings.DebugSettings;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.utils.LocaleUtils;
+import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.Locale;
@@ -58,9 +60,11 @@
     private static final String DEFAULT_AUTO_CORRECTION_THRESHOLD = "1";
 
     // The message that sets the underline is posted with a 500 ms delay
-    protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 500;
+    protected static final int DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS = 500;
     // The message that sets predictions is posted with a 200 ms delay
-    protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS = 200;
+    protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS = 200;
+    // We wait for gesture computation for this delay
+    protected static final int DELAY_TO_WAIT_FOR_GESTURE_MILLIS = 200;
     private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 60;
 
     // Type for a test phony dictionary
@@ -217,7 +221,7 @@
         // Run messages to avoid the messages enqueued by startInputView() and its friends
         // to run on a later call and ruin things. We need to wait first because some of them
         // can be posted with a delay (notably,  MSG_RESUME_SUGGESTIONS)
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
     }
 
@@ -301,6 +305,47 @@
         }
     }
 
+    protected Point getXY(final int codePoint) {
+        final Key key = mKeyboard.getKey(codePoint);
+        if (key == null) {
+            throw new RuntimeException("Code point not on the keyboard");
+        } else {
+            return new Point(key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2);
+        }
+    }
+
+    protected void gesture(final String stringToGesture) {
+        if (StringUtils.codePointCount(stringToGesture) < 2) {
+            throw new RuntimeException("Can't gesture strings less than 2 chars long");
+        }
+
+        mLatinIME.onStartBatchInput();
+        final int startCodePoint = stringToGesture.codePointAt(0);
+        Point oldPoint = getXY(startCodePoint);
+        int timestamp = 0; // In milliseconds since the start of the gesture
+        final InputPointers pointers = new InputPointers(Constants.DEFAULT_GESTURE_POINTS_CAPACITY);
+        pointers.addPointer(oldPoint.x, oldPoint.y, 0 /* pointerId */, timestamp);
+
+        for (int i = Character.charCount(startCodePoint); i < stringToGesture.length();
+                i = stringToGesture.offsetByCodePoints(i, 1)) {
+            final Point newPoint = getXY(stringToGesture.codePointAt(i));
+            // Arbitrarily 0.5s between letters and 0.1 between events. Refine this later if needed.
+            final int STEPS = 5;
+            for (int j = 0; j < STEPS; ++j) {
+                timestamp += 100;
+                pointers.addPointer(oldPoint.x + ((newPoint.x - oldPoint.x) * j) / STEPS,
+                        oldPoint.y + ((newPoint.y - oldPoint.y) * j) / STEPS,
+                        0 /* pointerId */, timestamp);
+            }
+            oldPoint.x = newPoint.x;
+            oldPoint.y = newPoint.y;
+            mLatinIME.onUpdateBatchInput(pointers);
+        }
+        mLatinIME.onEndBatchInput(pointers);
+        sleep(DELAY_TO_WAIT_FOR_GESTURE_MILLIS);
+        runMessages();
+    }
+
     protected void waitForDictionariesToBeLoaded() {
         try {
             mLatinIME.waitForLoadingDictionaries(
diff --git a/tests/src/com/android/inputmethod/latin/PunctuationTests.java b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
index 64750fb..3537918 100644
--- a/tests/src/com/android/inputmethod/latin/PunctuationTests.java
+++ b/tests/src/com/android/inputmethod/latin/PunctuationTests.java
@@ -38,7 +38,7 @@
         try {
             mLatinIME.loadSettings();
             type(WORD_TO_TYPE);
-            sleep(DELAY_TO_WAIT_FOR_UNDERLINE);
+            sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
             runMessages();
             assertTrue("type word then type space should display punctuation strip",
                     mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
diff --git a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
index db3c9ba..8ba0174 100644
--- a/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
+++ b/tests/src/com/android/inputmethod/latin/ShiftModeTests.java
@@ -75,7 +75,7 @@
             repeatKey(Constants.CODE_DELETE);
         }
         assertFalse("Caps immediately after repeating Backspace a lot", isCapsModeAutoShifted());
-        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS);
+        sleep(DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS);
         runMessages();
         assertTrue("Caps after a while after repeating Backspace a lot", isCapsModeAutoShifted());
     }