Cleanup action key label unit tests

Change-Id: Iae08ef5689235310ad59035f4f19c6d631ca0602
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java
index a25d6d6..17cee29 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelBase.java
@@ -16,12 +16,14 @@
 
 package com.android.inputmethod.keyboard;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.text.InputType;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyVisual;
 import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.utils.RunInLocale;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -29,28 +31,70 @@
 import java.util.Locale;
 
 abstract class KeyboardLayoutSetActionLabelBase extends KeyboardLayoutSetTestsBase {
+    static class ExpectedActionKey {
+        static ExpectedActionKey newIconKey(final String iconName) {
+            final int iconId = KeyboardIconsSet.getIconId(iconName);
+            return new ExpectedActionKey(ExpectedKeyVisual.newInstance(iconId));
+        }
+
+        static ExpectedActionKey newLabelKey(final String label) {
+            return new ExpectedActionKey(ExpectedKeyVisual.newInstance(label));
+        }
+
+        static ExpectedActionKey newLabelKey(final int labelResId,
+                final Locale labelLocale, final Context context) {
+            final RunInLocale<String> getString = new RunInLocale<String>() {
+                @Override
+                protected String job(final Resources res) {
+                    return res.getString(labelResId);
+                }
+            };
+            return newLabelKey(getString.runInLocale(context.getResources(), labelLocale));
+        }
+
+        private final ExpectedKeyVisual mVisual;
+
+        private ExpectedActionKey(final ExpectedKeyVisual visual) {
+            mVisual = visual;
+        }
+
+        public int getIconId() { return mVisual.getIconId(); }
+
+        public String getLabel() { return mVisual.getLabel(); }
+    }
+
+    protected static Locale getLabelLocale(final InputMethodSubtype subtype) {
+        if (subtype.getLocale().equals(SubtypeLocaleUtils.NO_LANGUAGE)) {
+            return null;
+        }
+        return SubtypeLocaleUtils.getSubtypeLocale(subtype);
+    }
+
     public void testActionUnspecified() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "unspecifiled "
                     + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_UNSPECIFIED,
-                    KeyboardIconsSet.NAME_ENTER_KEY);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_UNSPECIFIED, expectedKey);
         }
     }
 
     public void testActionNone() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "none " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_NONE,
-                    KeyboardIconsSet.NAME_ENTER_KEY);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_NONE, expectedKey);
         }
     }
 
     public void testActionSearch() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_SEARCH_KEY);
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "search " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_SEARCH,
-                    KeyboardIconsSet.NAME_SEARCH_KEY);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_SEARCH, expectedKey);
         }
     }
 
@@ -63,94 +107,47 @@
     public void testActionCustom() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "custom " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            final CharSequence customLabel = "customLabel";
             final EditorInfo editorInfo = new EditorInfo();
             editorInfo.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED;
-            editorInfo.actionLabel = customLabel;
-            doTestActionKeyLabel(tag, subtype, editorInfo, customLabel);
+            editorInfo.actionLabel = "customLabel";
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey("customLabel");
+            doTestActionKey(tag, subtype, editorInfo, expectedKey);
         }
     }
 
