From e855093f5513e46f7f2da6d99e74873ac4f1eeef Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 31 Jan 2014 15:58:14 +0900 Subject: Move some methods to MoreKeySpec class Change-Id: I025ed15e36ac3113db6a5fccefa0c87f016703fa --- .../keyboard/internal/KeySpecParserSplitTests.java | 439 -------------- .../keyboard/internal/KeySpecParserTests.java | 659 -------------------- .../keyboard/internal/MoreKeySpecSplitTests.java | 439 ++++++++++++++ .../keyboard/internal/MoreKeySpecTests.java | 662 +++++++++++++++++++++ 4 files changed, 1101 insertions(+), 1098 deletions(-) delete mode 100644 tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java delete mode 100644 tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java create mode 100644 tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecSplitTests.java create mode 100644 tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java (limited to 'tests/src') diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java deleted file mode 100644 index 7b7f1758c..000000000 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserSplitTests.java +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import android.app.Instrumentation; -import android.content.Context; -import android.content.res.Resources; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.MediumTest; - -import com.android.inputmethod.latin.utils.CollectionUtils; -import com.android.inputmethod.latin.utils.RunInLocale; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; - -@MediumTest -public class KeySpecParserSplitTests extends InstrumentationTestCase { - private static final Locale TEST_LOCALE = Locale.ENGLISH; - final KeyboardTextsSet mTextsSet = new KeyboardTextsSet(); - - @Override - protected void setUp() throws Exception { - super.setUp(); - - final Instrumentation instrumentation = getInstrumentation(); - final Context targetContext = instrumentation.getTargetContext(); - mTextsSet.setLanguage(TEST_LOCALE.getLanguage()); - new RunInLocale() { - @Override - protected Void job(final Resources res) { - mTextsSet.loadStringResources(targetContext); - return null; - } - }.runInLocale(targetContext.getResources(), TEST_LOCALE); - final String[] testResourceNames = getAllResourceIdNames( - com.android.inputmethod.latin.tests.R.string.class); - mTextsSet.loadStringResourcesInternal(instrumentation.getContext(), testResourceNames, - // This dummy raw resource is needed to be able to load string resources from a test - // APK successfully. - com.android.inputmethod.latin.tests.R.raw.dummy_resource_for_testing); - } - - private static String[] getAllResourceIdNames(final Class resourceIdClass) { - final ArrayList names = CollectionUtils.newArrayList(); - for (final Field field : resourceIdClass.getFields()) { - if (field.getType() == Integer.TYPE) { - names.add(field.getName()); - } - } - return names.toArray(new String[names.size()]); - } - - private static void assertArrayEquals(final String message, final T[] expected, - final T[] actual) { - if (expected == actual) { - return; - } - if (expected == null || actual == null) { - assertEquals(message, Arrays.toString(expected), Arrays.toString(actual)); - return; - } - if (expected.length != actual.length) { - assertEquals(message + " [length]", Arrays.toString(expected), Arrays.toString(actual)); - return; - } - for (int i = 0; i < expected.length; i++) { - final T e = expected[i]; - final T a = actual[i]; - if (e == a) { - continue; - } - assertEquals(message + " [" + i + "]", e, a); - } - } - - private void assertTextArray(final String message, final String value, - final String ... expectedArray) { - final String resolvedActual = mTextsSet.resolveTextReference(value); - final String[] actual = KeySpecParser.splitKeySpecs(resolvedActual); - final String[] expected = (expectedArray.length == 0) ? null : expectedArray; - assertArrayEquals(message, expected, actual); - } - - private void assertError(final String message, final String value, final String ... expected) { - try { - assertTextArray(message, value, expected); - fail(message); - } catch (Exception pcpe) { - // success. - } - } - - // \U001d11e: MUSICAL SYMBOL G CLEF - private static final String PAIR1 = "\ud834\udd1e"; - // \U001d122: MUSICAL SYMBOL F CLEF - private static final String PAIR2 = "\ud834\udd22"; - // \U002f8a6: CJK COMPATIBILITY IDEOGRAPH-2F8A6; variant character of \u6148. - private static final String PAIR3 = "\ud87e\udca6"; - private static final String SURROGATE1 = PAIR1 + PAIR2; - private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3; - - public void testResolveNullText() { - assertNull("resolve null", mTextsSet.resolveTextReference(null)); - } - - public void testResolveEmptyText() { - assertNull("resolve empty text", mTextsSet.resolveTextReference("!text/empty_string")); - } - - public void testSplitZero() { - assertTextArray("Empty string", ""); - assertTextArray("Empty entry", ","); - assertTextArray("Empty entry at beginning", ",a", "a"); - assertTextArray("Empty entry at end", "a,", "a"); - assertTextArray("Empty entry at middle", "a,,b", "a", "b"); - assertTextArray("Empty entries with escape", ",a,b\\,c,,d,", "a", "b\\,c", "d"); - } - - public void testSplitSingle() { - assertTextArray("Single char", "a", "a"); - assertTextArray("Surrogate pair", PAIR1, PAIR1); - assertTextArray("Single escape", "\\", "\\"); - assertTextArray("Space", " ", " "); - assertTextArray("Single label", "abc", "abc"); - assertTextArray("Single surrogate pairs label", SURROGATE2, SURROGATE2); - assertTextArray("Spaces", " ", " "); - assertTextArray("Spaces in label", "a b c", "a b c"); - assertTextArray("Spaces at beginning of label", " abc", " abc"); - assertTextArray("Spaces at end of label", "abc ", "abc "); - assertTextArray("Label surrounded by spaces", " abc ", " abc "); - assertTextArray("Surrogate pair surrounded by space", - " " + PAIR1 + " ", - " " + PAIR1 + " "); - assertTextArray("Surrogate pair within characters", - "ab" + PAIR2 + "cd", - "ab" + PAIR2 + "cd"); - assertTextArray("Surrogate pairs within characters", - "ab" + SURROGATE1 + "cd", - "ab" + SURROGATE1 + "cd"); - - assertTextArray("Incomplete resource reference 1", "text", "text"); - assertTextArray("Incomplete resource reference 2", "!text", "!text"); - assertTextArray("Incomplete RESOURCE REFERENCE 2", "!TEXT", "!TEXT"); - assertTextArray("Incomplete resource reference 3", "text/", "text/"); - assertTextArray("Incomplete resource reference 4", "!" + SURROGATE2, "!" + SURROGATE2); - } - - public void testSplitSingleEscaped() { - assertTextArray("Escaped char", "\\a", "\\a"); - assertTextArray("Escaped surrogate pair", "\\" + PAIR1, "\\" + PAIR1); - assertTextArray("Escaped comma", "\\,", "\\,"); - assertTextArray("Escaped comma escape", "a\\,\\", "a\\,\\"); - assertTextArray("Escaped escape", "\\\\", "\\\\"); - assertTextArray("Escaped label", "a\\bc", "a\\bc"); - assertTextArray("Escaped surrogate", "a\\" + PAIR1 + "c", "a\\" + PAIR1 + "c"); - assertTextArray("Escaped label at beginning", "\\abc", "\\abc"); - assertTextArray("Escaped surrogate at beginning", "\\" + SURROGATE2, "\\" + SURROGATE2); - assertTextArray("Escaped label at end", "abc\\", "abc\\"); - assertTextArray("Escaped surrogate at end", SURROGATE2 + "\\", SURROGATE2 + "\\"); - assertTextArray("Escaped label with comma", "a\\,c", "a\\,c"); - assertTextArray("Escaped surrogate with comma", - PAIR1 + "\\," + PAIR2, PAIR1 + "\\," + PAIR2); - assertTextArray("Escaped label with comma at beginning", "\\,bc", "\\,bc"); - assertTextArray("Escaped surrogate with comma at beginning", - "\\," + SURROGATE1, "\\," + SURROGATE1); - assertTextArray("Escaped label with comma at end", "ab\\,", "ab\\,"); - assertTextArray("Escaped surrogate with comma at end", - SURROGATE2 + "\\,", SURROGATE2 + "\\,"); - assertTextArray("Escaped label with successive", "\\,\\\\bc", "\\,\\\\bc"); - assertTextArray("Escaped surrogate with successive", - "\\,\\\\" + SURROGATE1, "\\,\\\\" + SURROGATE1); - assertTextArray("Escaped label with escape", "a\\\\c", "a\\\\c"); - assertTextArray("Escaped surrogate with escape", - PAIR1 + "\\\\" + PAIR2, PAIR1 + "\\\\" + PAIR2); - - assertTextArray("Escaped !text", "\\!text", "\\!text"); - assertTextArray("Escaped !text/", "\\!text/", "\\!text/"); - assertTextArray("Escaped !TEXT/", "\\!TEXT/", "\\!TEXT/"); - assertTextArray("Escaped !text/name", "\\!text/empty_string", "\\!text/empty_string"); - assertTextArray("Escaped !TEXT/NAME", "\\!TEXT/EMPTY_STRING", "\\!TEXT/EMPTY_STRING"); - } - - public void testSplitMulti() { - assertTextArray("Multiple chars", "a,b,c", "a", "b", "c"); - assertTextArray("Multiple chars", "a,b,\\c", "a", "b", "\\c"); - assertTextArray("Multiple chars and escape at beginning and end", - "\\a,b,\\c\\", "\\a", "b", "\\c\\"); - assertTextArray("Multiple surrogates", PAIR1 + "," + PAIR2 + "," + PAIR3, - PAIR1, PAIR2, PAIR3); - assertTextArray("Multiple chars surrounded by spaces", " a , b , c ", " a ", " b ", " c "); - assertTextArray("Multiple labels", "abc,def,ghi", "abc", "def", "ghi"); - assertTextArray("Multiple surrogated", SURROGATE1 + "," + SURROGATE2, - SURROGATE1, SURROGATE2); - assertTextArray("Multiple labels surrounded by spaces", " abc , def , ghi ", - " abc ", " def ", " ghi "); - } - - public void testSplitMultiEscaped() { - assertTextArray("Multiple chars with comma", "a,\\,,c", "a", "\\,", "c"); - assertTextArray("Multiple chars with comma surrounded by spaces", " a , \\, , c ", - " a ", " \\, ", " c "); - assertTextArray("Multiple labels with escape", - "\\abc,d\\ef,gh\\i", "\\abc", "d\\ef", "gh\\i"); - assertTextArray("Multiple labels with escape surrounded by spaces", - " \\abc , d\\ef , gh\\i ", " \\abc ", " d\\ef ", " gh\\i "); - assertTextArray("Multiple labels with comma and escape", - "ab\\\\,d\\\\\\,,g\\,i", "ab\\\\", "d\\\\\\,", "g\\,i"); - assertTextArray("Multiple labels with comma and escape surrounded by spaces", - " ab\\\\ , d\\\\\\, , g\\,i ", " ab\\\\ ", " d\\\\\\, ", " g\\,i "); - - assertTextArray("Multiple escaped !text", "\\!,\\!text/empty_string", - "\\!", "\\!text/empty_string"); - assertTextArray("Multiple escaped !TEXT", "\\!,\\!TEXT/EMPTY_STRING", - "\\!", "\\!TEXT/EMPTY_STRING"); - } - - public void testSplitResourceError() { - assertError("Incomplete resource name", "!text/", "!text/"); - assertError("Non existing resource", "!text/non_existing"); - } - - public void testSplitResourceZero() { - assertTextArray("Empty string", - "!text/empty_string"); - } - - public void testSplitResourceSingle() { - assertTextArray("Single char", - "!text/single_char", "a"); - assertTextArray("Space", - "!text/space", " "); - assertTextArray("Single label", - "!text/single_label", "abc"); - assertTextArray("Spaces", - "!text/spaces", " "); - assertTextArray("Spaces in label", - "!text/spaces_in_label", "a b c"); - assertTextArray("Spaces at beginning of label", - "!text/spaces_at_beginning_of_label", " abc"); - assertTextArray("Spaces at end of label", - "!text/spaces_at_end_of_label", "abc "); - assertTextArray("label surrounded by spaces", - "!text/label_surrounded_by_spaces", " abc "); - - assertTextArray("Escape and single char", - "\\\\!text/single_char", "\\\\a"); - } - - public void testSplitResourceSingleEscaped() { - assertTextArray("Escaped char", - "!text/escaped_char", "\\a"); - assertTextArray("Escaped comma", - "!text/escaped_comma", "\\,"); - assertTextArray("Escaped comma escape", - "!text/escaped_comma_escape", "a\\,\\"); - assertTextArray("Escaped escape", - "!text/escaped_escape", "\\\\"); - assertTextArray("Escaped label", - "!text/escaped_label", "a\\bc"); - assertTextArray("Escaped label at beginning", - "!text/escaped_label_at_beginning", "\\abc"); - assertTextArray("Escaped label at end", - "!text/escaped_label_at_end", "abc\\"); - assertTextArray("Escaped label with comma", - "!text/escaped_label_with_comma", "a\\,c"); - assertTextArray("Escaped label with comma at beginning", - "!text/escaped_label_with_comma_at_beginning", "\\,bc"); - assertTextArray("Escaped label with comma at end", - "!text/escaped_label_with_comma_at_end", "ab\\,"); - assertTextArray("Escaped label with successive", - "!text/escaped_label_with_successive", "\\,\\\\bc"); - assertTextArray("Escaped label with escape", - "!text/escaped_label_with_escape", "a\\\\c"); - } - - public void testSplitResourceMulti() { - assertTextArray("Multiple chars", - "!text/multiple_chars", "a", "b", "c"); - assertTextArray("Multiple chars surrounded by spaces", - "!text/multiple_chars_surrounded_by_spaces", - " a ", " b ", " c "); - assertTextArray("Multiple labels", - "!text/multiple_labels", "abc", "def", "ghi"); - assertTextArray("Multiple labels surrounded by spaces", - "!text/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi "); - } - - public void testSplitResourcetMultiEscaped() { - assertTextArray("Multiple chars with comma", - "!text/multiple_chars_with_comma", - "a", "\\,", "c"); - assertTextArray("Multiple chars with comma surrounded by spaces", - "!text/multiple_chars_with_comma_surrounded_by_spaces", - " a ", " \\, ", " c "); - assertTextArray("Multiple labels with escape", - "!text/multiple_labels_with_escape", - "\\abc", "d\\ef", "gh\\i"); - assertTextArray("Multiple labels with escape surrounded by spaces", - "!text/multiple_labels_with_escape_surrounded_by_spaces", - " \\abc ", " d\\ef ", " gh\\i "); - assertTextArray("Multiple labels with comma and escape", - "!text/multiple_labels_with_comma_and_escape", - "ab\\\\", "d\\\\\\,", "g\\,i"); - assertTextArray("Multiple labels with comma and escape surrounded by spaces", - "!text/multiple_labels_with_comma_and_escape_surrounded_by_spaces", - " ab\\\\ ", " d\\\\\\, ", " g\\,i "); - } - - public void testSplitMultipleResources() { - assertTextArray("Literals and resources", - "1,!text/multiple_chars,z", "1", "a", "b", "c", "z"); - assertTextArray("Literals and resources and escape at end", - "\\1,!text/multiple_chars,z\\", "\\1", "a", "b", "c", "z\\"); - assertTextArray("Multiple single resource chars and labels", - "!text/single_char,!text/single_label,!text/escaped_comma", - "a", "abc", "\\,"); - assertTextArray("Multiple single resource chars and labels 2", - "!text/single_char,!text/single_label,!text/escaped_comma_escape", - "a", "abc", "a\\,\\"); - assertTextArray("Multiple multiple resource chars and labels", - "!text/multiple_chars,!text/multiple_labels,!text/multiple_chars_with_comma", - "a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c"); - assertTextArray("Concatenated resources", - "!text/multiple_chars!text/multiple_labels!text/multiple_chars_with_comma", - "a", "b", "cabc", "def", "ghia", "\\,", "c"); - assertTextArray("Concatenated resource and literal", - "abc!text/multiple_labels", - "abcabc", "def", "ghi"); - } - - public void testSplitIndirectReference() { - assertTextArray("Indirect", - "!text/indirect_string", "a", "b", "c"); - assertTextArray("Indirect with literal", - "1,!text/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2"); - assertTextArray("Indirect2", - "!text/indirect2_string", "a", "b", "c"); - } - - public void testSplitInfiniteIndirectReference() { - assertError("Infinite indirection", - "1,!text/infinite_indirection,2", "1", "infinite", "", "loop", "2"); - } - - public void testLabelReferece() { - assertTextArray("Label time am", "!text/label_time_am", "AM"); - - assertTextArray("More keys for am pm", "!text/more_keys_for_am_pm", - "!fixedColumnOrder!2", "!hasLabels!", "AM", "PM"); - - assertTextArray("Settings as more key", "!text/settings_as_more_key", - "!icon/settings_key|!code/key_settings"); - - assertTextArray("Indirect naviagte actions as more key", - "!text/indirect_navigate_actions_as_more_key", - "!fixedColumnOrder!2", - "!hasLabels!", "Prev|!code/key_action_previous", - "!hasLabels!", "Next|!code/key_action_next"); - } - - public void testUselessUpperCaseSpecifier() { - assertTextArray("EMPTY STRING", - "!TEXT/EMPTY_STRING", "!TEXT/EMPTY_STRING"); - - assertTextArray("SINGLE CHAR", - "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_CHAR"); - assertTextArray("Escape and SINGLE CHAR", - "\\\\!TEXT/SINGLE_CHAR", "\\\\!TEXT/SINGLE_CHAR"); - - assertTextArray("MULTIPLE CHARS", - "!TEXT/MULTIPLE_CHARS", "!TEXT/MULTIPLE_CHARS"); - - assertTextArray("Literals and RESOURCES", - "1,!TEXT/MULTIPLE_CHARS,z", "1", "!TEXT/MULTIPLE_CHARS", "z"); - assertTextArray("Multiple single RESOURCE chars and LABELS 2", - "!TEXT/SINGLE_CHAR,!TEXT/SINGLE_LABEL,!TEXT/ESCAPED_COMMA_ESCAPE", - "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_LABEL", "!TEXT/ESCAPED_COMMA_ESCAPE"); - - assertTextArray("INDIRECT", - "!TEXT/INDIRECT_STRING", "!TEXT/INDIRECT_STRING"); - assertTextArray("INDIRECT with literal", - "1,!TEXT/INDIRECT_STRING_WITH_LITERAL,2", - "1", "!TEXT/INDIRECT_STRING_WITH_LITERAL", "2"); - assertTextArray("INDIRECT2", - "!TEXT/INDIRECT2_STRING", "!TEXT/INDIRECT2_STRING"); - - assertTextArray("Upper indirect", - "!text/upper_indirect_string", "!TEXT/MULTIPLE_CHARS"); - assertTextArray("Upper indirect with literal", - "1,!text/upper_indirect_string_with_literal,2", - "1", "x", "!TEXT/MULTIPLE_CHARS", "y", "2"); - assertTextArray("Upper indirect2", - "!text/upper_indirect2_string", "!TEXT/UPPER_INDIRECT_STRING"); - - assertTextArray("UPPER INDIRECT", - "!TEXT/upper_INDIRECT_STRING", "!TEXT/upper_INDIRECT_STRING"); - assertTextArray("Upper INDIRECT with literal", - "1,!TEXT/upper_INDIRECT_STRING_WITH_LITERAL,2", - "1", "!TEXT/upper_INDIRECT_STRING_WITH_LITERAL", "2"); - assertTextArray("Upper INDIRECT2", - "!TEXT/upper_INDIRECT2_STRING", "!TEXT/upper_INDIRECT2_STRING"); - - assertTextArray("INFINITE INDIRECTION", - "1,!TEXT/INFINITE_INDIRECTION,2", "1", "!TEXT/INFINITE_INDIRECTION", "2"); - - assertTextArray("Upper infinite indirection", - "1,!text/upper_infinite_indirection,2", - "1", "infinite", "!TEXT/INFINITE_INDIRECTION", "loop", "2"); - assertTextArray("Upper INFINITE INDIRECTION", - "1,!TEXT/UPPER_INFINITE_INDIRECTION,2", - "1", "!TEXT/UPPER_INFINITE_INDIRECTION", "2"); - - assertTextArray("LABEL TIME AM", "!TEXT/LABEL_TIME_AM", "!TEXT/LABEL_TIME_AM"); - assertTextArray("MORE KEYS FOR AM OM", "!TEXT/MORE_KEYS_FOR_AM_PM", - "!TEXT/MORE_KEYS_FOR_AM_PM"); - assertTextArray("SETTINGS AS MORE KEY", "!TEXT/SETTINGS_AS_MORE_KEY", - "!TEXT/SETTINGS_AS_MORE_KEY"); - assertTextArray("INDIRECT NAVIGATE ACTIONS AS MORE KEY", - "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY", - "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY"); - } -} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java deleted file mode 100644 index 0388435eb..000000000 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeySpecParserTests.java +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED; -import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT; -import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; - -import android.content.Context; -import android.content.res.Resources; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; - -import com.android.inputmethod.latin.Constants; -import com.android.inputmethod.latin.utils.RunInLocale; - -import java.util.Arrays; -import java.util.Locale; - -@SmallTest -public class KeySpecParserTests extends AndroidTestCase { - private final static Locale TEST_LOCALE = Locale.ENGLISH; - final KeyboardCodesSet mCodesSet = new KeyboardCodesSet(); - final KeyboardTextsSet mTextsSet = new KeyboardTextsSet(); - - private static final String CODE_SETTINGS = "!code/key_settings"; - private static final String ICON_SETTINGS = "!icon/settings_key"; - private static final String CODE_SETTINGS_UPPERCASE = CODE_SETTINGS.toUpperCase(Locale.ROOT); - private static final String ICON_SETTINGS_UPPERCASE = ICON_SETTINGS.toUpperCase(Locale.ROOT); - private static final String CODE_NON_EXISTING = "!code/non_existing"; - private static final String ICON_NON_EXISTING = "!icon/non_existing"; - - private int mCodeSettings; - private int mCodeActionNext; - private int mSettingsIconId; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - final String language = TEST_LOCALE.getLanguage(); - mCodesSet.setLanguage(language); - mTextsSet.setLanguage(language); - final Context context = getContext(); - new RunInLocale() { - @Override - protected Void job(final Resources res) { - mTextsSet.loadStringResources(context); - return null; - } - }.runInLocale(context.getResources(), TEST_LOCALE); - - mCodeSettings = KeySpecParser.parseCode( - CODE_SETTINGS, mCodesSet, CODE_UNSPECIFIED); - mCodeActionNext = KeySpecParser.parseCode( - "!code/key_action_next", mCodesSet, CODE_UNSPECIFIED); - mSettingsIconId = KeySpecParser.getIconId(ICON_SETTINGS); - } - - private void assertParser(String message, String moreKeySpec, String expectedLabel, - String expectedOutputText, int expectedIcon, int expectedCode) { - final String labelResolved = mTextsSet.resolveTextReference(moreKeySpec); - final MoreKeySpec spec = new MoreKeySpec(labelResolved, false /* needsToUpperCase */, - Locale.US, mCodesSet); - assertEquals(message + " [label]", expectedLabel, spec.mLabel); - assertEquals(message + " [ouptputText]", expectedOutputText, spec.mOutputText); - assertEquals(message + " [icon]", - KeyboardIconsSet.getIconName(expectedIcon), - KeyboardIconsSet.getIconName(spec.mIconId)); - assertEquals(message + " [code]", - Constants.printableCode(expectedCode), - Constants.printableCode(spec.mCode)); - } - - private void assertParserError(String message, String moreKeySpec, String expectedLabel, - String expectedOutputText, int expectedIcon, int expectedCode) { - try { - assertParser(message, moreKeySpec, expectedLabel, expectedOutputText, expectedIcon, - expectedCode); - fail(message); - } catch (Exception pcpe) { - // success. - } - } - - // \U001d11e: MUSICAL SYMBOL G CLEF - private static final String PAIR1 = "\ud834\udd1e"; - private static final int CODE1 = PAIR1.codePointAt(0); - // \U001d122: MUSICAL SYMBOL F CLEF - private static final String PAIR2 = "\ud834\udd22"; - private static final int CODE2 = PAIR2.codePointAt(0); - // \U002f8a6: CJK COMPATIBILITY IDEOGRAPH-2F8A6; variant character of \u6148. - private static final String PAIR3 = "\ud87e\udca6"; - private static final String SURROGATE1 = PAIR1 + PAIR2; - private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3; - - public void testSingleLetter() { - assertParser("Single letter", "a", - "a", null, ICON_UNDEFINED, 'a'); - assertParser("Single surrogate", PAIR1, - PAIR1, null, ICON_UNDEFINED, CODE1); - assertParser("Single escaped bar", "\\|", - "|", null, ICON_UNDEFINED, '|'); - assertParser("Single escaped escape", "\\\\", - "\\", null, ICON_UNDEFINED, '\\'); - assertParser("Single comma", ",", - ",", null, ICON_UNDEFINED, ','); - assertParser("Single escaped comma", "\\,", - ",", null, ICON_UNDEFINED, ','); - assertParser("Single escaped letter", "\\a", - "a", null, ICON_UNDEFINED, 'a'); - assertParser("Single escaped surrogate", "\\" + PAIR2, - PAIR2, null, ICON_UNDEFINED, CODE2); - assertParser("Single bang", "!", - "!", null, ICON_UNDEFINED, '!'); - assertParser("Single escaped bang", "\\!", - "!", null, ICON_UNDEFINED, '!'); - assertParser("Single output text letter", "a|a", - "a", null, ICON_UNDEFINED, 'a'); - assertParser("Single surrogate pair outputText", "G Clef|" + PAIR1, - "G Clef", null, ICON_UNDEFINED, CODE1); - assertParser("Single letter with outputText", "a|abc", - "a", "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with surrogate outputText", "a|" + SURROGATE1, - "a", SURROGATE1, ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single surrogate with outputText", PAIR3 + "|abc", - PAIR3, "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with escaped outputText", "a|a\\|c", - "a", "a|c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with escaped surrogate outputText", - "a|" + PAIR1 + "\\|" + PAIR2, - "a", PAIR1 + "|" + PAIR2, ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with comma outputText", "a|a,b", - "a", "a,b", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with escaped comma outputText", "a|a\\,b", - "a", "a,b", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with outputText starts with bang", "a|!bc", - "a", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with surrogate outputText starts with bang", "a|!" + SURROGATE2, - "a", "!" + SURROGATE2, ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with outputText contains bang", "a|a!c", - "a", "a!c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single letter with escaped bang outputText", "a|\\!bc", - "a", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Single escaped escape with single outputText", "\\\\|\\\\", - "\\", null, ICON_UNDEFINED, '\\'); - assertParser("Single escaped bar with single outputText", "\\||\\|", - "|", null, ICON_UNDEFINED, '|'); - assertParser("Single letter with code", "a|" + CODE_SETTINGS, - "a", null, ICON_UNDEFINED, mCodeSettings); - } - - public void testLabel() { - assertParser("Simple label", "abc", - "abc", "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Simple surrogate label", SURROGATE1, - SURROGATE1, SURROGATE1, ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped bar", "a\\|c", - "a|c", "a|c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Surrogate label with escaped bar", PAIR1 + "\\|" + PAIR2, - PAIR1 + "|" + PAIR2, PAIR1 + "|" + PAIR2, - ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped escape", "a\\\\c", - "a\\c", "a\\c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with comma", "a,c", - "a,c", "a,c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped comma", "a\\,c", - "a,c", "a,c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label starts with bang", "!bc", - "!bc", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Surrogate label starts with bang", "!" + SURROGATE1, - "!" + SURROGATE1, "!" + SURROGATE1, ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label contains bang", "a!c", - "a!c", "a!c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped bang", "\\!bc", - "!bc", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped letter", "\\abc", - "abc", "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with outputText", "abc|def", - "abc", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with comma and outputText", "a,c|def", - "a,c", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Escaped comma label with outputText", "a\\,c|def", - "a,c", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Escaped label with outputText", "a\\|c|def", - "a|c", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped bar outputText", "abc|d\\|f", - "abc", "d|f", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Escaped escape label with outputText", "a\\\\|def", - "a\\", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label starts with bang and outputText", "!bc|def", - "!bc", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label contains bang label and outputText", "a!c|def", - "a!c", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Escaped bang label with outputText", "\\!bc|def", - "!bc", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with comma outputText", "abc|a,b", - "abc", "a,b", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped comma outputText", "abc|a\\,b", - "abc", "a,b", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with outputText starts with bang", "abc|!bc", - "abc", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with outputText contains bang", "abc|a!c", - "abc", "a!c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped bang outputText", "abc|\\!bc", - "abc", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with escaped bar outputText", "abc|d\\|f", - "abc", "d|f", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Escaped bar label with escaped bar outputText", "a\\|c|d\\|f", - "a|c", "d|f", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with code", "abc|" + CODE_SETTINGS, - "abc", null, ICON_UNDEFINED, mCodeSettings); - assertParser("Escaped label with code", "a\\|c|" + CODE_SETTINGS, - "a|c", null, ICON_UNDEFINED, mCodeSettings); - } - - public void testIconAndCode() { - assertParser("Icon with outputText", ICON_SETTINGS + "|abc", - null, "abc", mSettingsIconId, CODE_OUTPUT_TEXT); - assertParser("Icon with outputText starts with bang", ICON_SETTINGS + "|!bc", - null, "!bc", mSettingsIconId, CODE_OUTPUT_TEXT); - assertParser("Icon with outputText contains bang", ICON_SETTINGS + "|a!c", - null, "a!c", mSettingsIconId, CODE_OUTPUT_TEXT); - assertParser("Icon with escaped bang outputText", ICON_SETTINGS + "|\\!bc", - null, "!bc", mSettingsIconId, CODE_OUTPUT_TEXT); - assertParser("Label starts with bang and code", "!bc|" + CODE_SETTINGS, - "!bc", null, ICON_UNDEFINED, mCodeSettings); - assertParser("Label contains bang and code", "a!c|" + CODE_SETTINGS, - "a!c", null, ICON_UNDEFINED, mCodeSettings); - assertParser("Escaped bang label with code", "\\!bc|" + CODE_SETTINGS, - "!bc", null, ICON_UNDEFINED, mCodeSettings); - assertParser("Icon with code", ICON_SETTINGS + "|" + CODE_SETTINGS, - null, null, mSettingsIconId, mCodeSettings); - } - - public void testResourceReference() { - assertParser("Settings as more key", "!text/settings_as_more_key", - null, null, mSettingsIconId, mCodeSettings); - - assertParser("Action next as more key", "!text/label_next_key|!code/key_action_next", - "Next", null, ICON_UNDEFINED, mCodeActionNext); - - assertParser("Popular domain", - "!text/keylabel_for_popular_domain|!text/keylabel_for_popular_domain ", - ".com", ".com ", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - } - - public void testFormatError() { - assertParserError("Empty spec", "", null, - null, ICON_UNDEFINED, CODE_UNSPECIFIED); - assertParserError("Empty label with outputText", "|a", - null, "a", ICON_UNDEFINED, CODE_UNSPECIFIED); - assertParserError("Empty label with code", "|" + CODE_SETTINGS, - null, null, ICON_UNDEFINED, mCodeSettings); - assertParserError("Empty outputText with label", "a|", - "a", null, ICON_UNDEFINED, CODE_UNSPECIFIED); - assertParserError("Empty outputText with icon", ICON_SETTINGS + "|", - null, null, mSettingsIconId, CODE_UNSPECIFIED); - assertParserError("Empty icon and code", "|", - null, null, ICON_UNDEFINED, CODE_UNSPECIFIED); - assertParserError("Icon without code", ICON_SETTINGS, - null, null, mSettingsIconId, CODE_UNSPECIFIED); - assertParserError("Non existing icon", ICON_NON_EXISTING + "|abc", - null, "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParserError("Non existing code", "abc|" + CODE_NON_EXISTING, - "abc", null, ICON_UNDEFINED, CODE_UNSPECIFIED); - assertParserError("Third bar at end", "a|b|", - "a", null, ICON_UNDEFINED, CODE_UNSPECIFIED); - assertParserError("Multiple bar", "a|b|c", - "a", null, ICON_UNDEFINED, CODE_UNSPECIFIED); - assertParserError("Multiple bar with label and code", "a|" + CODE_SETTINGS + "|c", - "a", null, ICON_UNDEFINED, mCodeSettings); - assertParserError("Multiple bar with icon and outputText", ICON_SETTINGS + "|b|c", - null, null, mSettingsIconId, CODE_UNSPECIFIED); - assertParserError("Multiple bar with icon and code", - ICON_SETTINGS + "|" + CODE_SETTINGS + "|c", - null, null, mSettingsIconId, mCodeSettings); - } - - public void testUselessUpperCaseSpecifier() { - assertParser("Single letter with CODE", "a|" + CODE_SETTINGS_UPPERCASE, - "a", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label with CODE", "abc|" + CODE_SETTINGS_UPPERCASE, - "abc", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Escaped label with CODE", "a\\|c|" + CODE_SETTINGS_UPPERCASE, - "a|c", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("ICON with outputText", ICON_SETTINGS_UPPERCASE + "|abc", - "!ICON/SETTINGS_KEY", "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("ICON with outputText starts with bang", ICON_SETTINGS_UPPERCASE + "|!bc", - "!ICON/SETTINGS_KEY", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("ICON with outputText contains bang", ICON_SETTINGS_UPPERCASE + "|a!c", - "!ICON/SETTINGS_KEY", "a!c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("ICON with escaped bang outputText", ICON_SETTINGS_UPPERCASE + "|\\!bc", - "!ICON/SETTINGS_KEY", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label starts with bang and CODE", "!bc|" + CODE_SETTINGS_UPPERCASE, - "!bc", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Label contains bang and CODE", "a!c|" + CODE_SETTINGS_UPPERCASE, - "a!c", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("Escaped bang label with CODE", "\\!bc|" + CODE_SETTINGS_UPPERCASE, - "!bc", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("ICON with CODE", ICON_SETTINGS_UPPERCASE + "|" + CODE_SETTINGS_UPPERCASE, - "!ICON/SETTINGS_KEY", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParser("SETTINGS AS MORE KEY", "!TEXT/SETTINGS_AS_MORE_KEY", - "!TEXT/SETTINGS_AS_MORE_KEY", "!TEXT/SETTINGS_AS_MORE_KEY", ICON_UNDEFINED, - CODE_OUTPUT_TEXT); - assertParser("ACTION NEXT AS MORE KEY", "!TEXT/LABEL_NEXT_KEY|!CODE/KEY_ACTION_NEXT", - "!TEXT/LABEL_NEXT_KEY", "!CODE/KEY_ACTION_NEXT", ICON_UNDEFINED, - CODE_OUTPUT_TEXT); - assertParser("POPULAR DOMAIN", - "!TEXT/KEYLABEL_FOR_POPULAR_DOMAIN|!TEXT/KEYLABEL_FOR_POPULAR_DOMAIN ", - "!TEXT/KEYLABEL_FOR_POPULAR_DOMAIN", "!TEXT/KEYLABEL_FOR_POPULAR_DOMAIN ", - ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParserError("Empty label with CODE", "|" + CODE_SETTINGS_UPPERCASE, - null, null, ICON_UNDEFINED, mCodeSettings); - assertParserError("Empty outputText with ICON", ICON_SETTINGS_UPPERCASE + "|", - null, null, mSettingsIconId, CODE_UNSPECIFIED); - assertParser("ICON without code", ICON_SETTINGS_UPPERCASE, - "!ICON/SETTINGS_KEY", "!ICON/SETTINGS_KEY", ICON_UNDEFINED, CODE_OUTPUT_TEXT); - assertParserError("Multiple bar with label and CODE", "a|" + CODE_SETTINGS_UPPERCASE + "|c", - "a", null, ICON_UNDEFINED, mCodeSettings); - assertParserError("Multiple bar with ICON and outputText", ICON_SETTINGS_UPPERCASE + "|b|c", - null, null, mSettingsIconId, CODE_UNSPECIFIED); - assertParserError("Multiple bar with ICON and CODE", - ICON_SETTINGS_UPPERCASE + "|" + CODE_SETTINGS_UPPERCASE + "|c", - null, null, mSettingsIconId, mCodeSettings); - } - - private static void assertArrayEquals(String message, Object[] expected, Object[] actual) { - if (expected == actual) { - return; - } - if (expected == null || actual == null) { - assertEquals(message, Arrays.toString(expected), Arrays.toString(actual)); - return; - } - if (expected.length != actual.length) { - assertEquals(message + " [length]", Arrays.toString(expected), Arrays.toString(actual)); - return; - } - for (int i = 0; i < expected.length; i++) { - assertEquals(message + " [" + i + "]", - Arrays.toString(expected), Arrays.toString(actual)); - } - } - - private static void assertInsertAdditionalMoreKeys(String message, String[] moreKeys, - String[] additionalMoreKeys, String[] expected) { - final String[] actual = - KeySpecParser.insertAdditionalMoreKeys( moreKeys, additionalMoreKeys); - assertArrayEquals(message, expected, actual); - } - - public void testEmptyEntry() { - assertInsertAdditionalMoreKeys("null more keys and null additons", - null, - null, - null); - assertInsertAdditionalMoreKeys("null more keys and empty additons", - null, - new String[0], - null); - assertInsertAdditionalMoreKeys("empty more keys and null additons", - new String[0], - null, - null); - assertInsertAdditionalMoreKeys("empty more keys and empty additons", - new String[0], - new String[0], - null); - - assertInsertAdditionalMoreKeys("filter out empty more keys", - new String[] { null, "a", "", "b", null }, - null, - new String[] { "a", "b" }); - assertInsertAdditionalMoreKeys("filter out empty additons", - new String[] { "a", "%", "b", "%", "c", "%", "d" }, - new String[] { null, "A", "", "B", null }, - new String[] { "a", "A", "b", "B", "c", "d" }); - } - - public void testInsertAdditionalMoreKeys() { - // Escaped marker. - assertInsertAdditionalMoreKeys("escaped marker", - new String[] { "\\%", "%-)" }, - new String[] { "1", "2" }, - new String[] { "1", "2", "\\%", "%-)" }); - - // 0 more key. - assertInsertAdditionalMoreKeys("null & null", null, null, null); - assertInsertAdditionalMoreKeys("null & 1 additon", - null, - new String[] { "1" }, - new String[] { "1" }); - assertInsertAdditionalMoreKeys("null & 2 additons", - null, - new String[] { "1", "2" }, - new String[] { "1", "2" }); - - // 0 additional more key. - assertInsertAdditionalMoreKeys("1 more key & null", - new String[] { "A" }, - null, - new String[] { "A" }); - assertInsertAdditionalMoreKeys("2 more keys & null", - new String[] { "A", "B" }, - null, - new String[] { "A", "B" }); - - // No marker. - assertInsertAdditionalMoreKeys("1 more key & 1 addtional & no marker", - new String[] { "A" }, - new String[] { "1" }, - new String[] { "1", "A" }); - assertInsertAdditionalMoreKeys("1 more key & 2 addtionals & no marker", - new String[] { "A" }, - new String[] { "1", "2" }, - new String[] { "1", "2", "A" }); - assertInsertAdditionalMoreKeys("2 more keys & 1 addtional & no marker", - new String[] { "A", "B" }, - new String[] { "1" }, - new String[] { "1", "A", "B" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 addtionals & no marker", - new String[] { "A", "B" }, - new String[] { "1", "2" }, - new String[] { "1", "2", "A", "B" }); - - // 1 marker. - assertInsertAdditionalMoreKeys("1 more key & 1 additon & marker at head", - new String[] { "%", "A" }, - new String[] { "1" }, - new String[] { "1", "A" }); - assertInsertAdditionalMoreKeys("1 more key & 1 additon & marker at tail", - new String[] { "A", "%" }, - new String[] { "1" }, - new String[] { "A", "1" }); - assertInsertAdditionalMoreKeys("2 more keys & 1 additon & marker at middle", - new String[] { "A", "%", "B" }, - new String[] { "1" }, - new String[] { "A", "1", "B" }); - - // 1 marker & excess additional more keys. - assertInsertAdditionalMoreKeys("1 more key & 2 additons & marker at head", - new String[] { "%", "A", "B" }, - new String[] { "1", "2" }, - new String[] { "1", "A", "B", "2" }); - assertInsertAdditionalMoreKeys("1 more key & 2 additons & marker at tail", - new String[] { "A", "B", "%" }, - new String[] { "1", "2" }, - new String[] { "A", "B", "1", "2" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 additons & marker at middle", - new String[] { "A", "%", "B" }, - new String[] { "1", "2" }, - new String[] { "A", "1", "B", "2" }); - - // 2 markers. - assertInsertAdditionalMoreKeys("0 more key & 2 addtional & 2 markers", - new String[] { "%", "%" }, - new String[] { "1", "2" }, - new String[] { "1", "2" }); - assertInsertAdditionalMoreKeys("1 more key & 2 addtional & 2 markers at head", - new String[] { "%", "%", "A" }, - new String[] { "1", "2" }, - new String[] { "1", "2", "A" }); - assertInsertAdditionalMoreKeys("1 more key & 2 addtional & 2 markers at tail", - new String[] { "A", "%", "%" }, - new String[] { "1", "2" }, - new String[] { "A", "1", "2" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 addtional & 2 markers at middle", - new String[] { "A", "%", "%", "B" }, - new String[] { "1", "2" }, - new String[] { "A", "1", "2", "B" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 addtional & 2 markers at head & middle", - new String[] { "%", "A", "%", "B" }, - new String[] { "1", "2" }, - new String[] { "1", "A", "2", "B" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 addtional & 2 markers at head & tail", - new String[] { "%", "A", "B", "%" }, - new String[] { "1", "2" }, - new String[] { "1", "A", "B", "2" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 addtional & 2 markers at middle & tail", - new String[] { "A", "%", "B", "%" }, - new String[] { "1", "2" }, - new String[] { "A", "1", "B", "2" }); - - // 2 markers & excess additional more keys. - assertInsertAdditionalMoreKeys("0 more key & 2 additons & 2 markers", - new String[] { "%", "%" }, - new String[] { "1", "2", "3" }, - new String[] { "1", "2", "3" }); - assertInsertAdditionalMoreKeys("1 more key & 2 additons & 2 markers at head", - new String[] { "%", "%", "A" }, - new String[] { "1", "2", "3" }, - new String[] { "1", "2", "A", "3" }); - assertInsertAdditionalMoreKeys("1 more key & 2 additons & 2 markers at tail", - new String[] { "A", "%", "%" }, - new String[] { "1", "2", "3" }, - new String[] { "A", "1", "2", "3" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 additons & 2 markers at middle", - new String[] { "A", "%", "%", "B" }, - new String[] { "1", "2", "3" }, - new String[] { "A", "1", "2", "B", "3" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 additons & 2 markers at head & middle", - new String[] { "%", "A", "%", "B" }, - new String[] { "1", "2", "3" }, - new String[] { "1", "A", "2", "B", "3" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 additons & 2 markers at head & tail", - new String[] { "%", "A", "B", "%" }, - new String[] { "1", "2", "3" }, - new String[] { "1", "A", "B", "2", "3" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 additons & 2 markers at middle & tail", - new String[] { "A", "%", "B", "%" }, - new String[] { "1", "2", "3" }, - new String[] { "A", "1", "B", "2", "3" }); - - // 0 addtional more key and excess markers. - assertInsertAdditionalMoreKeys("0 more key & null & excess marker", - new String[] { "%" }, - null, - null); - assertInsertAdditionalMoreKeys("1 more key & null & excess marker at head", - new String[] { "%", "A" }, - null, - new String[] { "A" }); - assertInsertAdditionalMoreKeys("1 more key & null & excess marker at tail", - new String[] { "A", "%" }, - null, - new String[] { "A" }); - assertInsertAdditionalMoreKeys("2 more keys & null & excess marker at middle", - new String[] { "A", "%", "B" }, - null, - new String[] { "A", "B" }); - assertInsertAdditionalMoreKeys("2 more keys & null & excess markers", - new String[] { "%", "A", "%", "B", "%" }, - null, - new String[] { "A", "B" }); - - // Excess markers. - assertInsertAdditionalMoreKeys("0 more key & 1 additon & excess marker", - new String[] { "%", "%" }, - new String[] { "1" }, - new String[] { "1" }); - assertInsertAdditionalMoreKeys("1 more key & 1 additon & excess marker at head", - new String[] { "%", "%", "A" }, - new String[] { "1" }, - new String[] { "1", "A" }); - assertInsertAdditionalMoreKeys("1 more key & 1 additon & excess marker at tail", - new String[] { "A", "%", "%" }, - new String[] { "1" }, - new String[] { "A", "1" }); - assertInsertAdditionalMoreKeys("2 more keys & 1 additon & excess marker at middle", - new String[] { "A", "%", "%", "B" }, - new String[] { "1" }, - new String[] { "A", "1", "B" }); - assertInsertAdditionalMoreKeys("2 more keys & 1 additon & excess markers", - new String[] { "%", "A", "%", "B", "%" }, - new String[] { "1" }, - new String[] { "1", "A", "B" }); - assertInsertAdditionalMoreKeys("2 more keys & 2 additons & excess markers", - new String[] { "%", "A", "%", "B", "%" }, - new String[] { "1", "2" }, - new String[] { "1", "A", "2", "B" }); - assertInsertAdditionalMoreKeys("2 more keys & 3 additons & excess markers", - new String[] { "%", "A", "%", "%", "B", "%" }, - new String[] { "1", "2", "3" }, - new String[] { "1", "A", "2", "3", "B" }); - } - - private static final String HAS_LABEL = "!hasLabel!"; - private static final String NEEDS_DIVIDER = "!needsDividers!"; - private static final String AUTO_COLUMN_ORDER = "!autoColumnOrder!"; - private static final String FIXED_COLUMN_ORDER = "!fixedColumnOrder!"; - - private static void assertGetBooleanValue(String message, String key, String[] moreKeys, - String[] expected, boolean expectedValue) { - final String[] actual = Arrays.copyOf(moreKeys, moreKeys.length); - final boolean actualValue = KeySpecParser.getBooleanValue(actual, key); - assertEquals(message + " [value]", expectedValue, actualValue); - assertArrayEquals(message, expected, actual); - } - - public void testGetBooleanValue() { - assertGetBooleanValue("Has label", HAS_LABEL, - new String[] { HAS_LABEL, "a", "b", "c" }, - new String[] { null, "a", "b", "c" }, true); - // Upper case specification will not work. - assertGetBooleanValue("HAS LABEL", HAS_LABEL, - new String[] { HAS_LABEL.toUpperCase(Locale.ROOT), "a", "b", "c" }, - new String[] { "!HASLABEL!", "a", "b", "c" }, false); - - assertGetBooleanValue("No has label", HAS_LABEL, - new String[] { "a", "b", "c" }, - new String[] { "a", "b", "c" }, false); - assertGetBooleanValue("No has label with fixed clumn order", HAS_LABEL, - new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" }, - new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" }, false); - - // Upper case specification will not work. - assertGetBooleanValue("Multiple has label", HAS_LABEL, - new String[] { - "a", HAS_LABEL.toUpperCase(Locale.ROOT), "b", "c", HAS_LABEL, "d" }, - new String[] { - "a", "!HASLABEL!", "b", "c", null, "d" }, true); - // Upper case specification will not work. - assertGetBooleanValue("Multiple has label with needs dividers", HAS_LABEL, - new String[] { - "a", HAS_LABEL, "b", NEEDS_DIVIDER, HAS_LABEL.toUpperCase(Locale.ROOT), "d" }, - new String[] { - "a", null, "b", NEEDS_DIVIDER, "!HASLABEL!", "d" }, true); - } - - private static void assertGetIntValue(String message, String key, int defaultValue, - String[] moreKeys, String[] expected, int expectedValue) { - final String[] actual = Arrays.copyOf(moreKeys, moreKeys.length); - final int actualValue = KeySpecParser.getIntValue(actual, key, defaultValue); - assertEquals(message + " [value]", expectedValue, actualValue); - assertArrayEquals(message, expected, actual); - } - - public void testGetIntValue() { - assertGetIntValue("Fixed column order 3", FIXED_COLUMN_ORDER, -1, - new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" }, - new String[] { null, "a", "b", "c" }, 3); - // Upper case specification will not work. - assertGetIntValue("FIXED COLUMN ORDER 3", FIXED_COLUMN_ORDER, -1, - new String[] { FIXED_COLUMN_ORDER.toUpperCase(Locale.ROOT) + "3", "a", "b", "c" }, - new String[] { "!FIXEDCOLUMNORDER!3", "a", "b", "c" }, -1); - - assertGetIntValue("No fixed column order", FIXED_COLUMN_ORDER, -1, - new String[] { "a", "b", "c" }, - new String[] { "a", "b", "c" }, -1); - assertGetIntValue("No fixed column order with auto column order", FIXED_COLUMN_ORDER, -1, - new String[] { AUTO_COLUMN_ORDER + "5", "a", "b", "c" }, - new String[] { AUTO_COLUMN_ORDER + "5", "a", "b", "c" }, -1); - - assertGetIntValue("Multiple fixed column order 3,5", FIXED_COLUMN_ORDER, -1, - new String[] { FIXED_COLUMN_ORDER + "3", "a", FIXED_COLUMN_ORDER + "5", "b" }, - new String[] { null, "a", null, "b" }, 3); - // Upper case specification will not work. - assertGetIntValue("Multiple fixed column order 5,3 with has label", FIXED_COLUMN_ORDER, -1, - new String[] { - FIXED_COLUMN_ORDER.toUpperCase(Locale.ROOT) + "5", HAS_LABEL, "a", - FIXED_COLUMN_ORDER + "3", "b" }, - new String[] { "!FIXEDCOLUMNORDER!5", HAS_LABEL, "a", null, "b" }, 3); - } -} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecSplitTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecSplitTests.java new file mode 100644 index 000000000..5f301a839 --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecSplitTests.java @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import android.app.Instrumentation; +import android.content.Context; +import android.content.res.Resources; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.MediumTest; + +import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.RunInLocale; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; + +@MediumTest +public class MoreKeySpecSplitTests extends InstrumentationTestCase { + private static final Locale TEST_LOCALE = Locale.ENGLISH; + final KeyboardTextsSet mTextsSet = new KeyboardTextsSet(); + + @Override + protected void setUp() throws Exception { + super.setUp(); + + final Instrumentation instrumentation = getInstrumentation(); + final Context targetContext = instrumentation.getTargetContext(); + mTextsSet.setLanguage(TEST_LOCALE.getLanguage()); + new RunInLocale() { + @Override + protected Void job(final Resources res) { + mTextsSet.loadStringResources(targetContext); + return null; + } + }.runInLocale(targetContext.getResources(), TEST_LOCALE); + final String[] testResourceNames = getAllResourceIdNames( + com.android.inputmethod.latin.tests.R.string.class); + mTextsSet.loadStringResourcesInternal(instrumentation.getContext(), testResourceNames, + // This dummy raw resource is needed to be able to load string resources from a test + // APK successfully. + com.android.inputmethod.latin.tests.R.raw.dummy_resource_for_testing); + } + + private static String[] getAllResourceIdNames(final Class resourceIdClass) { + final ArrayList names = CollectionUtils.newArrayList(); + for (final Field field : resourceIdClass.getFields()) { + if (field.getType() == Integer.TYPE) { + names.add(field.getName()); + } + } + return names.toArray(new String[names.size()]); + } + + private static void assertArrayEquals(final String message, final T[] expected, + final T[] actual) { + if (expected == actual) { + return; + } + if (expected == null || actual == null) { + assertEquals(message, Arrays.toString(expected), Arrays.toString(actual)); + return; + } + if (expected.length != actual.length) { + assertEquals(message + " [length]", Arrays.toString(expected), Arrays.toString(actual)); + return; + } + for (int i = 0; i < expected.length; i++) { + final T e = expected[i]; + final T a = actual[i]; + if (e == a) { + continue; + } + assertEquals(message + " [" + i + "]", e, a); + } + } + + private void assertTextArray(final String message, final String value, + final String ... expectedArray) { + final String resolvedActual = mTextsSet.resolveTextReference(value); + final String[] actual = MoreKeySpec.splitKeySpecs(resolvedActual); + final String[] expected = (expectedArray.length == 0) ? null : expectedArray; + assertArrayEquals(message, expected, actual); + } + + private void assertError(final String message, final String value, final String ... expected) { + try { + assertTextArray(message, value, expected); + fail(message); + } catch (Exception pcpe) { + // success. + } + } + + // \U001d11e: MUSICAL SYMBOL G CLEF + private static final String PAIR1 = "\ud834\udd1e"; + // \U001d122: MUSICAL SYMBOL F CLEF + private static final String PAIR2 = "\ud834\udd22"; + // \U002f8a6: CJK COMPATIBILITY IDEOGRAPH-2F8A6; variant character of \u6148. + private static final String PAIR3 = "\ud87e\udca6"; + private static final String SURROGATE1 = PAIR1 + PAIR2; + private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3; + + public void testResolveNullText() { + assertNull("resolve null", mTextsSet.resolveTextReference(null)); + } + + public void testResolveEmptyText() { + assertNull("resolve empty text", mTextsSet.resolveTextReference("!text/empty_string")); + } + + public void testSplitZero() { + assertTextArray("Empty string", ""); + assertTextArray("Empty entry", ","); + assertTextArray("Empty entry at beginning", ",a", "a"); + assertTextArray("Empty entry at end", "a,", "a"); + assertTextArray("Empty entry at middle", "a,,b", "a", "b"); + assertTextArray("Empty entries with escape", ",a,b\\,c,,d,", "a", "b\\,c", "d"); + } + + public void testSplitSingle() { + assertTextArray("Single char", "a", "a"); + assertTextArray("Surrogate pair", PAIR1, PAIR1); + assertTextArray("Single escape", "\\", "\\"); + assertTextArray("Space", " ", " "); + assertTextArray("Single label", "abc", "abc"); + assertTextArray("Single surrogate pairs label", SURROGATE2, SURROGATE2); + assertTextArray("Spaces", " ", " "); + assertTextArray("Spaces in label", "a b c", "a b c"); + assertTextArray("Spaces at beginning of label", " abc", " abc"); + assertTextArray("Spaces at end of label", "abc ", "abc "); + assertTextArray("Label surrounded by spaces", " abc ", " abc "); + assertTextArray("Surrogate pair surrounded by space", + " " + PAIR1 + " ", + " " + PAIR1 + " "); + assertTextArray("Surrogate pair within characters", + "ab" + PAIR2 + "cd", + "ab" + PAIR2 + "cd"); + assertTextArray("Surrogate pairs within characters", + "ab" + SURROGATE1 + "cd", + "ab" + SURROGATE1 + "cd"); + + assertTextArray("Incomplete resource reference 1", "text", "text"); + assertTextArray("Incomplete resource reference 2", "!text", "!text"); + assertTextArray("Incomplete RESOURCE REFERENCE 2", "!TEXT", "!TEXT"); + assertTextArray("Incomplete resource reference 3", "text/", "text/"); + assertTextArray("Incomplete resource reference 4", "!" + SURROGATE2, "!" + SURROGATE2); + } + + public void testSplitSingleEscaped() { + assertTextArray("Escaped char", "\\a", "\\a"); + assertTextArray("Escaped surrogate pair", "\\" + PAIR1, "\\" + PAIR1); + assertTextArray("Escaped comma", "\\,", "\\,"); + assertTextArray("Escaped comma escape", "a\\,\\", "a\\,\\"); + assertTextArray("Escaped escape", "\\\\", "\\\\"); + assertTextArray("Escaped label", "a\\bc", "a\\bc"); + assertTextArray("Escaped surrogate", "a\\" + PAIR1 + "c", "a\\" + PAIR1 + "c"); + assertTextArray("Escaped label at beginning", "\\abc", "\\abc"); + assertTextArray("Escaped surrogate at beginning", "\\" + SURROGATE2, "\\" + SURROGATE2); + assertTextArray("Escaped label at end", "abc\\", "abc\\"); + assertTextArray("Escaped surrogate at end", SURROGATE2 + "\\", SURROGATE2 + "\\"); + assertTextArray("Escaped label with comma", "a\\,c", "a\\,c"); + assertTextArray("Escaped surrogate with comma", + PAIR1 + "\\," + PAIR2, PAIR1 + "\\," + PAIR2); + assertTextArray("Escaped label with comma at beginning", "\\,bc", "\\,bc"); + assertTextArray("Escaped surrogate with comma at beginning", + "\\," + SURROGATE1, "\\," + SURROGATE1); + assertTextArray("Escaped label with comma at end", "ab\\,", "ab\\,"); + assertTextArray("Escaped surrogate with comma at end", + SURROGATE2 + "\\,", SURROGATE2 + "\\,"); + assertTextArray("Escaped label with successive", "\\,\\\\bc", "\\,\\\\bc"); + assertTextArray("Escaped surrogate with successive", + "\\,\\\\" + SURROGATE1, "\\,\\\\" + SURROGATE1); + assertTextArray("Escaped label with escape", "a\\\\c", "a\\\\c"); + assertTextArray("Escaped surrogate with escape", + PAIR1 + "\\\\" + PAIR2, PAIR1 + "\\\\" + PAIR2); + + assertTextArray("Escaped !text", "\\!text", "\\!text"); + assertTextArray("Escaped !text/", "\\!text/", "\\!text/"); + assertTextArray("Escaped !TEXT/", "\\!TEXT/", "\\!TEXT/"); + assertTextArray("Escaped !text/name", "\\!text/empty_string", "\\!text/empty_string"); + assertTextArray("Escaped !TEXT/NAME", "\\!TEXT/EMPTY_STRING", "\\!TEXT/EMPTY_STRING"); + } + + public void testSplitMulti() { + assertTextArray("Multiple chars", "a,b,c", "a", "b", "c"); + assertTextArray("Multiple chars", "a,b,\\c", "a", "b", "\\c"); + assertTextArray("Multiple chars and escape at beginning and end", + "\\a,b,\\c\\", "\\a", "b", "\\c\\"); + assertTextArray("Multiple surrogates", PAIR1 + "," + PAIR2 + "," + PAIR3, + PAIR1, PAIR2, PAIR3); + assertTextArray("Multiple chars surrounded by spaces", " a , b , c ", " a ", " b ", " c "); + assertTextArray("Multiple labels", "abc,def,ghi", "abc", "def", "ghi"); + assertTextArray("Multiple surrogated", SURROGATE1 + "," + SURROGATE2, + SURROGATE1, SURROGATE2); + assertTextArray("Multiple labels surrounded by spaces", " abc , def , ghi ", + " abc ", " def ", " ghi "); + } + + public void testSplitMultiEscaped() { + assertTextArray("Multiple chars with comma", "a,\\,,c", "a", "\\,", "c"); + assertTextArray("Multiple chars with comma surrounded by spaces", " a , \\, , c ", + " a ", " \\, ", " c "); + assertTextArray("Multiple labels with escape", + "\\abc,d\\ef,gh\\i", "\\abc", "d\\ef", "gh\\i"); + assertTextArray("Multiple labels with escape surrounded by spaces", + " \\abc , d\\ef , gh\\i ", " \\abc ", " d\\ef ", " gh\\i "); + assertTextArray("Multiple labels with comma and escape", + "ab\\\\,d\\\\\\,,g\\,i", "ab\\\\", "d\\\\\\,", "g\\,i"); + assertTextArray("Multiple labels with comma and escape surrounded by spaces", + " ab\\\\ , d\\\\\\, , g\\,i ", " ab\\\\ ", " d\\\\\\, ", " g\\,i "); + + assertTextArray("Multiple escaped !text", "\\!,\\!text/empty_string", + "\\!", "\\!text/empty_string"); + assertTextArray("Multiple escaped !TEXT", "\\!,\\!TEXT/EMPTY_STRING", + "\\!", "\\!TEXT/EMPTY_STRING"); + } + + public void testSplitResourceError() { + assertError("Incomplete resource name", "!text/", "!text/"); + assertError("Non existing resource", "!text/non_existing"); + } + + public void testSplitResourceZero() { + assertTextArray("Empty string", + "!text/empty_string"); + } + + public void testSplitResourceSingle() { + assertTextArray("Single char", + "!text/single_char", "a"); + assertTextArray("Space", + "!text/space", " "); + assertTextArray("Single label", + "!text/single_label", "abc"); + assertTextArray("Spaces", + "!text/spaces", " "); + assertTextArray("Spaces in label", + "!text/spaces_in_label", "a b c"); + assertTextArray("Spaces at beginning of label", + "!text/spaces_at_beginning_of_label", " abc"); + assertTextArray("Spaces at end of label", + "!text/spaces_at_end_of_label", "abc "); + assertTextArray("label surrounded by spaces", + "!text/label_surrounded_by_spaces", " abc "); + + assertTextArray("Escape and single char", + "\\\\!text/single_char", "\\\\a"); + } + + public void testSplitResourceSingleEscaped() { + assertTextArray("Escaped char", + "!text/escaped_char", "\\a"); + assertTextArray("Escaped comma", + "!text/escaped_comma", "\\,"); + assertTextArray("Escaped comma escape", + "!text/escaped_comma_escape", "a\\,\\"); + assertTextArray("Escaped escape", + "!text/escaped_escape", "\\\\"); + assertTextArray("Escaped label", + "!text/escaped_label", "a\\bc"); + assertTextArray("Escaped label at beginning", + "!text/escaped_label_at_beginning", "\\abc"); + assertTextArray("Escaped label at end", + "!text/escaped_label_at_end", "abc\\"); + assertTextArray("Escaped label with comma", + "!text/escaped_label_with_comma", "a\\,c"); + assertTextArray("Escaped label with comma at beginning", + "!text/escaped_label_with_comma_at_beginning", "\\,bc"); + assertTextArray("Escaped label with comma at end", + "!text/escaped_label_with_comma_at_end", "ab\\,"); + assertTextArray("Escaped label with successive", + "!text/escaped_label_with_successive", "\\,\\\\bc"); + assertTextArray("Escaped label with escape", + "!text/escaped_label_with_escape", "a\\\\c"); + } + + public void testSplitResourceMulti() { + assertTextArray("Multiple chars", + "!text/multiple_chars", "a", "b", "c"); + assertTextArray("Multiple chars surrounded by spaces", + "!text/multiple_chars_surrounded_by_spaces", + " a ", " b ", " c "); + assertTextArray("Multiple labels", + "!text/multiple_labels", "abc", "def", "ghi"); + assertTextArray("Multiple labels surrounded by spaces", + "!text/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi "); + } + + public void testSplitResourcetMultiEscaped() { + assertTextArray("Multiple chars with comma", + "!text/multiple_chars_with_comma", + "a", "\\,", "c"); + assertTextArray("Multiple chars with comma surrounded by spaces", + "!text/multiple_chars_with_comma_surrounded_by_spaces", + " a ", " \\, ", " c "); + assertTextArray("Multiple labels with escape", + "!text/multiple_labels_with_escape", + "\\abc", "d\\ef", "gh\\i"); + assertTextArray("Multiple labels with escape surrounded by spaces", + "!text/multiple_labels_with_escape_surrounded_by_spaces", + " \\abc ", " d\\ef ", " gh\\i "); + assertTextArray("Multiple labels with comma and escape", + "!text/multiple_labels_with_comma_and_escape", + "ab\\\\", "d\\\\\\,", "g\\,i"); + assertTextArray("Multiple labels with comma and escape surrounded by spaces", + "!text/multiple_labels_with_comma_and_escape_surrounded_by_spaces", + " ab\\\\ ", " d\\\\\\, ", " g\\,i "); + } + + public void testSplitMultipleResources() { + assertTextArray("Literals and resources", + "1,!text/multiple_chars,z", "1", "a", "b", "c", "z"); + assertTextArray("Literals and resources and escape at end", + "\\1,!text/multiple_chars,z\\", "\\1", "a", "b", "c", "z\\"); + assertTextArray("Multiple single resource chars and labels", + "!text/single_char,!text/single_label,!text/escaped_comma", + "a", "abc", "\\,"); + assertTextArray("Multiple single resource chars and labels 2", + "!text/single_char,!text/single_label,!text/escaped_comma_escape", + "a", "abc", "a\\,\\"); + assertTextArray("Multiple multiple resource chars and labels", + "!text/multiple_chars,!text/multiple_labels,!text/multiple_chars_with_comma", + "a", "b", "c", "abc", "def", "ghi", "a", "\\,", "c"); + assertTextArray("Concatenated resources", + "!text/multiple_chars!text/multiple_labels!text/multiple_chars_with_comma", + "a", "b", "cabc", "def", "ghia", "\\,", "c"); + assertTextArray("Concatenated resource and literal", + "abc!text/multiple_labels", + "abcabc", "def", "ghi"); + } + + public void testSplitIndirectReference() { + assertTextArray("Indirect", + "!text/indirect_string", "a", "b", "c"); + assertTextArray("Indirect with literal", + "1,!text/indirect_string_with_literal,2", "1", "x", "a", "b", "c", "y", "2"); + assertTextArray("Indirect2", + "!text/indirect2_string", "a", "b", "c"); + } + + public void testSplitInfiniteIndirectReference() { + assertError("Infinite indirection", + "1,!text/infinite_indirection,2", "1", "infinite", "", "loop", "2"); + } + + public void testLabelReferece() { + assertTextArray("Label time am", "!text/label_time_am", "AM"); + + assertTextArray("More keys for am pm", "!text/more_keys_for_am_pm", + "!fixedColumnOrder!2", "!hasLabels!", "AM", "PM"); + + assertTextArray("Settings as more key", "!text/settings_as_more_key", + "!icon/settings_key|!code/key_settings"); + + assertTextArray("Indirect naviagte actions as more key", + "!text/indirect_navigate_actions_as_more_key", + "!fixedColumnOrder!2", + "!hasLabels!", "Prev|!code/key_action_previous", + "!hasLabels!", "Next|!code/key_action_next"); + } + + public void testUselessUpperCaseSpecifier() { + assertTextArray("EMPTY STRING", + "!TEXT/EMPTY_STRING", "!TEXT/EMPTY_STRING"); + + assertTextArray("SINGLE CHAR", + "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_CHAR"); + assertTextArray("Escape and SINGLE CHAR", + "\\\\!TEXT/SINGLE_CHAR", "\\\\!TEXT/SINGLE_CHAR"); + + assertTextArray("MULTIPLE CHARS", + "!TEXT/MULTIPLE_CHARS", "!TEXT/MULTIPLE_CHARS"); + + assertTextArray("Literals and RESOURCES", + "1,!TEXT/MULTIPLE_CHARS,z", "1", "!TEXT/MULTIPLE_CHARS", "z"); + assertTextArray("Multiple single RESOURCE chars and LABELS 2", + "!TEXT/SINGLE_CHAR,!TEXT/SINGLE_LABEL,!TEXT/ESCAPED_COMMA_ESCAPE", + "!TEXT/SINGLE_CHAR", "!TEXT/SINGLE_LABEL", "!TEXT/ESCAPED_COMMA_ESCAPE"); + + assertTextArray("INDIRECT", + "!TEXT/INDIRECT_STRING", "!TEXT/INDIRECT_STRING"); + assertTextArray("INDIRECT with literal", + "1,!TEXT/INDIRECT_STRING_WITH_LITERAL,2", + "1", "!TEXT/INDIRECT_STRING_WITH_LITERAL", "2"); + assertTextArray("INDIRECT2", + "!TEXT/INDIRECT2_STRING", "!TEXT/INDIRECT2_STRING"); + + assertTextArray("Upper indirect", + "!text/upper_indirect_string", "!TEXT/MULTIPLE_CHARS"); + assertTextArray("Upper indirect with literal", + "1,!text/upper_indirect_string_with_literal,2", + "1", "x", "!TEXT/MULTIPLE_CHARS", "y", "2"); + assertTextArray("Upper indirect2", + "!text/upper_indirect2_string", "!TEXT/UPPER_INDIRECT_STRING"); + + assertTextArray("UPPER INDIRECT", + "!TEXT/upper_INDIRECT_STRING", "!TEXT/upper_INDIRECT_STRING"); + assertTextArray("Upper INDIRECT with literal", + "1,!TEXT/upper_INDIRECT_STRING_WITH_LITERAL,2", + "1", "!TEXT/upper_INDIRECT_STRING_WITH_LITERAL", "2"); + assertTextArray("Upper INDIRECT2", + "!TEXT/upper_INDIRECT2_STRING", "!TEXT/upper_INDIRECT2_STRING"); + + assertTextArray("INFINITE INDIRECTION", + "1,!TEXT/INFINITE_INDIRECTION,2", "1", "!TEXT/INFINITE_INDIRECTION", "2"); + + assertTextArray("Upper infinite indirection", + "1,!text/upper_infinite_indirection,2", + "1", "infinite", "!TEXT/INFINITE_INDIRECTION", "loop", "2"); + assertTextArray("Upper INFINITE INDIRECTION", + "1,!TEXT/UPPER_INFINITE_INDIRECTION,2", + "1", "!TEXT/UPPER_INFINITE_INDIRECTION", "2"); + + assertTextArray("LABEL TIME AM", "!TEXT/LABEL_TIME_AM", "!TEXT/LABEL_TIME_AM"); + assertTextArray("MORE KEYS FOR AM OM", "!TEXT/MORE_KEYS_FOR_AM_PM", + "!TEXT/MORE_KEYS_FOR_AM_PM"); + assertTextArray("SETTINGS AS MORE KEY", "!TEXT/SETTINGS_AS_MORE_KEY", + "!TEXT/SETTINGS_AS_MORE_KEY"); + assertTextArray("INDIRECT NAVIGATE ACTIONS AS MORE KEY", + "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY", + "!TEXT/INDIRECT_NAVIGATE_ACTIONS_AS_MORE_KEY"); + } +} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java new file mode 100644 index 000000000..538ba2ccf --- /dev/null +++ b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecTests.java @@ -0,0 +1,662 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import static com.android.inputmethod.keyboard.internal.KeyboardIconsSet.ICON_UNDEFINED; +import static com.android.inputmethod.latin.Constants.CODE_OUTPUT_TEXT; +import static com.android.inputmethod.latin.Constants.CODE_UNSPECIFIED; + +import android.content.Context; +import android.content.res.Resources; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.utils.RunInLocale; + +import java.util.Arrays; +import java.util.Locale; + +@SmallTest +public class MoreKeySpecTests extends AndroidTestCase { + private final static Locale TEST_LOCALE = Locale.ENGLISH; + final KeyboardCodesSet mCodesSet = new KeyboardCodesSet(); + final KeyboardTextsSet mTextsSet = new KeyboardTextsSet(); + + private static final String CODE_SETTINGS = "!code/key_settings"; + private static final String ICON_SETTINGS = "!icon/settings_key"; + private static final String CODE_SETTINGS_UPPERCASE = CODE_SETTINGS.toUpperCase(Locale.ROOT); + private static final String ICON_SETTINGS_UPPERCASE = ICON_SETTINGS.toUpperCase(Locale.ROOT); + private static final String CODE_NON_EXISTING = "!code/non_existing"; + private static final String ICON_NON_EXISTING = "!icon/non_existing"; + + private int mCodeSettings; + private int mCodeActionNext; + private int mSettingsIconId; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + final String language = TEST_LOCALE.getLanguage(); + mCodesSet.setLanguage(language); + mTextsSet.setLanguage(language); + final Context context = getContext(); + new RunInLocale() { + @Override + protected Void job(final Resources res) { + mTextsSet.loadStringResources(context); + return null; + } + }.runInLocale(context.getResources(), TEST_LOCALE); + + mCodeSettings = KeySpecParser.parseCode( + CODE_SETTINGS, mCodesSet, CODE_UNSPECIFIED); + mCodeActionNext = KeySpecParser.parseCode( + "!code/key_action_next", mCodesSet, CODE_UNSPECIFIED); + mSettingsIconId = KeySpecParser.getIconId(ICON_SETTINGS); + } + + private void assertParser(final String message, final String moreKeySpec, + final String expectedLabel, final String expectedOutputText, final int expectedIcon, + final int expectedCode) { + final String labelResolved = mTextsSet.resolveTextReference(moreKeySpec); + final MoreKeySpec spec = new MoreKeySpec(labelResolved, false /* needsToUpperCase */, + Locale.US, mCodesSet); + assertEquals(message + " [label]", expectedLabel, spec.mLabel); + assertEquals(message + " [ouptputText]", expectedOutputText, spec.mOutputText); + assertEquals(message + " [icon]", + KeyboardIconsSet.getIconName(expectedIcon), + KeyboardIconsSet.getIconName(spec.mIconId)); + assertEquals(message + " [code]", + Constants.printableCode(expectedCode), + Constants.printableCode(spec.mCode)); + } + + private void assertParserError(final String message, final String moreKeySpec, + final String expectedLabel, final String expectedOutputText, final int expectedIcon, + final int expectedCode) { + try { + assertParser(message, moreKeySpec, expectedLabel, expectedOutputText, expectedIcon, + expectedCode); + fail(message); + } catch (Exception pcpe) { + // success. + } + } + + // \U001d11e: MUSICAL SYMBOL G CLEF + private static final String PAIR1 = "\ud834\udd1e"; + private static final int CODE1 = PAIR1.codePointAt(0); + // \U001d122: MUSICAL SYMBOL F CLEF + private static final String PAIR2 = "\ud834\udd22"; + private static final int CODE2 = PAIR2.codePointAt(0); + // \U002f8a6: CJK COMPATIBILITY IDEOGRAPH-2F8A6; variant character of \u6148. + private static final String PAIR3 = "\ud87e\udca6"; + private static final String SURROGATE1 = PAIR1 + PAIR2; + private static final String SURROGATE2 = PAIR1 + PAIR2 + PAIR3; + + public void testSingleLetter() { + assertParser("Single letter", "a", + "a", null, ICON_UNDEFINED, 'a'); + assertParser("Single surrogate", PAIR1, + PAIR1, null, ICON_UNDEFINED, CODE1); + assertParser("Single escaped bar", "\\|", + "|", null, ICON_UNDEFINED, '|'); + assertParser("Single escaped escape", "\\\\", + "\\", null, ICON_UNDEFINED, '\\'); + assertParser("Single comma", ",", + ",", null, ICON_UNDEFINED, ','); + assertParser("Single escaped comma", "\\,", + ",", null, ICON_UNDEFINED, ','); + assertParser("Single escaped letter", "\\a", + "a", null, ICON_UNDEFINED, 'a'); + assertParser("Single escaped surrogate", "\\" + PAIR2, + PAIR2, null, ICON_UNDEFINED, CODE2); + assertParser("Single bang", "!", + "!", null, ICON_UNDEFINED, '!'); + assertParser("Single escaped bang", "\\!", + "!", null, ICON_UNDEFINED, '!'); + assertParser("Single output text letter", "a|a", + "a", null, ICON_UNDEFINED, 'a'); + assertParser("Single surrogate pair outputText", "G Clef|" + PAIR1, + "G Clef", null, ICON_UNDEFINED, CODE1); + assertParser("Single letter with outputText", "a|abc", + "a", "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with surrogate outputText", "a|" + SURROGATE1, + "a", SURROGATE1, ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single surrogate with outputText", PAIR3 + "|abc", + PAIR3, "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with escaped outputText", "a|a\\|c", + "a", "a|c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with escaped surrogate outputText", + "a|" + PAIR1 + "\\|" + PAIR2, + "a", PAIR1 + "|" + PAIR2, ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with comma outputText", "a|a,b", + "a", "a,b", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with escaped comma outputText", "a|a\\,b", + "a", "a,b", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with outputText starts with bang", "a|!bc", + "a", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with surrogate outputText starts with bang", "a|!" + SURROGATE2, + "a", "!" + SURROGATE2, ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with outputText contains bang", "a|a!c", + "a", "a!c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single letter with escaped bang outputText", "a|\\!bc", + "a", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Single escaped escape with single outputText", "\\\\|\\\\", + "\\", null, ICON_UNDEFINED, '\\'); + assertParser("Single escaped bar with single outputText", "\\||\\|", + "|", null, ICON_UNDEFINED, '|'); + assertParser("Single letter with code", "a|" + CODE_SETTINGS, + "a", null, ICON_UNDEFINED, mCodeSettings); + } + + public void testLabel() { + assertParser("Simple label", "abc", + "abc", "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Simple surrogate label", SURROGATE1, + SURROGATE1, SURROGATE1, ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped bar", "a\\|c", + "a|c", "a|c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Surrogate label with escaped bar", PAIR1 + "\\|" + PAIR2, + PAIR1 + "|" + PAIR2, PAIR1 + "|" + PAIR2, + ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped escape", "a\\\\c", + "a\\c", "a\\c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with comma", "a,c", + "a,c", "a,c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped comma", "a\\,c", + "a,c", "a,c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label starts with bang", "!bc", + "!bc", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Surrogate label starts with bang", "!" + SURROGATE1, + "!" + SURROGATE1, "!" + SURROGATE1, ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label contains bang", "a!c", + "a!c", "a!c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped bang", "\\!bc", + "!bc", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped letter", "\\abc", + "abc", "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with outputText", "abc|def", + "abc", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with comma and outputText", "a,c|def", + "a,c", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Escaped comma label with outputText", "a\\,c|def", + "a,c", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Escaped label with outputText", "a\\|c|def", + "a|c", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped bar outputText", "abc|d\\|f", + "abc", "d|f", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Escaped escape label with outputText", "a\\\\|def", + "a\\", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label starts with bang and outputText", "!bc|def", + "!bc", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label contains bang label and outputText", "a!c|def", + "a!c", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Escaped bang label with outputText", "\\!bc|def", + "!bc", "def", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with comma outputText", "abc|a,b", + "abc", "a,b", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped comma outputText", "abc|a\\,b", + "abc", "a,b", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with outputText starts with bang", "abc|!bc", + "abc", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with outputText contains bang", "abc|a!c", + "abc", "a!c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped bang outputText", "abc|\\!bc", + "abc", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with escaped bar outputText", "abc|d\\|f", + "abc", "d|f", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Escaped bar label with escaped bar outputText", "a\\|c|d\\|f", + "a|c", "d|f", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with code", "abc|" + CODE_SETTINGS, + "abc", null, ICON_UNDEFINED, mCodeSettings); + assertParser("Escaped label with code", "a\\|c|" + CODE_SETTINGS, + "a|c", null, ICON_UNDEFINED, mCodeSettings); + } + + public void testIconAndCode() { + assertParser("Icon with outputText", ICON_SETTINGS + "|abc", + null, "abc", mSettingsIconId, CODE_OUTPUT_TEXT); + assertParser("Icon with outputText starts with bang", ICON_SETTINGS + "|!bc", + null, "!bc", mSettingsIconId, CODE_OUTPUT_TEXT); + assertParser("Icon with outputText contains bang", ICON_SETTINGS + "|a!c", + null, "a!c", mSettingsIconId, CODE_OUTPUT_TEXT); + assertParser("Icon with escaped bang outputText", ICON_SETTINGS + "|\\!bc", + null, "!bc", mSettingsIconId, CODE_OUTPUT_TEXT); + assertParser("Label starts with bang and code", "!bc|" + CODE_SETTINGS, + "!bc", null, ICON_UNDEFINED, mCodeSettings); + assertParser("Label contains bang and code", "a!c|" + CODE_SETTINGS, + "a!c", null, ICON_UNDEFINED, mCodeSettings); + assertParser("Escaped bang label with code", "\\!bc|" + CODE_SETTINGS, + "!bc", null, ICON_UNDEFINED, mCodeSettings); + assertParser("Icon with code", ICON_SETTINGS + "|" + CODE_SETTINGS, + null, null, mSettingsIconId, mCodeSettings); + } + + public void testResourceReference() { + assertParser("Settings as more key", "!text/settings_as_more_key", + null, null, mSettingsIconId, mCodeSettings); + + assertParser("Action next as more key", "!text/label_next_key|!code/key_action_next", + "Next", null, ICON_UNDEFINED, mCodeActionNext); + + assertParser("Popular domain", + "!text/keylabel_for_popular_domain|!text/keylabel_for_popular_domain ", + ".com", ".com ", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + } + + public void testFormatError() { + assertParserError("Empty spec", "", null, + null, ICON_UNDEFINED, CODE_UNSPECIFIED); + assertParserError("Empty label with outputText", "|a", + null, "a", ICON_UNDEFINED, CODE_UNSPECIFIED); + assertParserError("Empty label with code", "|" + CODE_SETTINGS, + null, null, ICON_UNDEFINED, mCodeSettings); + assertParserError("Empty outputText with label", "a|", + "a", null, ICON_UNDEFINED, CODE_UNSPECIFIED); + assertParserError("Empty outputText with icon", ICON_SETTINGS + "|", + null, null, mSettingsIconId, CODE_UNSPECIFIED); + assertParserError("Empty icon and code", "|", + null, null, ICON_UNDEFINED, CODE_UNSPECIFIED); + assertParserError("Icon without code", ICON_SETTINGS, + null, null, mSettingsIconId, CODE_UNSPECIFIED); + assertParserError("Non existing icon", ICON_NON_EXISTING + "|abc", + null, "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParserError("Non existing code", "abc|" + CODE_NON_EXISTING, + "abc", null, ICON_UNDEFINED, CODE_UNSPECIFIED); + assertParserError("Third bar at end", "a|b|", + "a", null, ICON_UNDEFINED, CODE_UNSPECIFIED); + assertParserError("Multiple bar", "a|b|c", + "a", null, ICON_UNDEFINED, CODE_UNSPECIFIED); + assertParserError("Multiple bar with label and code", "a|" + CODE_SETTINGS + "|c", + "a", null, ICON_UNDEFINED, mCodeSettings); + assertParserError("Multiple bar with icon and outputText", ICON_SETTINGS + "|b|c", + null, null, mSettingsIconId, CODE_UNSPECIFIED); + assertParserError("Multiple bar with icon and code", + ICON_SETTINGS + "|" + CODE_SETTINGS + "|c", + null, null, mSettingsIconId, mCodeSettings); + } + + public void testUselessUpperCaseSpecifier() { + assertParser("Single letter with CODE", "a|" + CODE_SETTINGS_UPPERCASE, + "a", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label with CODE", "abc|" + CODE_SETTINGS_UPPERCASE, + "abc", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Escaped label with CODE", "a\\|c|" + CODE_SETTINGS_UPPERCASE, + "a|c", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("ICON with outputText", ICON_SETTINGS_UPPERCASE + "|abc", + "!ICON/SETTINGS_KEY", "abc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("ICON with outputText starts with bang", ICON_SETTINGS_UPPERCASE + "|!bc", + "!ICON/SETTINGS_KEY", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("ICON with outputText contains bang", ICON_SETTINGS_UPPERCASE + "|a!c", + "!ICON/SETTINGS_KEY", "a!c", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("ICON with escaped bang outputText", ICON_SETTINGS_UPPERCASE + "|\\!bc", + "!ICON/SETTINGS_KEY", "!bc", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label starts with bang and CODE", "!bc|" + CODE_SETTINGS_UPPERCASE, + "!bc", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Label contains bang and CODE", "a!c|" + CODE_SETTINGS_UPPERCASE, + "a!c", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("Escaped bang label with CODE", "\\!bc|" + CODE_SETTINGS_UPPERCASE, + "!bc", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("ICON with CODE", ICON_SETTINGS_UPPERCASE + "|" + CODE_SETTINGS_UPPERCASE, + "!ICON/SETTINGS_KEY", "!CODE/KEY_SETTINGS", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParser("SETTINGS AS MORE KEY", "!TEXT/SETTINGS_AS_MORE_KEY", + "!TEXT/SETTINGS_AS_MORE_KEY", "!TEXT/SETTINGS_AS_MORE_KEY", ICON_UNDEFINED, + CODE_OUTPUT_TEXT); + assertParser("ACTION NEXT AS MORE KEY", "!TEXT/LABEL_NEXT_KEY|!CODE/KEY_ACTION_NEXT", + "!TEXT/LABEL_NEXT_KEY", "!CODE/KEY_ACTION_NEXT", ICON_UNDEFINED, + CODE_OUTPUT_TEXT); + assertParser("POPULAR DOMAIN", + "!TEXT/KEYLABEL_FOR_POPULAR_DOMAIN|!TEXT/KEYLABEL_FOR_POPULAR_DOMAIN ", + "!TEXT/KEYLABEL_FOR_POPULAR_DOMAIN", "!TEXT/KEYLABEL_FOR_POPULAR_DOMAIN ", + ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParserError("Empty label with CODE", "|" + CODE_SETTINGS_UPPERCASE, + null, null, ICON_UNDEFINED, mCodeSettings); + assertParserError("Empty outputText with ICON", ICON_SETTINGS_UPPERCASE + "|", + null, null, mSettingsIconId, CODE_UNSPECIFIED); + assertParser("ICON without code", ICON_SETTINGS_UPPERCASE, + "!ICON/SETTINGS_KEY", "!ICON/SETTINGS_KEY", ICON_UNDEFINED, CODE_OUTPUT_TEXT); + assertParserError("Multiple bar with label and CODE", "a|" + CODE_SETTINGS_UPPERCASE + "|c", + "a", null, ICON_UNDEFINED, mCodeSettings); + assertParserError("Multiple bar with ICON and outputText", ICON_SETTINGS_UPPERCASE + "|b|c", + null, null, mSettingsIconId, CODE_UNSPECIFIED); + assertParserError("Multiple bar with ICON and CODE", + ICON_SETTINGS_UPPERCASE + "|" + CODE_SETTINGS_UPPERCASE + "|c", + null, null, mSettingsIconId, mCodeSettings); + } + + private static void assertArrayEquals(final String message, final Object[] expected, + final Object[] actual) { + if (expected == actual) { + return; + } + if (expected == null || actual == null) { + assertEquals(message, Arrays.toString(expected), Arrays.toString(actual)); + return; + } + if (expected.length != actual.length) { + assertEquals(message + " [length]", Arrays.toString(expected), Arrays.toString(actual)); + return; + } + for (int i = 0; i < expected.length; i++) { + assertEquals(message + " [" + i + "]", + Arrays.toString(expected), Arrays.toString(actual)); + } + } + + private static void assertInsertAdditionalMoreKeys(final String message, + final String[] moreKeys, final String[] additionalMoreKeys, final String[] expected) { + final String[] actual = MoreKeySpec.insertAdditionalMoreKeys(moreKeys, additionalMoreKeys); + assertArrayEquals(message, expected, actual); + } + + public void testEmptyEntry() { + assertInsertAdditionalMoreKeys("null more keys and null additons", + null, + null, + null); + assertInsertAdditionalMoreKeys("null more keys and empty additons", + null, + new String[0], + null); + assertInsertAdditionalMoreKeys("empty more keys and null additons", + new String[0], + null, + null); + assertInsertAdditionalMoreKeys("empty more keys and empty additons", + new String[0], + new String[0], + null); + + assertInsertAdditionalMoreKeys("filter out empty more keys", + new String[] { null, "a", "", "b", null }, + null, + new String[] { "a", "b" }); + assertInsertAdditionalMoreKeys("filter out empty additons", + new String[] { "a", "%", "b", "%", "c", "%", "d" }, + new String[] { null, "A", "", "B", null }, + new String[] { "a", "A", "b", "B", "c", "d" }); + } + + public void testInsertAdditionalMoreKeys() { + // Escaped marker. + assertInsertAdditionalMoreKeys("escaped marker", + new String[] { "\\%", "%-)" }, + new String[] { "1", "2" }, + new String[] { "1", "2", "\\%", "%-)" }); + + // 0 more key. + assertInsertAdditionalMoreKeys("null & null", null, null, null); + assertInsertAdditionalMoreKeys("null & 1 additon", + null, + new String[] { "1" }, + new String[] { "1" }); + assertInsertAdditionalMoreKeys("null & 2 additons", + null, + new String[] { "1", "2" }, + new String[] { "1", "2" }); + + // 0 additional more key. + assertInsertAdditionalMoreKeys("1 more key & null", + new String[] { "A" }, + null, + new String[] { "A" }); + assertInsertAdditionalMoreKeys("2 more keys & null", + new String[] { "A", "B" }, + null, + new String[] { "A", "B" }); + + // No marker. + assertInsertAdditionalMoreKeys("1 more key & 1 addtional & no marker", + new String[] { "A" }, + new String[] { "1" }, + new String[] { "1", "A" }); + assertInsertAdditionalMoreKeys("1 more key & 2 addtionals & no marker", + new String[] { "A" }, + new String[] { "1", "2" }, + new String[] { "1", "2", "A" }); + assertInsertAdditionalMoreKeys("2 more keys & 1 addtional & no marker", + new String[] { "A", "B" }, + new String[] { "1" }, + new String[] { "1", "A", "B" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 addtionals & no marker", + new String[] { "A", "B" }, + new String[] { "1", "2" }, + new String[] { "1", "2", "A", "B" }); + + // 1 marker. + assertInsertAdditionalMoreKeys("1 more key & 1 additon & marker at head", + new String[] { "%", "A" }, + new String[] { "1" }, + new String[] { "1", "A" }); + assertInsertAdditionalMoreKeys("1 more key & 1 additon & marker at tail", + new String[] { "A", "%" }, + new String[] { "1" }, + new String[] { "A", "1" }); + assertInsertAdditionalMoreKeys("2 more keys & 1 additon & marker at middle", + new String[] { "A", "%", "B" }, + new String[] { "1" }, + new String[] { "A", "1", "B" }); + + // 1 marker & excess additional more keys. + assertInsertAdditionalMoreKeys("1 more key & 2 additons & marker at head", + new String[] { "%", "A", "B" }, + new String[] { "1", "2" }, + new String[] { "1", "A", "B", "2" }); + assertInsertAdditionalMoreKeys("1 more key & 2 additons & marker at tail", + new String[] { "A", "B", "%" }, + new String[] { "1", "2" }, + new String[] { "A", "B", "1", "2" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 additons & marker at middle", + new String[] { "A", "%", "B" }, + new String[] { "1", "2" }, + new String[] { "A", "1", "B", "2" }); + + // 2 markers. + assertInsertAdditionalMoreKeys("0 more key & 2 addtional & 2 markers", + new String[] { "%", "%" }, + new String[] { "1", "2" }, + new String[] { "1", "2" }); + assertInsertAdditionalMoreKeys("1 more key & 2 addtional & 2 markers at head", + new String[] { "%", "%", "A" }, + new String[] { "1", "2" }, + new String[] { "1", "2", "A" }); + assertInsertAdditionalMoreKeys("1 more key & 2 addtional & 2 markers at tail", + new String[] { "A", "%", "%" }, + new String[] { "1", "2" }, + new String[] { "A", "1", "2" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 addtional & 2 markers at middle", + new String[] { "A", "%", "%", "B" }, + new String[] { "1", "2" }, + new String[] { "A", "1", "2", "B" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 addtional & 2 markers at head & middle", + new String[] { "%", "A", "%", "B" }, + new String[] { "1", "2" }, + new String[] { "1", "A", "2", "B" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 addtional & 2 markers at head & tail", + new String[] { "%", "A", "B", "%" }, + new String[] { "1", "2" }, + new String[] { "1", "A", "B", "2" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 addtional & 2 markers at middle & tail", + new String[] { "A", "%", "B", "%" }, + new String[] { "1", "2" }, + new String[] { "A", "1", "B", "2" }); + + // 2 markers & excess additional more keys. + assertInsertAdditionalMoreKeys("0 more key & 2 additons & 2 markers", + new String[] { "%", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "2", "3" }); + assertInsertAdditionalMoreKeys("1 more key & 2 additons & 2 markers at head", + new String[] { "%", "%", "A" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "2", "A", "3" }); + assertInsertAdditionalMoreKeys("1 more key & 2 additons & 2 markers at tail", + new String[] { "A", "%", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "A", "1", "2", "3" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 additons & 2 markers at middle", + new String[] { "A", "%", "%", "B" }, + new String[] { "1", "2", "3" }, + new String[] { "A", "1", "2", "B", "3" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 additons & 2 markers at head & middle", + new String[] { "%", "A", "%", "B" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "A", "2", "B", "3" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 additons & 2 markers at head & tail", + new String[] { "%", "A", "B", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "A", "B", "2", "3" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 additons & 2 markers at middle & tail", + new String[] { "A", "%", "B", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "A", "1", "B", "2", "3" }); + + // 0 addtional more key and excess markers. + assertInsertAdditionalMoreKeys("0 more key & null & excess marker", + new String[] { "%" }, + null, + null); + assertInsertAdditionalMoreKeys("1 more key & null & excess marker at head", + new String[] { "%", "A" }, + null, + new String[] { "A" }); + assertInsertAdditionalMoreKeys("1 more key & null & excess marker at tail", + new String[] { "A", "%" }, + null, + new String[] { "A" }); + assertInsertAdditionalMoreKeys("2 more keys & null & excess marker at middle", + new String[] { "A", "%", "B" }, + null, + new String[] { "A", "B" }); + assertInsertAdditionalMoreKeys("2 more keys & null & excess markers", + new String[] { "%", "A", "%", "B", "%" }, + null, + new String[] { "A", "B" }); + + // Excess markers. + assertInsertAdditionalMoreKeys("0 more key & 1 additon & excess marker", + new String[] { "%", "%" }, + new String[] { "1" }, + new String[] { "1" }); + assertInsertAdditionalMoreKeys("1 more key & 1 additon & excess marker at head", + new String[] { "%", "%", "A" }, + new String[] { "1" }, + new String[] { "1", "A" }); + assertInsertAdditionalMoreKeys("1 more key & 1 additon & excess marker at tail", + new String[] { "A", "%", "%" }, + new String[] { "1" }, + new String[] { "A", "1" }); + assertInsertAdditionalMoreKeys("2 more keys & 1 additon & excess marker at middle", + new String[] { "A", "%", "%", "B" }, + new String[] { "1" }, + new String[] { "A", "1", "B" }); + assertInsertAdditionalMoreKeys("2 more keys & 1 additon & excess markers", + new String[] { "%", "A", "%", "B", "%" }, + new String[] { "1" }, + new String[] { "1", "A", "B" }); + assertInsertAdditionalMoreKeys("2 more keys & 2 additons & excess markers", + new String[] { "%", "A", "%", "B", "%" }, + new String[] { "1", "2" }, + new String[] { "1", "A", "2", "B" }); + assertInsertAdditionalMoreKeys("2 more keys & 3 additons & excess markers", + new String[] { "%", "A", "%", "%", "B", "%" }, + new String[] { "1", "2", "3" }, + new String[] { "1", "A", "2", "3", "B" }); + } + + private static final String HAS_LABEL = "!hasLabel!"; + private static final String NEEDS_DIVIDER = "!needsDividers!"; + private static final String AUTO_COLUMN_ORDER = "!autoColumnOrder!"; + private static final String FIXED_COLUMN_ORDER = "!fixedColumnOrder!"; + + private static void assertGetBooleanValue(final String message, final String key, + final String[] moreKeys, final String[] expected, final boolean expectedValue) { + final String[] actual = Arrays.copyOf(moreKeys, moreKeys.length); + final boolean actualValue = MoreKeySpec.getBooleanValue(actual, key); + assertEquals(message + " [value]", expectedValue, actualValue); + assertArrayEquals(message, expected, actual); + } + + public void testGetBooleanValue() { + assertGetBooleanValue("Has label", HAS_LABEL, + new String[] { HAS_LABEL, "a", "b", "c" }, + new String[] { null, "a", "b", "c" }, true); + // Upper case specification will not work. + assertGetBooleanValue("HAS LABEL", HAS_LABEL, + new String[] { HAS_LABEL.toUpperCase(Locale.ROOT), "a", "b", "c" }, + new String[] { "!HASLABEL!", "a", "b", "c" }, false); + + assertGetBooleanValue("No has label", HAS_LABEL, + new String[] { "a", "b", "c" }, + new String[] { "a", "b", "c" }, false); + assertGetBooleanValue("No has label with fixed clumn order", HAS_LABEL, + new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" }, + new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" }, false); + + // Upper case specification will not work. + assertGetBooleanValue("Multiple has label", HAS_LABEL, + new String[] { + "a", HAS_LABEL.toUpperCase(Locale.ROOT), "b", "c", HAS_LABEL, "d" }, + new String[] { + "a", "!HASLABEL!", "b", "c", null, "d" }, true); + // Upper case specification will not work. + assertGetBooleanValue("Multiple has label with needs dividers", HAS_LABEL, + new String[] { + "a", HAS_LABEL, "b", NEEDS_DIVIDER, HAS_LABEL.toUpperCase(Locale.ROOT), "d" }, + new String[] { + "a", null, "b", NEEDS_DIVIDER, "!HASLABEL!", "d" }, true); + } + + private static void assertGetIntValue(final String message, final String key, + final int defaultValue, final String[] moreKeys, final String[] expected, + final int expectedValue) { + final String[] actual = Arrays.copyOf(moreKeys, moreKeys.length); + final int actualValue = MoreKeySpec.getIntValue(actual, key, defaultValue); + assertEquals(message + " [value]", expectedValue, actualValue); + assertArrayEquals(message, expected, actual); + } + + public void testGetIntValue() { + assertGetIntValue("Fixed column order 3", FIXED_COLUMN_ORDER, -1, + new String[] { FIXED_COLUMN_ORDER + "3", "a", "b", "c" }, + new String[] { null, "a", "b", "c" }, 3); + // Upper case specification will not work. + assertGetIntValue("FIXED COLUMN ORDER 3", FIXED_COLUMN_ORDER, -1, + new String[] { FIXED_COLUMN_ORDER.toUpperCase(Locale.ROOT) + "3", "a", "b", "c" }, + new String[] { "!FIXEDCOLUMNORDER!3", "a", "b", "c" }, -1); + + assertGetIntValue("No fixed column order", FIXED_COLUMN_ORDER, -1, + new String[] { "a", "b", "c" }, + new String[] { "a", "b", "c" }, -1); + assertGetIntValue("No fixed column order with auto column order", FIXED_COLUMN_ORDER, -1, + new String[] { AUTO_COLUMN_ORDER + "5", "a", "b", "c" }, + new String[] { AUTO_COLUMN_ORDER + "5", "a", "b", "c" }, -1); + + assertGetIntValue("Multiple fixed column order 3,5", FIXED_COLUMN_ORDER, -1, + new String[] { FIXED_COLUMN_ORDER + "3", "a", FIXED_COLUMN_ORDER + "5", "b" }, + new String[] { null, "a", null, "b" }, 3); + // Upper case specification will not work. + assertGetIntValue("Multiple fixed column order 5,3 with has label", FIXED_COLUMN_ORDER, -1, + new String[] { + FIXED_COLUMN_ORDER.toUpperCase(Locale.ROOT) + "5", HAS_LABEL, "a", + FIXED_COLUMN_ORDER + "3", "b" }, + new String[] { "!FIXEDCOLUMNORDER!5", HAS_LABEL, "a", null, "b" }, 3); + } +} -- cgit v1.2.3-83-g751a