-    private static void doTestActionKey(final String tag, final KeyboardLayoutSet layoutSet,
-            final int elementId, final CharSequence label, final int iconId) {
+    private static void assertActionKey(final String tag, final KeyboardLayoutSet layoutSet,
+            final int elementId, final ExpectedActionKey expectedKey) {
         final Keyboard keyboard = layoutSet.getKeyboard(elementId);
-        final Key enterKey = keyboard.getKey(Constants.CODE_ENTER);
-        assertNotNull(tag + " enter key on " + keyboard.mId, enterKey);
-        assertEquals(tag + " enter label " + enterKey, label, enterKey.getLabel());
-        assertEquals(tag + " enter icon " + enterKey, iconId, enterKey.getIconId());
+        final Key actualKey = keyboard.getKey(Constants.CODE_ENTER);
+        assertNotNull(tag + " enter key on " + keyboard.mId, actualKey);
+        assertEquals(tag + " label " + expectedKey, expectedKey.getLabel(), actualKey.getLabel());
+        assertEquals(tag + " icon " + expectedKey, expectedKey.getIconId(), actualKey.getIconId());
     }
 
-    protected void doTestActionKeyLabelResId(final String tag, final InputMethodSubtype subtype,
-            final int actionId, final int labelResId) {
-        final Locale labelLocale = subtype.getLocale().equals(SubtypeLocaleUtils.NO_LANGUAGE)
-                ? null : SubtypeLocaleUtils.getSubtypeLocale(subtype);
-        doTestActionKeyLabelResIdInLocale(tag, subtype, actionId, labelLocale, labelResId);
-    }
-
-    protected void doTestActionKeyLabelResIdInLocale(final String tag,
-            final InputMethodSubtype subtype, final int actionId, final Locale labelLocale,
-            final int labelResId) {
+    protected void doTestActionKey(final String tag, final InputMethodSubtype subtype,
+            final int actionId, final ExpectedActionKey expectedKey) {
         final EditorInfo editorInfo = new EditorInfo();
         editorInfo.imeOptions = actionId;
-        final RunInLocale<String> job = new RunInLocale<String>() {
-            @Override
-            protected String job(final Resources res) {
-                return res.getString(labelResId);
-            }
-        };
-        final String label = job.runInLocale(getContext().getResources(), labelLocale);
-        doTestActionKeyLabel(tag, subtype, editorInfo, label);
+        doTestActionKey(tag, subtype, editorInfo, expectedKey);
     }
 
-    protected void doTestActionKeyLabel(final String tag, final InputMethodSubtype subtype,
-            final EditorInfo editorInfo, final CharSequence label) {
+    protected void doTestActionKey(final String tag, final InputMethodSubtype subtype,
+            final EditorInfo editorInfo, final ExpectedActionKey expectedKey) {
         // Test text layouts.
         editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
         final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET, expectedKey);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS, expectedKey);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED, expectedKey);
         // Test phone number layouts.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE, expectedKey);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS, expectedKey);
         // Test normal number layout.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-        // Test number password layouts.
-        editorInfo.inputType =
-                InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
-        final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER,
-                label, KeyboardIconsSet.ICON_UNDEFINED);
-    }
-
-    protected void doTestActionKeyIcon(final String tag, final InputMethodSubtype subtype,
-            final int actionId, final String iconName) {
-        final int iconId = KeyboardIconsSet.getIconId(iconName);
-        final EditorInfo editorInfo = new EditorInfo();
-        editorInfo.imeOptions = actionId;
-        // Test text layouts.
-        editorInfo.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
-        final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_ALPHABET, null /* label */, iconId);
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS, null /* label */, iconId);
-        doTestActionKey(
-                tag, layoutSet, KeyboardId.ELEMENT_SYMBOLS_SHIFTED, null /* label */, iconId);
-        // Test phone number layouts.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_PHONE, null /* label */, iconId);
-        doTestActionKey(
-                tag, layoutSet, KeyboardId.ELEMENT_PHONE_SYMBOLS, null /* label */, iconId);
-        // Test normal number layout.
-        doTestActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
+        assertActionKey(tag, layoutSet, KeyboardId.ELEMENT_NUMBER, expectedKey);
         // Test number password layout.
         editorInfo.inputType =
                 InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
         final KeyboardLayoutSet passwordSet = createKeyboardLayoutSet(subtype, editorInfo);
-        doTestActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER, null /* label */, iconId);
+        assertActionKey(tag, passwordSet, KeyboardId.ELEMENT_NUMBER, expectedKey);
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java
index 322a344..07d4705 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelKlpTests.java
@@ -40,8 +40,9 @@
     public void testActionGo() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_GO,
-                    R.string.label_go_key);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_go_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_GO, expectedKey);
         }
     }
 
@@ -49,8 +50,9 @@
     public void testActionSend() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_SEND,
-                    R.string.label_send_key);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_send_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_SEND, expectedKey);
         }
     }
 
@@ -58,8 +60,9 @@
     public void testActionNext() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_NEXT,
-                    R.string.label_next_key);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_next_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_NEXT, expectedKey);
         }
     }
 
@@ -67,8 +70,9 @@
     public void testActionDone() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_DONE,
-                    R.string.label_done_key);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_done_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_DONE, expectedKey);
         }
     }
 
@@ -76,42 +80,59 @@
     public void testActionPrevious() {
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyLabelResId(tag, subtype, EditorInfo.IME_ACTION_PREVIOUS,
-                    R.string.label_previous_key);
+            final ExpectedActionKey expectedKey = ExpectedActionKey.newLabelKey(
+                    R.string.label_previous_key, getLabelLocale(subtype), getContext());
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_PREVIOUS, expectedKey);
         }
     }
 
+    private void doTestActionKeys(final InputMethodSubtype subtype, final String tag,
+            final ExpectedActionKey unspecifiedKey, final ExpectedActionKey noneKey,
+            final ExpectedActionKey goKey, final ExpectedActionKey searchKey,
+            final ExpectedActionKey sendKey, final ExpectedActionKey nextKey,
+            final ExpectedActionKey doneKey, final ExpectedActionKey previousKey) {
+        doTestActionKey(
+                tag + " unspecified", subtype, EditorInfo.IME_ACTION_UNSPECIFIED, unspecifiedKey);
+        doTestActionKey(tag + " none", subtype, EditorInfo.IME_ACTION_NONE, noneKey);
+        doTestActionKey(tag + " go", subtype, EditorInfo.IME_ACTION_GO, goKey);
+        doTestActionKey(tag + " search", subtype, EditorInfo.IME_ACTION_SEARCH, searchKey);
+        doTestActionKey(tag + " send", subtype, EditorInfo.IME_ACTION_SEND, sendKey);
+        doTestActionKey(tag + " next", subtype, EditorInfo.IME_ACTION_NEXT, nextKey);
+        doTestActionKey(tag + " done", subtype, EditorInfo.IME_ACTION_DONE, doneKey);
+        doTestActionKey(tag + " previous", subtype, EditorInfo.IME_ACTION_PREVIOUS, previousKey);
+    }
+
     // Working variable to simulate system locale changing.
     private Locale mSystemLocale = Locale.getDefault();
 
-    private void doTestActionLabelInLocale(final InputMethodSubtype subtype,
+    private void doTestActionKeysInLocale(final InputMethodSubtype subtype,
             final Locale labelLocale, final Locale systemLocale) {
         // Simulate system locale changing, see {@link SystemBroadcastReceiver}.
         if (!systemLocale.equals(mSystemLocale)) {
             KeyboardLayoutSet.onSystemLocaleChanged();
             mSystemLocale = systemLocale;
         }
+        final ExpectedActionKey enterKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_ENTER_KEY);
+        final ExpectedActionKey goKey = ExpectedActionKey.newLabelKey(
+                R.string.label_go_key, labelLocale, getContext());
+        final ExpectedActionKey searchKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_SEARCH_KEY);
+        final ExpectedActionKey sendKey = ExpectedActionKey.newLabelKey(
+                R.string.label_send_key, labelLocale, getContext());
+        final ExpectedActionKey nextKey = ExpectedActionKey.newLabelKey(
+                R.string.label_next_key, labelLocale, getContext());
+        final ExpectedActionKey doneKey = ExpectedActionKey.newLabelKey(
+                R.string.label_done_key, labelLocale, getContext());
+        final ExpectedActionKey previousKey = ExpectedActionKey.newLabelKey(
+                R.string.label_previous_key, labelLocale, getContext());
         final String tag = "label=" + labelLocale + " system=" + systemLocale
                 + " " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
         final RunInLocale<Void> job = new RunInLocale<Void>() {
             @Override
             public Void job(final Resources res) {
-                doTestActionKeyIcon(tag + " unspecified", subtype,
-                        EditorInfo.IME_ACTION_UNSPECIFIED, KeyboardIconsSet.NAME_ENTER_KEY);
-                doTestActionKeyIcon(tag + " none", subtype,
-                        EditorInfo.IME_ACTION_NONE, KeyboardIconsSet.NAME_ENTER_KEY);
-                doTestActionKeyLabelResIdInLocale(tag + " go", subtype,
-                        EditorInfo.IME_ACTION_GO, labelLocale, R.string.label_go_key);
-                doTestActionKeyIcon(tag + " search", subtype,
-                        EditorInfo.IME_ACTION_SEARCH, KeyboardIconsSet.NAME_SEARCH_KEY);
-                doTestActionKeyLabelResIdInLocale(tag + " send", subtype,
-                        EditorInfo.IME_ACTION_SEND, labelLocale, R.string.label_send_key);
-                doTestActionKeyLabelResIdInLocale(tag + " next", subtype,
-                        EditorInfo.IME_ACTION_NEXT, labelLocale, R.string.label_next_key);
-                doTestActionKeyLabelResIdInLocale(tag + " done", subtype,
-                        EditorInfo.IME_ACTION_DONE, labelLocale, R.string.label_done_key);
-                doTestActionKeyLabelResIdInLocale(tag + " previous", subtype,
-                        EditorInfo.IME_ACTION_PREVIOUS, labelLocale, R.string.label_previous_key);
+                doTestActionKeys(subtype, tag, enterKey, enterKey, goKey, searchKey, sendKey,
+                        nextKey, doneKey, previousKey);
                 return null;
             }
         };
@@ -123,10 +144,10 @@
         final InputMethodSubtype italian = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
                 Locale.ITALIAN.toString(), SubtypeLocaleUtils.QWERTY);
         // An action label should be displayed in subtype's locale regardless of the system locale.
-        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.US);
-        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.FRENCH);
-        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.ITALIAN);
-        doTestActionLabelInLocale(italian, Locale.ITALIAN, Locale.JAPANESE);
+        doTestActionKeysInLocale(italian, Locale.ITALIAN, Locale.US);
+        doTestActionKeysInLocale(italian, Locale.ITALIAN, Locale.FRENCH);
+        doTestActionKeysInLocale(italian, Locale.ITALIAN, Locale.ITALIAN);
+        doTestActionKeysInLocale(italian, Locale.ITALIAN, Locale.JAPANESE);
     }
 
     public void testNoLanguageSubtypeActionLabel() {
@@ -134,9 +155,9 @@
         final InputMethodSubtype noLanguage = richImm.findSubtypeByLocaleAndKeyboardLayoutSet(
                 SubtypeLocaleUtils.NO_LANGUAGE, SubtypeLocaleUtils.QWERTY);
         // An action label of no language keyboard should be displayed in the system locale.
-        doTestActionLabelInLocale(noLanguage, Locale.US, Locale.US);
-        doTestActionLabelInLocale(noLanguage, Locale.FRENCH, Locale.FRENCH);
-        doTestActionLabelInLocale(noLanguage, Locale.ITALIAN, Locale.ITALIAN);
-        doTestActionLabelInLocale(noLanguage, Locale.JAPANESE, Locale.JAPANESE);
+        doTestActionKeysInLocale(noLanguage, Locale.US, Locale.US);
+        doTestActionKeysInLocale(noLanguage, Locale.FRENCH, Locale.FRENCH);
+        doTestActionKeysInLocale(noLanguage, Locale.ITALIAN, Locale.ITALIAN);
+        doTestActionKeysInLocale(noLanguage, Locale.JAPANESE, Locale.JAPANESE);
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java
index 028b3e4..fec501d 100644
--- a/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/KeyboardLayoutSetActionLabelLxxTests.java
@@ -32,46 +32,51 @@
 
     @Override
     public void testActionGo() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_GO_KEY);
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "go " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_GO,
-                    KeyboardIconsSet.NAME_GO_KEY);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_GO, expectedKey);
         }
     }
 
     @Override
     public void testActionSend() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_SEND_KEY);
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "send " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_SEND,
-                    KeyboardIconsSet.NAME_SEND_KEY);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_SEND, expectedKey);
         }
     }
 
     @Override
     public void testActionNext() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_NEXT_KEY);
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "next " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_NEXT,
-                    KeyboardIconsSet.NAME_NEXT_KEY);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_NEXT, expectedKey);
         }
     }
 
     @Override
     public void testActionDone() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_DONE_KEY);
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "done " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_DONE,
-                    KeyboardIconsSet.NAME_DONE_KEY);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_DONE, expectedKey);
         }
     }
 
     @Override
     public void testActionPrevious() {
+        final ExpectedActionKey expectedKey = ExpectedActionKey.newIconKey(
+                KeyboardIconsSet.NAME_PREVIOUS_KEY);
         for (final InputMethodSubtype subtype : getAllSubtypesList()) {
             final String tag = "previous " + SubtypeLocaleUtils.getSubtypeNameForLogging(subtype);
-            doTestActionKeyIcon(tag, subtype, EditorInfo.IME_ACTION_PREVIOUS,
-                    KeyboardIconsSet.NAME_PREVIOUS_KEY);
+            doTestActionKey(tag, subtype, EditorInfo.IME_ACTION_PREVIOUS, expectedKey);
         }
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKey.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKey.java
index 2674a6a..5c147a3 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKey.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKey.java
@@ -105,11 +105,11 @@
     // The expected output of this key.
     private final ExpectedKeyOutput mOutput;
 
-    public final ExpectedKeyVisual getVisual() {
+    protected final ExpectedKeyVisual getVisual() {
         return mVisual;
     }
 
-    public final ExpectedKeyOutput getOutput() {
+    protected final ExpectedKeyOutput getOutput() {
         return mOutput;
     }
 
@@ -162,18 +162,19 @@
 
     public boolean equalsTo(final Key key) {
         // This key has no "more keys".
-        return mVisual.equalsTo(key) && mOutput.equalsTo(key) && key.getMoreKeys() == null;
+        return mVisual.hasSameKeyVisual(key) && mOutput.hasSameKeyOutput(key)
+                && key.getMoreKeys() == null;
     }
 
     public boolean equalsTo(final MoreKeySpec moreKeySpec) {
-        return mVisual.equalsTo(moreKeySpec) && mOutput.equalsTo(moreKeySpec);
+        return mVisual.hasSameKeyVisual(moreKeySpec) && mOutput.hasSameKeyOutput(moreKeySpec);
     }
 
     @Override
     public boolean equals(final Object object) {
         if (object instanceof ExpectedKey) {
             final ExpectedKey key = (ExpectedKey) object;
-            return mVisual.equalsTo(key.mVisual) && mOutput.equalsTo(key.mOutput)
+            return mVisual.hasSameKeyVisual(key.mVisual) && mOutput.hasSameKeyOutput(key.mOutput)
                     && Arrays.equals(getMoreKeys(), key.getMoreKeys());
         }
         return false;
@@ -190,7 +191,7 @@
 
     @Override
     public String toString() {
-        if (mVisual.equalsTo(mOutput)) {
+        if (mVisual.hasSameKeyVisual(mOutput)) {
             return mVisual.toString();
         }
         return mVisual + "|" + mOutput;
@@ -274,7 +275,7 @@
 
         @Override
         public boolean equalsTo(final Key key) {
-            if (getVisual().equalsTo(key) && getOutput().equalsTo(key)) {
+            if (getVisual().hasSameKeyVisual(key) && getOutput().hasSameKeyOutput(key)) {
                 final MoreKeySpec[] moreKeySpecs = key.getMoreKeys();
                 final ExpectedKey[] moreKeys = getMoreKeys();
                 // This key should have at least one "more key".
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyOutput.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyOutput.java
index 737d169..5c1a70f 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyOutput.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyOutput.java
@@ -43,10 +43,10 @@
 
     abstract ExpectedKeyOutput toUpperCase(final Locale locale);
     abstract ExpectedKeyOutput preserveCase();
-    abstract boolean equalsTo(final String text);
-    abstract boolean equalsTo(final Key key);
-    abstract boolean equalsTo(final MoreKeySpec moreKeySpec);
-    abstract boolean equalsTo(final ExpectedKeyOutput output);
+    abstract boolean hasSameKeyOutput(final String text);
+    abstract boolean hasSameKeyOutput(final Key key);
+    abstract boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec);
+    abstract boolean hasSameKeyOutput(final ExpectedKeyOutput output);
 
     /**
      * This class represents an integer code point.
@@ -75,22 +75,22 @@
         }
 
         @Override
-        boolean equalsTo(final String text) {
+        boolean hasSameKeyOutput(final String text) {
             return StringUtils.codePointCount(text) == 1 && text.codePointAt(0) == mCode;
         }
 
         @Override
-        boolean equalsTo(final Key key) {
+        boolean hasSameKeyOutput(final Key key) {
             return mCode == key.getCode();
         }
 
         @Override
-        boolean equalsTo(final MoreKeySpec moreKeySpec) {
+        boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec) {
             return mCode == moreKeySpec.mCode;
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyOutput output) {
+        boolean hasSameKeyOutput(final ExpectedKeyOutput output) {
             return (output instanceof Code) && mCode == ((Code)output).mCode;
         }
 
@@ -130,24 +130,24 @@
         }
 
         @Override
-        boolean equalsTo(final String text) {
+        boolean hasSameKeyOutput(final String text) {
             return text.equals(text);
         }
 
         @Override
-        boolean equalsTo(final Key key) {
+        boolean hasSameKeyOutput(final Key key) {
             return key.getCode() == Constants.CODE_OUTPUT_TEXT
                     && mText.equals(key.getOutputText());
         }
 
         @Override
-        boolean equalsTo(final MoreKeySpec moreKeySpec) {
+        boolean hasSameKeyOutput(final MoreKeySpec moreKeySpec) {
             return moreKeySpec.mCode == Constants.CODE_OUTPUT_TEXT
                     && mText.equals(moreKeySpec.mOutputText);
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyOutput output) {
+        boolean hasSameKeyOutput(final ExpectedKeyOutput output) {
             return (output instanceof Text) && mText == ((Text)output).mText;
         }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyVisual.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyVisual.java
index facdf70..2f3a0c1 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyVisual.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyVisual.java
@@ -27,22 +27,24 @@
  *
  * There are two types of expected visual, an integer icon id and a string label.
  */
-abstract class ExpectedKeyVisual {
-    static ExpectedKeyVisual newInstance(final String label) {
+public abstract class ExpectedKeyVisual {
+    public static ExpectedKeyVisual newInstance(final String label) {
         return new Label(label);
     }
 
-    static ExpectedKeyVisual newInstance(final int iconId) {
+    public static ExpectedKeyVisual newInstance(final int iconId) {
         return new Icon(iconId);
     }
 
+    public abstract int getIconId();
+    public abstract String getLabel();
     abstract ExpectedKeyVisual toUpperCase(final Locale locale);
     abstract ExpectedKeyVisual preserveCase();
-    abstract boolean equalsTo(final String text);
-    abstract boolean equalsTo(final Key key);
-    abstract boolean equalsTo(final MoreKeySpec moreKeySpec);
-    abstract boolean equalsTo(final ExpectedKeyOutput output);
-    abstract boolean equalsTo(final ExpectedKeyVisual visual);
+    abstract boolean hasSameKeyVisual(final String text);
+    abstract boolean hasSameKeyVisual(final Key key);
+    abstract boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec);
+    abstract boolean hasSameKeyVisual(final ExpectedKeyOutput output);
+    abstract boolean hasSameKeyVisual(final ExpectedKeyVisual visual);
 
     /**
      * This class represents an integer icon id.
@@ -55,6 +57,16 @@
         }
 
         @Override
+        public int getIconId() {
+            return mIconId;
+        }
+
+        @Override
+        public String getLabel() {
+            return null;
+        }
+
+        @Override
         ExpectedKeyVisual toUpperCase(final Locale locale) {
             return this;
         }
@@ -65,27 +77,32 @@
         }
 
         @Override
-        boolean equalsTo(final String text) {
+        boolean hasSameKeyVisual(final String text) {
             return false;
         }
 
         @Override
-        boolean equalsTo(final Key key) {
-            return mIconId == key.getIconId();
+        boolean hasSameKeyVisual(final Key key) {
+            // If the actual key has an icon as its visual, a label has to be null.
+            // See {@link KeyboardView#onDrawKeyTopVisuals(Key,Canvas,Paint,KeyDrawParams).
+            return mIconId == key.getIconId() && key.getLabel() == null;
         }
 
         @Override
-        boolean equalsTo(final MoreKeySpec moreKeySpec) {
-            return mIconId == moreKeySpec.mIconId;
+        boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec) {
+            // If the actual more key has an icon as its visual, a label has to be null.
+            // See {@link KeySpecParser#getIconId(String)} and
+            // {@link KeySpecParser#getLabel(String)}.
+            return mIconId == moreKeySpec.mIconId && moreKeySpec.mLabel == null;
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyOutput output) {
+        boolean hasSameKeyVisual(final ExpectedKeyOutput output) {
             return false;
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyVisual visual) {
+        boolean hasSameKeyVisual(final ExpectedKeyVisual visual) {
             return (visual instanceof Icon) && mIconId == ((Icon)visual).mIconId;
         }
 
@@ -101,7 +118,19 @@
     private static class Label extends ExpectedKeyVisual {
         private final String mLabel;
 
-        Label(final String label) { mLabel = label; }
+        Label(final String label) {
+            mLabel = label;
+        }
+
+        @Override
+        public int getIconId() {
+            return KeyboardIconsSet.ICON_UNDEFINED;
+        }
+
+        @Override
+        public String getLabel() {
+            return mLabel;
+        }
 
         @Override
         ExpectedKeyVisual toUpperCase(final Locale locale) {
@@ -114,27 +143,34 @@
         }
 
         @Override
-        boolean equalsTo(final String text) {
+        boolean hasSameKeyVisual(final String text) {
             return mLabel.equals(text);
         }
 
         @Override
-        boolean equalsTo(final Key key) {
-            return mLabel.equals(key.getLabel());
+        boolean hasSameKeyVisual(final Key key) {
+            // If the actual key has a label as its visual, an icon has to be undefined.
+            // See {@link KeyboardView#onDrawKeyTopVisuals(Key,Canvas,Paint,KeyDrawParams).
+            return mLabel.equals(key.getLabel())
+                    && key.getIconId() == KeyboardIconsSet.ICON_UNDEFINED;
         }
 
         @Override
-        boolean equalsTo(final MoreKeySpec moreKeySpec) {
-            return mLabel.equals(moreKeySpec.mLabel);
+        boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec) {
+            // If the actual more key has a label as its visual, an icon has to be undefined.
+            // See {@link KeySpecParser#getIconId(String)} and
+            // {@link KeySpecParser#getLabel(String)}.
+            return mLabel.equals(moreKeySpec.mLabel)
+                    && moreKeySpec.mIconId == KeyboardIconsSet.ICON_UNDEFINED;
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyOutput output) {
-            return output.equalsTo(mLabel);
+        boolean hasSameKeyVisual(final ExpectedKeyOutput output) {
+            return output.hasSameKeyOutput(mLabel);
         }
 
         @Override
-        boolean equalsTo(final ExpectedKeyVisual visual) {
+        boolean hasSameKeyVisual(final ExpectedKeyVisual visual) {
             return (visual instanceof Label) && mLabel.equals(((Label)visual).mLabel);
         }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
index 9b7de88..f5531c9 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/expected/ExpectedKeyboardBuilder.java
@@ -91,7 +91,7 @@
             ExpectedKey[] keys = getRowAt(row);
             for (int columnIndex = 0; columnIndex < keys.length; /* nothing */) {
                 final ExpectedKey currentKey = keys[columnIndex];
-                if (!currentKey.getVisual().equalsTo(visual)) {
+                if (!currentKey.getVisual().hasSameKeyVisual(visual)) {
                     columnIndex++;
                     continue;
                 }