diff options
author | 2024-12-16 21:45:41 -0500 | |
---|---|---|
committer | 2025-01-11 14:17:35 -0500 | |
commit | e9a0e66716dab4dd3184d009d8920de1961efdfa (patch) | |
tree | 02dcc096643d74645bf28459c2834c3d4a2ad7f2 /tests/src/org/kelar/inputmethod/latin/utils | |
parent | fb3b9360d70596d7e921de8bf7d3ca99564a077e (diff) | |
download | latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.gz latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.xz latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.zip |
Rename to Kelar Keyboard (org.kelar.inputmethod.latin)
Diffstat (limited to 'tests/src/org/kelar/inputmethod/latin/utils')
14 files changed, 2275 insertions, 0 deletions
diff --git a/tests/src/org/kelar/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java new file mode 100644 index 000000000..7c929c7a1 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/AdditionalSubtypeUtilsTests.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2014 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 org.kelar.inputmethod.latin.utils; + +import static org.kelar.inputmethod.latin.common.Constants.Subtype.ExtraValue.ASCII_CAPABLE; +import static org.kelar.inputmethod.latin.common.Constants.Subtype.ExtraValue.EMOJI_CAPABLE; +import static org.kelar.inputmethod.latin.common.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE; +import static org.kelar.inputmethod.latin.common.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; +import static org.kelar.inputmethod.latin.common.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; +import static org.kelar.inputmethod.latin.common.Constants.Subtype.KEYBOARD_MODE; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.os.Build; +import android.view.inputmethod.InputMethodSubtype; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.kelar.inputmethod.compat.InputMethodSubtypeCompatUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Locale; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AdditionalSubtypeUtilsTests { + + /** + * Predictable subtype ID for en_US dvorak layout. This is actually a hash code calculated as + * follows. + * <code> + * final boolean isAuxiliary = false; + * final boolean overrideImplicitlyEnabledSubtype = false; + * final int SUBTYPE_ID_EN_US_DVORAK = Arrays.hashCode(new Object[] { + * "en_US", + * "keyboard", + * "KeyboardLayoutSet=dvorak" + * + ",AsciiCapable" + * + ",UntranslatableReplacementStringInSubtypeName=Dvorak" + * + ",EmojiCapable" + * + ",isAdditionalSubtype", + * isAuxiliary, + * overrideImplicitlyEnabledSubtype }); + * </code> + */ + private static int SUBTYPE_ID_EN_US_DVORAK = 0xb3c0cc56; + private static String EXTRA_VALUE_EN_US_DVORAK_ICS = + "KeyboardLayoutSet=dvorak" + + ",AsciiCapable" + + ",isAdditionalSubtype"; + private static String EXTRA_VALUE_EN_US_DVORAK_JELLY_BEAN = + "KeyboardLayoutSet=dvorak" + + ",AsciiCapable" + + ",UntranslatableReplacementStringInSubtypeName=Dvorak" + + ",isAdditionalSubtype"; + private static String EXTRA_VALUE_EN_US_DVORAK_KITKAT = + "KeyboardLayoutSet=dvorak" + + ",AsciiCapable" + + ",UntranslatableReplacementStringInSubtypeName=Dvorak" + + ",EmojiCapable" + + ",isAdditionalSubtype"; + + /** + * Predictable subtype ID for azerty layout. This is actually a hash code calculated as follows. + * <code> + * final boolean isAuxiliary = false; + * final boolean overrideImplicitlyEnabledSubtype = false; + * final int SUBTYPE_ID_ZZ_AZERTY = Arrays.hashCode(new Object[] { + * "zz", + * "keyboard", + * "KeyboardLayoutSet=azerty" + * + ",AsciiCapable" + * + ",EmojiCapable" + * + ",isAdditionalSubtype", + * isAuxiliary, + * overrideImplicitlyEnabledSubtype }); + * </code> + */ + private static int SUBTYPE_ID_ZZ_AZERTY = 0x5b6be697; + private static String EXTRA_VALUE_ZZ_AZERTY_ICS = + "KeyboardLayoutSet=azerty" + + ",AsciiCapable" + + ",isAdditionalSubtype"; + private static String EXTRA_VALUE_ZZ_AZERTY_KITKAT = + "KeyboardLayoutSet=azerty" + + ",AsciiCapable" + + ",EmojiCapable" + + ",isAdditionalSubtype"; + + @Before + public void setUp() throws Exception { + final Context context = InstrumentationRegistry.getTargetContext(); + SubtypeLocaleUtils.init(context); + } + + private static void assertEnUsDvorak(InputMethodSubtype subtype) { + assertEquals("en_US", subtype.getLocale()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + assertEquals(EXTRA_VALUE_EN_US_DVORAK_KITKAT, subtype.getExtraValue()); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + assertEquals(EXTRA_VALUE_EN_US_DVORAK_JELLY_BEAN, subtype.getExtraValue()); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + assertEquals(EXTRA_VALUE_EN_US_DVORAK_ICS, subtype.getExtraValue()); + } + assertTrue(subtype.containsExtraValueKey(ASCII_CAPABLE)); + assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)); + // TODO: Enable following test + // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapableWithAPI(subtype)); + // } + assertTrue(subtype.containsExtraValueKey(EMOJI_CAPABLE)); + assertTrue(subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE)); + assertEquals("dvorak", subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET)); + assertEquals("Dvorak", subtype.getExtraValueOf(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)); + assertEquals(KEYBOARD_MODE, subtype.getMode()); + assertEquals(SUBTYPE_ID_EN_US_DVORAK, subtype.hashCode()); + } + + private static void assertAzerty(InputMethodSubtype subtype) { + assertEquals("zz", subtype.getLocale()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + assertEquals(EXTRA_VALUE_ZZ_AZERTY_KITKAT, subtype.getExtraValue()); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + assertEquals(EXTRA_VALUE_ZZ_AZERTY_ICS, subtype.getExtraValue()); + } + assertTrue(subtype.containsExtraValueKey(ASCII_CAPABLE)); + assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapable(subtype)); + // TODO: Enable following test + // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // assertTrue(InputMethodSubtypeCompatUtils.isAsciiCapableWithAPI(subtype)); + // } + assertTrue(subtype.containsExtraValueKey(EMOJI_CAPABLE)); + assertTrue(subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE)); + assertEquals("azerty", subtype.getExtraValueOf(KEYBOARD_LAYOUT_SET)); + assertFalse(subtype.containsExtraValueKey(UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)); + assertEquals(KEYBOARD_MODE, subtype.getMode()); + assertEquals(SUBTYPE_ID_ZZ_AZERTY, subtype.hashCode()); + } + + @Test + public void testRestorable() { + final InputMethodSubtype EN_US_DVORAK = + AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + Locale.US.toString(), "dvorak"); + final InputMethodSubtype ZZ_AZERTY = + AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + SubtypeLocaleUtils.NO_LANGUAGE, "azerty"); + assertEnUsDvorak(EN_US_DVORAK); + assertAzerty(ZZ_AZERTY); + + // Make sure the subtype can be stored and restored in a deterministic manner. + final InputMethodSubtype[] subtypes = { EN_US_DVORAK, ZZ_AZERTY }; + final String prefSubtype = AdditionalSubtypeUtils.createPrefSubtypes(subtypes); + final InputMethodSubtype[] restoredSubtypes = + AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefSubtype); + assertEquals(2, restoredSubtypes.length); + final InputMethodSubtype restored_EN_US_DVORAK = restoredSubtypes[0]; + final InputMethodSubtype restored_ZZ_AZERTY = restoredSubtypes[1]; + + assertEnUsDvorak(restored_EN_US_DVORAK); + assertAzerty(restored_ZZ_AZERTY); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/AsyncResultHolderTests.java b/tests/src/org/kelar/inputmethod/latin/utils/AsyncResultHolderTests.java new file mode 100644 index 000000000..b85e4f38c --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/AsyncResultHolderTests.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2013 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; + +import android.util.Log; + +import androidx.test.filters.MediumTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@MediumTest +@RunWith(AndroidJUnit4.class) +public class AsyncResultHolderTests { + static final String TAG = AsyncResultHolderTests.class.getSimpleName(); + + private static final int TIMEOUT_IN_MILLISECONDS = 500; + private static final int MARGIN_IN_MILLISECONDS = 250; + private static final int DEFAULT_VALUE = 2; + private static final int SET_VALUE = 1; + + private static <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value, + final long time) { + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.sleep(time); + } catch (InterruptedException e) { + Log.d(TAG, "Exception while sleeping", e); + } + holder.set(value); + } + }).start(); + } + + @Test + public void testGetWithoutSet() { + final AsyncResultHolder<Integer> holder = new AsyncResultHolder<>("Test"); + final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); + assertEquals(DEFAULT_VALUE, resultValue); + } + + @Test + public void testGetBeforeSet() { + final AsyncResultHolder<Integer> holder = new AsyncResultHolder<>("Test"); + setAfterGivenTime(holder, SET_VALUE, TIMEOUT_IN_MILLISECONDS + MARGIN_IN_MILLISECONDS); + final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); + assertEquals(DEFAULT_VALUE, resultValue); + } + + @Test + public void testGetAfterSet() { + final AsyncResultHolder<Integer> holder = new AsyncResultHolder<>("Test"); + holder.set(SET_VALUE); + final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); + assertEquals(SET_VALUE, resultValue); + } + + @Test + public void testGetBeforeTimeout() { + final AsyncResultHolder<Integer> holder = new AsyncResultHolder<>("Test"); + setAfterGivenTime(holder, SET_VALUE, TIMEOUT_IN_MILLISECONDS - MARGIN_IN_MILLISECONDS); + final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); + assertEquals(SET_VALUE, resultValue); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/ByteArrayDictBuffer.java b/tests/src/org/kelar/inputmethod/latin/utils/ByteArrayDictBuffer.java new file mode 100644 index 000000000..6c0854824 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/ByteArrayDictBuffer.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2013 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 org.kelar.inputmethod.latin.utils; + +import org.kelar.inputmethod.latin.makedict.BinaryDictDecoderUtils.DictBuffer; + +/** + * This class provides an implementation for the FusionDictionary buffer interface that is backed + * by a simpled byte array. It allows to create a binary dictionary in memory. + */ +public final class ByteArrayDictBuffer implements DictBuffer { + private byte[] mBuffer; + private int mPosition; + + public ByteArrayDictBuffer(final byte[] buffer) { + mBuffer = buffer; + mPosition = 0; + } + + @Override + public int readUnsignedByte() { + return mBuffer[mPosition++] & 0xFF; + } + + @Override + public int readUnsignedShort() { + final int retval = readUnsignedByte(); + return (retval << 8) + readUnsignedByte(); + } + + @Override + public int readUnsignedInt24() { + final int retval = readUnsignedShort(); + return (retval << 8) + readUnsignedByte(); + } + + @Override + public int readInt() { + final int retval = readUnsignedShort(); + return (retval << 16) + readUnsignedShort(); + } + + @Override + public int position() { + return mPosition; + } + + @Override + public void position(int position) { + mPosition = position; + } + + @Override + public void put(final byte b) { + mBuffer[mPosition++] = b; + } + + @Override + public int limit() { + return mBuffer.length - 1; + } + + @Override + public int capacity() { + return mBuffer.length; + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/CapsModeUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/CapsModeUtilsTests.java new file mode 100644 index 000000000..75463929f --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/CapsModeUtilsTests.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2013 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.content.res.Resources; +import android.text.TextUtils; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.kelar.inputmethod.latin.common.LocaleUtils; +import org.kelar.inputmethod.latin.settings.SpacingAndPunctuations; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Locale; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class CapsModeUtilsTests { + private static void onePathForCaps(final CharSequence cs, final int expectedResult, + final int mask, final SpacingAndPunctuations sp, final boolean hasSpaceBefore) { + final int oneTimeResult = expectedResult & mask; + assertEquals("After >" + cs + "<", oneTimeResult, + CapsModeUtils.getCapsMode(cs, mask, sp, hasSpaceBefore)); + } + + private static void allPathsForCaps(final CharSequence cs, final int expectedResult, + final SpacingAndPunctuations sp, final boolean hasSpaceBefore) { + final int c = TextUtils.CAP_MODE_CHARACTERS; + final int w = TextUtils.CAP_MODE_WORDS; + final int s = TextUtils.CAP_MODE_SENTENCES; + onePathForCaps(cs, expectedResult, c | w | s, sp, hasSpaceBefore); + onePathForCaps(cs, expectedResult, w | s, sp, hasSpaceBefore); + onePathForCaps(cs, expectedResult, c | s, sp, hasSpaceBefore); + onePathForCaps(cs, expectedResult, c | w, sp, hasSpaceBefore); + onePathForCaps(cs, expectedResult, c, sp, hasSpaceBefore); + onePathForCaps(cs, expectedResult, w, sp, hasSpaceBefore); + onePathForCaps(cs, expectedResult, s, sp, hasSpaceBefore); + } + + @Test + public void testGetCapsMode() { + final int c = TextUtils.CAP_MODE_CHARACTERS; + final int w = TextUtils.CAP_MODE_WORDS; + final int s = TextUtils.CAP_MODE_SENTENCES; + final RunInLocale<SpacingAndPunctuations> job = new RunInLocale<SpacingAndPunctuations>() { + @Override + protected SpacingAndPunctuations job(final Resources res) { + return new SpacingAndPunctuations(res); + } + }; + final Resources res = InstrumentationRegistry.getTargetContext().getResources(); + SpacingAndPunctuations sp = job.runInLocale(res, Locale.ENGLISH); + allPathsForCaps("", c | w | s, sp, false); + allPathsForCaps("Word", c, sp, false); + allPathsForCaps("Word.", c, sp, false); + allPathsForCaps("Word ", c | w, sp, false); + allPathsForCaps("Word. ", c | w | s, sp, false); + allPathsForCaps("Word..", c, sp, false); + allPathsForCaps("Word.. ", c | w | s, sp, false); + allPathsForCaps("Word... ", c | w | s, sp, false); + allPathsForCaps("Word ... ", c | w | s, sp, false); + allPathsForCaps("Word . ", c | w, sp, false); + allPathsForCaps("In the U.S ", c | w, sp, false); + allPathsForCaps("In the U.S. ", c | w, sp, false); + allPathsForCaps("Some stuff (e.g. ", c | w, sp, false); + allPathsForCaps("In the U.S.. ", c | w | s, sp, false); + allPathsForCaps("\"Word.\" ", c | w | s, sp, false); + allPathsForCaps("\"Word\". ", c | w | s, sp, false); + allPathsForCaps("\"Word\" ", c | w, sp, false); + + // Test for phantom space + allPathsForCaps("Word", c | w, sp, true); + allPathsForCaps("Word.", c | w | s, sp, true); + + // Tests after some whitespace + allPathsForCaps("Word\n", c | w | s, sp, false); + allPathsForCaps("Word\n", c | w | s, sp, true); + allPathsForCaps("Word\n ", c | w | s, sp, true); + allPathsForCaps("Word.\n", c | w | s, sp, false); + allPathsForCaps("Word.\n", c | w | s, sp, true); + allPathsForCaps("Word.\n ", c | w | s, sp, true); + + sp = job.runInLocale(res, Locale.FRENCH); + allPathsForCaps("\"Word.\" ", c | w, sp, false); + allPathsForCaps("\"Word\". ", c | w | s, sp, false); + allPathsForCaps("\"Word\" ", c | w, sp, false); + + // Test special case for German. German does not capitalize at the start of a + // line when the previous line starts with a comma. It does in other cases. + sp = job.runInLocale(res, Locale.GERMAN); + allPathsForCaps("Liebe Sara,\n", c | w, sp, false); + allPathsForCaps("Liebe Sara,\n", c | w, sp, true); + allPathsForCaps("Liebe Sara, \n ", c | w, sp, false); + allPathsForCaps("Liebe Sara \n ", c | w | s, sp, false); + allPathsForCaps("Liebe Sara.\n ", c | w | s, sp, false); + sp = job.runInLocale(res, Locale.ENGLISH); + allPathsForCaps("Liebe Sara,\n", c | w | s, sp, false); + allPathsForCaps("Liebe Sara,\n", c | w | s, sp, true); + allPathsForCaps("Liebe Sara, \n ", c | w | s, sp, false); + allPathsForCaps("Liebe Sara \n ", c | w | s, sp, false); + allPathsForCaps("Liebe Sara.\n ", c | w | s, sp, false); + + // Test armenian period + sp = job.runInLocale(res, LocaleUtils.constructLocaleFromString("hy_AM")); + assertTrue("Period is not sentence separator in Armenian", + !sp.isSentenceSeparator('.')); + assertTrue("Sentence separator is Armenian period in Armenian", + sp.isSentenceSeparator(0x589)); + // No space : capitalize only if MODE_CHARACTERS + allPathsForCaps("Word", c, sp, false); + allPathsForCaps("Word.", c, sp, false); + // Space, but no armenian period : capitalize if MODE_WORDS but not SENTENCES + allPathsForCaps("Word. ", c | w, sp, false); + // Armenian period : capitalize if MODE_SENTENCES + allPathsForCaps("Word\u0589 ", c | w | s, sp, false); + + // Test for sentence terminators + sp = job.runInLocale(res, Locale.ENGLISH); + allPathsForCaps("Word? ", c | w | s, sp, false); + allPathsForCaps("Word?", c | w | s, sp, true); + allPathsForCaps("Word?", c, sp, false); + allPathsForCaps("Word! ", c | w | s, sp, false); + allPathsForCaps("Word!", c | w | s, sp, true); + allPathsForCaps("Word!", c, sp, false); + allPathsForCaps("Word; ", c | w, sp, false); + allPathsForCaps("Word;", c | w, sp, true); + allPathsForCaps("Word;", c, sp, false); + // Test for sentence terminators in Greek + sp = job.runInLocale(res, LocaleUtils.constructLocaleFromString("el")); + allPathsForCaps("Word? ", c | w | s, sp, false); + allPathsForCaps("Word?", c | w | s, sp, true); + allPathsForCaps("Word?", c, sp, false); + allPathsForCaps("Word! ", c | w | s, sp, false); + allPathsForCaps("Word!", c | w | s, sp, true); + allPathsForCaps("Word!", c, sp, false); + // In Greek ";" is the question mark and it terminates the sentence + allPathsForCaps("Word; ", c | w | s, sp, false); + allPathsForCaps("Word;", c | w | s, sp, true); + allPathsForCaps("Word;", c, sp, false); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/CollectionUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/CollectionUtilsTests.java new file mode 100644 index 000000000..390e88828 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/CollectionUtilsTests.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2014 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.kelar.inputmethod.latin.common.CollectionUtils; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Tests for {@link CollectionUtils}. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class CollectionUtilsTests { + /** + * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} fails as expected + * with some invalid inputs. + */ + @Test + public void testArrayAsListFailure() { + final String[] array = { "0", "1" }; + // Negative start + try { + CollectionUtils.arrayAsList(array, -1, 1); + fail("Failed to catch start < 0"); + } catch (final IllegalArgumentException e) { + assertEquals("Invalid start: -1 end: 1 with array.length: 2", e.getMessage()); + } + // start > end + try { + CollectionUtils.arrayAsList(array, 1, -1); + fail("Failed to catch start > end"); + } catch (final IllegalArgumentException e) { + assertEquals("Invalid start: 1 end: -1 with array.length: 2", e.getMessage()); + } + // end > array.length + try { + CollectionUtils.arrayAsList(array, 1, 3); + fail("Failed to catch end > array.length"); + } catch (final IllegalArgumentException e) { + assertEquals("Invalid start: 1 end: 3 with array.length: 2", e.getMessage()); + } + } + + /** + * Tests that {@link CollectionUtils#arrayAsList(Object[],int,int)} gives the expected + * results for a few valid inputs. + */ + @Test + public void testArrayAsList() { + final ArrayList<String> empty = new ArrayList<>(); + assertEquals(empty, CollectionUtils.arrayAsList(new String[] {}, 0, 0)); + final String[] array = { "0", "1", "2", "3", "4" }; + assertEquals(empty, CollectionUtils.arrayAsList(array, 0, 0)); + assertEquals(empty, CollectionUtils.arrayAsList(array, 1, 1)); + assertEquals(empty, CollectionUtils.arrayAsList(array, array.length, array.length)); + final ArrayList<String> expected123 = new ArrayList<>(Arrays.asList("1", "2", "3")); + assertEquals(expected123, CollectionUtils.arrayAsList(array, 1, 4)); + } + + /** + * Tests that {@link CollectionUtils#isNullOrEmpty(java.util.Collection)} gives the expected + * results for a few cases. + */ + @Test + public void testIsNullOrEmpty() { + assertTrue(CollectionUtils.isNullOrEmpty((List<String>) null)); + assertTrue(CollectionUtils.isNullOrEmpty((Map<String, String>) null)); + assertTrue(CollectionUtils.isNullOrEmpty(new ArrayList<String>())); + assertTrue(CollectionUtils.isNullOrEmpty(new HashMap<String, String>())); + assertFalse(CollectionUtils.isNullOrEmpty(Collections.singletonList("Not empty"))); + assertFalse(CollectionUtils.isNullOrEmpty(Collections.singletonMap("Not", "empty"))); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/DictionaryInfoUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/DictionaryInfoUtilsTests.java new file mode 100644 index 000000000..4c30750f5 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/DictionaryInfoUtilsTests.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.content.res.Resources; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.kelar.inputmethod.latin.common.LocaleUtils; +import org.kelar.inputmethod.latin.settings.SpacingAndPunctuations; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Locale; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class DictionaryInfoUtilsTests { + @Test + public void testLooksValidForDictionaryInsertion() { + final RunInLocale<SpacingAndPunctuations> job = new RunInLocale<SpacingAndPunctuations>() { + @Override + protected SpacingAndPunctuations job(final Resources res) { + return new SpacingAndPunctuations(res); + } + }; + final Resources res = InstrumentationRegistry.getTargetContext().getResources(); + final SpacingAndPunctuations sp = job.runInLocale(res, Locale.ENGLISH); + assertTrue(DictionaryInfoUtils.looksValidForDictionaryInsertion("aochaueo", sp)); + assertFalse(DictionaryInfoUtils.looksValidForDictionaryInsertion("", sp)); + assertTrue(DictionaryInfoUtils.looksValidForDictionaryInsertion("ao-ch'aueo", sp)); + assertFalse(DictionaryInfoUtils.looksValidForDictionaryInsertion("2908743256", sp)); + assertTrue(DictionaryInfoUtils.looksValidForDictionaryInsertion("31aochaueo", sp)); + assertFalse(DictionaryInfoUtils.looksValidForDictionaryInsertion("akeo raeoch oerch .", + sp)); + assertFalse(DictionaryInfoUtils.looksValidForDictionaryInsertion("!!!", sp)); + } + + @Test + public void testGetMainDictId() { + assertEquals("main:en", + DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en"))); + assertEquals("main:en_us", + DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en_US"))); + assertEquals("main:en_gb", + DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("en_GB"))); + + assertEquals("main:es", + DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("es"))); + assertEquals("main:es_us", + DictionaryInfoUtils.getMainDictId(LocaleUtils.constructLocaleFromString("es_US"))); + + assertEquals("main:en_us_posix", DictionaryInfoUtils.getMainDictId( + LocaleUtils.constructLocaleFromString("en_US_POSIX"))); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/ExecutorUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/ExecutorUtilsTests.java new file mode 100644 index 000000000..440e527f1 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/ExecutorUtilsTests.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; + +import android.util.Log; + +import androidx.test.filters.MediumTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Unit tests for {@link ExecutorUtils}. + */ +@MediumTest +@RunWith(AndroidJUnit4.class) +public class ExecutorUtilsTests { + private static final String TAG = ExecutorUtilsTests.class.getSimpleName(); + + private static final int NUM_OF_TASKS = 10; + private static final int DELAY_FOR_WAITING_TASKS_MILLISECONDS = 500; + + @Test + public void testExecute() { + final ExecutorService executor = + ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD); + final AtomicInteger v = new AtomicInteger(0); + for (int i = 0; i < NUM_OF_TASKS; ++i) { + executor.execute(new Runnable() { + @Override + public void run() { + v.incrementAndGet(); + } + }); + } + try { + executor.awaitTermination(DELAY_FOR_WAITING_TASKS_MILLISECONDS, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Log.d(TAG, "Exception while sleeping.", e); + } + + assertEquals(NUM_OF_TASKS, v.get()); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/ImportantNoticeUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/ImportantNoticeUtilsTests.java new file mode 100644 index 000000000..65abd16fd --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/ImportantNoticeUtilsTests.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2014 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 org.kelar.inputmethod.latin.utils; + +import static org.kelar.inputmethod.latin.utils.ImportantNoticeUtils.KEY_TIMESTAMP_OF_CONTACTS_NOTICE; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.MediumTest; +import androidx.test.runner.AndroidJUnit4; + +import org.kelar.inputmethod.latin.settings.SettingsValues; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@MediumTest +@RunWith(AndroidJUnit4.class) +public class ImportantNoticeUtilsTests { + + private ImportantNoticePreferences mImportantNoticePreferences; + + @Mock private SettingsValues mMockSettingsValues; + + private Context getContext() { + return InstrumentationRegistry.getTargetContext(); + } + + private static class ImportantNoticePreferences { + private final SharedPreferences mPref; + + private Long mLastTime; + + public ImportantNoticePreferences(final Context context) { + mPref = ImportantNoticeUtils.getImportantNoticePreferences(context); + } + + private Integer getInt(final String key) { + if (mPref.contains(key)) { + return mPref.getInt(key, 0); + } + return null; + } + + public Long getLong(final String key) { + if (mPref.contains(key)) { + return mPref.getLong(key, 0); + } + return null; + } + + private void putInt(final String key, final Integer value) { + if (value == null) { + removePreference(key); + } else { + mPref.edit().putInt(key, value).apply(); + } + } + + private void putLong(final String key, final Long value) { + if (value == null) { + removePreference(key); + } else { + mPref.edit().putLong(key, value).apply(); + } + } + + private void removePreference(final String key) { + mPref.edit().remove(key).apply(); + } + + public void save() { + mLastTime = getLong(KEY_TIMESTAMP_OF_CONTACTS_NOTICE); + } + + public void restore() { + putLong(KEY_TIMESTAMP_OF_CONTACTS_NOTICE, mLastTime); + } + + public void clear() { + removePreference(KEY_TIMESTAMP_OF_CONTACTS_NOTICE); + } + } + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mImportantNoticePreferences = new ImportantNoticePreferences(getContext()); + mImportantNoticePreferences.save(); + when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(true); + } + + @After + public void tearDown() throws Exception { + mImportantNoticePreferences.restore(); + } + + @Test + public void testPersonalizationSetting() { + mImportantNoticePreferences.clear(); + + // Personalization enabled. + when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(true); + assertEquals("Current boolean with personalization enabled", true, + ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues)); + + // Personalization disabled. + when(mMockSettingsValues.isPersonalizationEnabled()).thenReturn(false); + assertEquals("Current boolean with personalization disabled", false, + ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues)); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/JsonUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/JsonUtilsTests.java new file mode 100644 index 000000000..5a323ef51 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/JsonUtilsTests.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Arrays; +import java.util.List; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class JsonUtilsTests { + @Test + public void testJsonUtils() { + final Object[] objs = new Object[] { 1, "aaa", "bbb", 3 }; + final List<Object> objArray = Arrays.asList(objs); + final String str = JsonUtils.listToJsonStr(objArray); + final List<Object> newObjArray = JsonUtils.jsonStrToList(str); + for (int i = 0; i < objs.length; ++i) { + assertEquals(objs[i], newObjArray.get(i)); + } + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java new file mode 100644 index 000000000..007c69fd2 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/LanguageOnSpacebarUtilsTests.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2014 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 org.kelar.inputmethod.latin.utils; + +import static org.kelar.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_FULL_LOCALE; +import static org.kelar.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_LANGUAGE_ONLY; +import static org.kelar.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_NONE; + +import static org.junit.Assert.assertEquals; + +import android.content.Context; +import android.view.inputmethod.InputMethodSubtype; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.kelar.inputmethod.latin.RichInputMethodManager; +import org.kelar.inputmethod.latin.RichInputMethodSubtype; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.Locale; + +import javax.annotation.Nonnull; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class LanguageOnSpacebarUtilsTests { + private RichInputMethodManager mRichImm; + + RichInputMethodSubtype EN_US_QWERTY; + RichInputMethodSubtype EN_GB_QWERTY; + RichInputMethodSubtype FR_AZERTY; + RichInputMethodSubtype FR_CA_QWERTY; + RichInputMethodSubtype FR_CH_SWISS; + RichInputMethodSubtype FR_CH_QWERTY; + RichInputMethodSubtype FR_CH_QWERTZ; + RichInputMethodSubtype IW_HEBREW; + RichInputMethodSubtype ZZ_QWERTY; + + @Before + public void setUp() throws Exception { + final Context context = InstrumentationRegistry.getTargetContext(); + RichInputMethodManager.init(context); + mRichImm = RichInputMethodManager.getInstance(); + + EN_US_QWERTY = findSubtypeOf(Locale.US.toString(), "qwerty"); + EN_GB_QWERTY = findSubtypeOf(Locale.UK.toString(), "qwerty"); + FR_AZERTY = findSubtypeOf(Locale.FRENCH.toString(), "azerty"); + FR_CA_QWERTY = findSubtypeOf(Locale.CANADA_FRENCH.toString(), "qwerty"); + FR_CH_SWISS = findSubtypeOf("fr_CH", "swiss"); + FR_CH_QWERTZ = new RichInputMethodSubtype( + AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwertz")); + FR_CH_QWERTY = new RichInputMethodSubtype( + AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwerty")); + IW_HEBREW = findSubtypeOf("iw", "hebrew"); + ZZ_QWERTY = findSubtypeOf(SubtypeLocaleUtils.NO_LANGUAGE, "qwerty"); + } + + @Nonnull + private RichInputMethodSubtype findSubtypeOf(final String localeString, + final String keyboardLayoutSetName) { + final InputMethodSubtype subtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + localeString, keyboardLayoutSetName); + if (subtype == null) { + throw new RuntimeException("Can't find subtype of " + localeString + " with " + + keyboardLayoutSetName); + } + return new RichInputMethodSubtype(subtype); + } + + private static void enableSubtypes(final RichInputMethodSubtype ... subtypes) { + final ArrayList<InputMethodSubtype> enabledSubtypes = new ArrayList<>(); + for (final RichInputMethodSubtype subtype : subtypes) { + enabledSubtypes.add(subtype.getRawSubtype()); + } + LanguageOnSpacebarUtils.setEnabledSubtypes(enabledSubtypes); + } + + private static void assertFormatType(final RichInputMethodSubtype subtype, + final boolean implicitlyEnabledSubtype, final Locale systemLocale, + final int expectedFormat) { + LanguageOnSpacebarUtils.onSubtypeChanged(subtype, implicitlyEnabledSubtype, systemLocale); + assertEquals(subtype.getLocale() + " implicitly=" + implicitlyEnabledSubtype + + " in " + systemLocale, expectedFormat, + LanguageOnSpacebarUtils.getLanguageOnSpacebarFormatType(subtype)); + } + + @Test + public void testOneSubtypeImplicitlyEnabled() { + enableSubtypes(EN_US_QWERTY); + assertFormatType(EN_US_QWERTY, true, Locale.US, FORMAT_TYPE_NONE); + + enableSubtypes(EN_GB_QWERTY); + assertFormatType(EN_GB_QWERTY, true, Locale.UK, FORMAT_TYPE_NONE); + + enableSubtypes(FR_AZERTY); + assertFormatType(FR_AZERTY, true, Locale.FRANCE, FORMAT_TYPE_NONE); + + enableSubtypes(FR_CA_QWERTY); + assertFormatType(FR_CA_QWERTY, true, Locale.CANADA_FRENCH, FORMAT_TYPE_NONE); + } + + @Test + public void testOneSubtypeExplicitlyEnabled() { + enableSubtypes(EN_US_QWERTY); + assertFormatType(EN_US_QWERTY, false, Locale.UK, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + + enableSubtypes(EN_GB_QWERTY); + assertFormatType(EN_GB_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(EN_GB_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + + enableSubtypes(FR_AZERTY); + assertFormatType(FR_AZERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_AZERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY); + + enableSubtypes(FR_CA_QWERTY); + assertFormatType(FR_CA_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + } + + @Test + public void testOneSubtypeImplicitlyEnabledWithNoLanguageSubtype() { + final Locale Locale_IW = new Locale("iw"); + enableSubtypes(IW_HEBREW, ZZ_QWERTY); + // TODO: Should this be FORMAT_TYPE_NONE? + assertFormatType(IW_HEBREW, true, Locale_IW, FORMAT_TYPE_LANGUAGE_ONLY); + // TODO: Should this be FORMAT_TYPE_NONE? + assertFormatType(ZZ_QWERTY, true, Locale_IW, FORMAT_TYPE_FULL_LOCALE); + } + + @Test + public void testTwoSubtypesExplicitlyEnabled() { + enableSubtypes(EN_US_QWERTY, FR_AZERTY); + assertFormatType(EN_US_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_AZERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_AZERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(EN_US_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_AZERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + + enableSubtypes(EN_US_QWERTY, ZZ_QWERTY); + assertFormatType(EN_US_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(ZZ_QWERTY, false, Locale.US, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(ZZ_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE); + + } + + @Test + public void testMultiSubtypeWithSameLanuageAndSameLayout() { + // Explicitly enable en_US, en_GB, fr_FR, and no language keyboards. + enableSubtypes(EN_US_QWERTY, EN_GB_QWERTY, FR_CA_QWERTY, ZZ_QWERTY); + + assertFormatType(EN_US_QWERTY, false, Locale.US, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(EN_GB_QWERTY, false, Locale.US, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(FR_CA_QWERTY, false, Locale.US, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(ZZ_QWERTY, false, Locale.US, FORMAT_TYPE_FULL_LOCALE); + + assertFormatType(EN_US_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(EN_GB_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(ZZ_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE); + } + + @Test + public void testMultiSubtypesWithSameLanguageButHaveDifferentLayout() { + enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTZ); + + assertFormatType(FR_AZERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_SWISS, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + + assertFormatType(FR_AZERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_SWISS, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY); + + assertFormatType(FR_AZERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_SWISS, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + } + + @Test + public void testMultiSubtypesWithSameLanguageAndMayHaveSameLayout() { + enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTY, FR_CH_QWERTZ); + + assertFormatType(FR_AZERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(FR_CH_SWISS, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY); + + assertFormatType(FR_AZERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(FR_CH_SWISS, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY); + + assertFormatType(FR_AZERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(FR_CH_SWISS, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + assertFormatType(FR_CH_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE); + assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/RecapitalizeStatusTests.java b/tests/src/org/kelar/inputmethod/latin/utils/RecapitalizeStatusTests.java new file mode 100644 index 000000000..1ce091b0b --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/RecapitalizeStatusTests.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2013 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.kelar.inputmethod.latin.common.Constants; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Locale; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RecapitalizeStatusTests { + private static final int[] SPACE = { Constants.CODE_SPACE }; + + @Test + public void testTrim() { + final RecapitalizeStatus status = new RecapitalizeStatus(); + status.start(30, 40, "abcdefghij", Locale.ENGLISH, SPACE); + status.trim(); + assertEquals("abcdefghij", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(40, status.getNewCursorEnd()); + + status.start(30, 44, " abcdefghij", Locale.ENGLISH, SPACE); + status.trim(); + assertEquals("abcdefghij", status.getRecapitalizedString()); + assertEquals(34, status.getNewCursorStart()); + assertEquals(44, status.getNewCursorEnd()); + + status.start(30, 40, "abcdefgh ", Locale.ENGLISH, SPACE); + status.trim(); + assertEquals("abcdefgh", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(38, status.getNewCursorEnd()); + + status.start(30, 45, " abcdefghij ", Locale.ENGLISH, SPACE); + status.trim(); + assertEquals("abcdefghij", status.getRecapitalizedString()); + assertEquals(33, status.getNewCursorStart()); + assertEquals(43, status.getNewCursorEnd()); + } + + @Test + public void testRotate() { + final RecapitalizeStatus status = new RecapitalizeStatus(); + status.start(29, 40, "abcd efghij", Locale.ENGLISH, SPACE); + status.rotate(); + assertEquals("Abcd Efghij", status.getRecapitalizedString()); + assertEquals(29, status.getNewCursorStart()); + assertEquals(40, status.getNewCursorEnd()); + status.rotate(); + assertEquals("ABCD EFGHIJ", status.getRecapitalizedString()); + status.rotate(); + assertEquals("abcd efghij", status.getRecapitalizedString()); + status.rotate(); + assertEquals("Abcd Efghij", status.getRecapitalizedString()); + + status.start(29, 40, "Abcd Efghij", Locale.ENGLISH, SPACE); + status.rotate(); + assertEquals("ABCD EFGHIJ", status.getRecapitalizedString()); + assertEquals(29, status.getNewCursorStart()); + assertEquals(40, status.getNewCursorEnd()); + status.rotate(); + assertEquals("abcd efghij", status.getRecapitalizedString()); + status.rotate(); + assertEquals("Abcd Efghij", status.getRecapitalizedString()); + status.rotate(); + assertEquals("ABCD EFGHIJ", status.getRecapitalizedString()); + + status.start(29, 40, "ABCD EFGHIJ", Locale.ENGLISH, SPACE); + status.rotate(); + assertEquals("abcd efghij", status.getRecapitalizedString()); + assertEquals(29, status.getNewCursorStart()); + assertEquals(40, status.getNewCursorEnd()); + status.rotate(); + assertEquals("Abcd Efghij", status.getRecapitalizedString()); + status.rotate(); + assertEquals("ABCD EFGHIJ", status.getRecapitalizedString()); + status.rotate(); + assertEquals("abcd efghij", status.getRecapitalizedString()); + + status.start(29, 39, "AbCDefghij", Locale.ENGLISH, SPACE); + status.rotate(); + assertEquals("abcdefghij", status.getRecapitalizedString()); + assertEquals(29, status.getNewCursorStart()); + assertEquals(39, status.getNewCursorEnd()); + status.rotate(); + assertEquals("Abcdefghij", status.getRecapitalizedString()); + status.rotate(); + assertEquals("ABCDEFGHIJ", status.getRecapitalizedString()); + status.rotate(); + assertEquals("AbCDefghij", status.getRecapitalizedString()); + status.rotate(); + assertEquals("abcdefghij", status.getRecapitalizedString()); + + status.start(29, 40, "Abcd efghij", Locale.ENGLISH, SPACE); + status.rotate(); + assertEquals("abcd efghij", status.getRecapitalizedString()); + assertEquals(29, status.getNewCursorStart()); + assertEquals(40, status.getNewCursorEnd()); + status.rotate(); + assertEquals("Abcd Efghij", status.getRecapitalizedString()); + status.rotate(); + assertEquals("ABCD EFGHIJ", status.getRecapitalizedString()); + status.rotate(); + assertEquals("Abcd efghij", status.getRecapitalizedString()); + status.rotate(); + assertEquals("abcd efghij", status.getRecapitalizedString()); + + status.start(30, 34, "grüß", Locale.GERMAN, SPACE); + status.rotate(); + assertEquals("Grüß", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(34, status.getNewCursorEnd()); + status.rotate(); + assertEquals("GRÜSS", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(35, status.getNewCursorEnd()); + status.rotate(); + assertEquals("grüß", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(34, status.getNewCursorEnd()); + status.rotate(); + assertEquals("Grüß", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(34, status.getNewCursorEnd()); + + status.start(30, 33, "œuf", Locale.FRENCH, SPACE); + status.rotate(); + assertEquals("Œuf", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + status.rotate(); + assertEquals("ŒUF", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + status.rotate(); + assertEquals("œuf", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + status.rotate(); + assertEquals("Œuf", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + + status.start(30, 33, "œUf", Locale.FRENCH, SPACE); + status.rotate(); + assertEquals("œuf", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + status.rotate(); + assertEquals("Œuf", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + status.rotate(); + assertEquals("ŒUF", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + status.rotate(); + assertEquals("œUf", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + status.rotate(); + assertEquals("œuf", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(33, status.getNewCursorEnd()); + + status.start(30, 35, "école", Locale.FRENCH, SPACE); + status.rotate(); + assertEquals("École", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(35, status.getNewCursorEnd()); + status.rotate(); + assertEquals("ÉCOLE", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(35, status.getNewCursorEnd()); + status.rotate(); + assertEquals("école", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(35, status.getNewCursorEnd()); + status.rotate(); + assertEquals("École", status.getRecapitalizedString()); + assertEquals(30, status.getNewCursorStart()); + assertEquals(35, status.getNewCursorEnd()); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/ResourceUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/ResourceUtilsTests.java new file mode 100644 index 000000000..7e7f24d49 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/ResourceUtilsTests.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2013 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.HashMap; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ResourceUtilsTests { + @Test + public void testFindConstantForKeyValuePairsSimple() { + final HashMap<String,String> anyKeyValue = new HashMap<>(); + anyKeyValue.put("anyKey", "anyValue"); + final HashMap<String,String> nullKeyValue = null; + final HashMap<String,String> emptyKeyValue = new HashMap<>(); + + final String[] nullArray = null; + assertNull(ResourceUtils.findConstantForKeyValuePairs(anyKeyValue, nullArray)); + assertNull(ResourceUtils.findConstantForKeyValuePairs(emptyKeyValue, nullArray)); + assertNull(ResourceUtils.findConstantForKeyValuePairs(nullKeyValue, nullArray)); + + final String[] emptyArray = {}; + assertNull(ResourceUtils.findConstantForKeyValuePairs(anyKeyValue, emptyArray)); + assertNull(ResourceUtils.findConstantForKeyValuePairs(emptyKeyValue, emptyArray)); + assertNull(ResourceUtils.findConstantForKeyValuePairs(nullKeyValue, emptyArray)); + + final String HARDWARE_KEY = "HARDWARE"; + final String[] array = { + ",defaultValue", + "HARDWARE=grouper,0.3", + "HARDWARE=mako,0.4", + "HARDWARE=manta,0.2", + "HARDWARE=mako,0.5", + }; + + final HashMap<String,String> keyValues = new HashMap<>(); + keyValues.put(HARDWARE_KEY, "grouper"); + assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + keyValues.put(HARDWARE_KEY, "mako"); + assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + keyValues.put(HARDWARE_KEY, "manta"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + + keyValues.clear(); + keyValues.put("hardware", "grouper"); + assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + + keyValues.clear(); + keyValues.put(HARDWARE_KEY, "MAKO"); + assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + keyValues.put(HARDWARE_KEY, "mantaray"); + assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + + assertNull(ResourceUtils.findConstantForKeyValuePairs(emptyKeyValue, array)); + } + + @Test + public void testFindConstantForKeyValuePairsCombined() { + final String HARDWARE_KEY = "HARDWARE"; + final String MODEL_KEY = "MODEL"; + final String MANUFACTURER_KEY = "MANUFACTURER"; + final String[] array = { + ",defaultValue", + "no_comma", + "error_pattern,0.1", + "HARDWARE=grouper:MANUFACTURER=asus,0.3", + "HARDWARE=mako:MODEL=Nexus 4,0.4", + "HARDWARE=manta:MODEL=Nexus 10:MANUFACTURER=samsung,0.2" + }; + final String[] failArray = { + ",defaultValue", + "HARDWARE=grouper:MANUFACTURER=ASUS,0.3", + "HARDWARE=mako:MODEL=Nexus_4,0.4", + "HARDWARE=mantaray:MODEL=Nexus 10:MANUFACTURER=samsung,0.2" + }; + + final HashMap<String,String> keyValues = new HashMap<>(); + keyValues.put(HARDWARE_KEY, "grouper"); + keyValues.put(MODEL_KEY, "Nexus 7"); + keyValues.put(MANUFACTURER_KEY, "asus"); + assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray)); + + keyValues.clear(); + keyValues.put(HARDWARE_KEY, "mako"); + keyValues.put(MODEL_KEY, "Nexus 4"); + keyValues.put(MANUFACTURER_KEY, "LGE"); + assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray)); + + keyValues.clear(); + keyValues.put(HARDWARE_KEY, "manta"); + keyValues.put(MODEL_KEY, "Nexus 10"); + keyValues.put(MANUFACTURER_KEY, "samsung"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray)); + keyValues.put(HARDWARE_KEY, "mantaray"); + assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray)); + } + + @Test + public void testFindConstantForKeyValuePairsRegexp() { + final String HARDWARE_KEY = "HARDWARE"; + final String MODEL_KEY = "MODEL"; + final String MANUFACTURER_KEY = "MANUFACTURER"; + final String[] array = { + ",defaultValue", + "no_comma", + "HARDWARE=error_regexp:MANUFACTURER=error[regexp,0.1", + "HARDWARE=grouper|tilapia:MANUFACTURER=asus,0.3", + "HARDWARE=[mM][aA][kK][oO]:MODEL=Nexus 4,0.4", + "HARDWARE=manta.*:MODEL=Nexus 10:MANUFACTURER=samsung,0.2" + }; + + final HashMap<String,String> keyValues = new HashMap<>(); + keyValues.put(HARDWARE_KEY, "grouper"); + keyValues.put(MODEL_KEY, "Nexus 7"); + keyValues.put(MANUFACTURER_KEY, "asus"); + assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + keyValues.put(HARDWARE_KEY, "tilapia"); + assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + + keyValues.clear(); + keyValues.put(HARDWARE_KEY, "mako"); + keyValues.put(MODEL_KEY, "Nexus 4"); + keyValues.put(MANUFACTURER_KEY, "LGE"); + assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + keyValues.put(HARDWARE_KEY, "MAKO"); + assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + + keyValues.clear(); + keyValues.put(HARDWARE_KEY, "manta"); + keyValues.put(MODEL_KEY, "Nexus 10"); + keyValues.put(MANUFACTURER_KEY, "samsung"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + keyValues.put(HARDWARE_KEY, "mantaray"); + assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array)); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/SpannableStringUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/SpannableStringUtilsTests.java new file mode 100644 index 000000000..f5546a04d --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/SpannableStringUtilsTests.java @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2013 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.SpannedString; +import android.text.style.SuggestionSpan; +import android.text.style.URLSpan; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class SpannableStringUtilsTests { + + private Context getContext() { + return InstrumentationRegistry.getTargetContext(); + } + + @Test + public void testConcatWithSuggestionSpansOnly() { + SpannableStringBuilder s = new SpannableStringBuilder("test string\ntest string\n" + + "test string\ntest string\ntest string\ntest string\ntest string\ntest string\n" + + "test string\ntest string\n"); + final int N = 10; + for (int i = 0; i < N; ++i) { + // Put a PARAGRAPH-flagged span that should not be found in the result. + s.setSpan(new SuggestionSpan(getContext(), + new String[] {"" + i}, Spanned.SPAN_PARAGRAPH), + i * 12, i * 12 + 12, Spanned.SPAN_PARAGRAPH); + // Put a normal suggestion span that should be found in the result. + s.setSpan(new SuggestionSpan(getContext(), new String[] {"" + i}, 0), i, i * 2, 0); + // Put a URL span than should not be found in the result. + s.setSpan(new URLSpan("http://a"), i, i * 2, 0); + } + + final CharSequence a = s.subSequence(0, 15); + final CharSequence b = s.subSequence(15, s.length()); + final Spanned result = + (Spanned)SpannableStringUtils.concatWithNonParagraphSuggestionSpansOnly(a, b); + + Object[] spans = result.getSpans(0, result.length(), SuggestionSpan.class); + for (int i = 0; i < spans.length; i++) { + final int flags = result.getSpanFlags(spans[i]); + assertEquals("Should not find a span with PARAGRAPH flag", + flags & Spanned.SPAN_PARAGRAPH, 0); + assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan); + } + } + + private static void assertSpanCount(final int expectedCount, final CharSequence cs) { + final int actualCount; + if (cs instanceof Spanned) { + final Spanned spanned = (Spanned) cs; + actualCount = spanned.getSpans(0, spanned.length(), Object.class).length; + } else { + actualCount = 0; + } + assertEquals(expectedCount, actualCount); + } + + private static void assertSpan(final CharSequence cs, final Object expectedSpan, + final int expectedStart, final int expectedEnd, final int expectedFlags) { + assertTrue(cs instanceof Spanned); + final Spanned spanned = (Spanned) cs; + final Object[] actualSpans = spanned.getSpans(0, spanned.length(), Object.class); + for (Object actualSpan : actualSpans) { + if (actualSpan == expectedSpan) { + final int actualStart = spanned.getSpanStart(actualSpan); + final int actualEnd = spanned.getSpanEnd(actualSpan); + final int actualFlags = spanned.getSpanFlags(actualSpan); + assertEquals(expectedStart, actualStart); + assertEquals(expectedEnd, actualEnd); + assertEquals(expectedFlags, actualFlags); + return; + } + } + assertTrue(false); + } + + @Test + public void testSplitCharSequenceWithSpan() { + // text: " a bcd efg hij " + // span1: ^^^^^^^ + // span2: ^^^^^ + // span3: ^ + final SpannableString spannableString = new SpannableString(" a bcd efg hij "); + final Object span1 = new Object(); + final Object span2 = new Object(); + final Object span3 = new Object(); + final int SPAN1_FLAGS = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; + final int SPAN2_FLAGS = Spanned.SPAN_EXCLUSIVE_INCLUSIVE; + final int SPAN3_FLAGS = Spanned.SPAN_INCLUSIVE_INCLUSIVE; + spannableString.setSpan(span1, 0, 7, SPAN1_FLAGS); + spannableString.setSpan(span2, 0, 5, SPAN2_FLAGS); + spannableString.setSpan(span3, 12, 13, SPAN3_FLAGS); + final CharSequence[] charSequencesFromSpanned = SpannableStringUtils.split( + spannableString, " ", true /* preserveTrailingEmptySegmengs */); + final CharSequence[] charSequencesFromString = SpannableStringUtils.split( + spannableString.toString(), " ", true /* preserveTrailingEmptySegmengs */); + + + assertEquals(7, charSequencesFromString.length); + assertEquals(7, charSequencesFromSpanned.length); + + // text: "" + // span1: ^ + // span2: ^ + // span3: + assertEquals("", charSequencesFromString[0].toString()); + assertSpanCount(0, charSequencesFromString[0]); + assertEquals("", charSequencesFromSpanned[0].toString()); + assertSpanCount(2, charSequencesFromSpanned[0]); + assertSpan(charSequencesFromSpanned[0], span1, 0, 0, SPAN1_FLAGS); + assertSpan(charSequencesFromSpanned[0], span2, 0, 0, SPAN2_FLAGS); + + // text: "a" + // span1: ^ + // span2: ^ + // span3: + assertEquals("a", charSequencesFromString[1].toString()); + assertSpanCount(0, charSequencesFromString[1]); + assertEquals("a", charSequencesFromSpanned[1].toString()); + assertSpanCount(2, charSequencesFromSpanned[1]); + assertSpan(charSequencesFromSpanned[1], span1, 0, 1, SPAN1_FLAGS); + assertSpan(charSequencesFromSpanned[1], span2, 0, 1, SPAN2_FLAGS); + + // text: "bcd" + // span1: ^^^ + // span2: ^^ + // span3: + assertEquals("bcd", charSequencesFromString[2].toString()); + assertSpanCount(0, charSequencesFromString[2]); + assertEquals("bcd", charSequencesFromSpanned[2].toString()); + assertSpanCount(2, charSequencesFromSpanned[2]); + assertSpan(charSequencesFromSpanned[2], span1, 0, 3, SPAN1_FLAGS); + assertSpan(charSequencesFromSpanned[2], span2, 0, 2, SPAN2_FLAGS); + + // text: "efg" + // span1: + // span2: + // span3: + assertEquals("efg", charSequencesFromString[3].toString()); + assertSpanCount(0, charSequencesFromString[3]); + assertEquals("efg", charSequencesFromSpanned[3].toString()); + assertSpanCount(0, charSequencesFromSpanned[3]); + + // text: "hij" + // span1: + // span2: + // span3: ^ + assertEquals("hij", charSequencesFromString[4].toString()); + assertSpanCount(0, charSequencesFromString[4]); + assertEquals("hij", charSequencesFromSpanned[4].toString()); + assertSpanCount(1, charSequencesFromSpanned[4]); + assertSpan(charSequencesFromSpanned[4], span3, 1, 2, SPAN3_FLAGS); + + // text: "" + // span1: + // span2: + // span3: + assertEquals("", charSequencesFromString[5].toString()); + assertSpanCount(0, charSequencesFromString[5]); + assertEquals("", charSequencesFromSpanned[5].toString()); + assertSpanCount(0, charSequencesFromSpanned[5]); + + // text: "" + // span1: + // span2: + // span3: + assertEquals("", charSequencesFromString[6].toString()); + assertSpanCount(0, charSequencesFromString[6]); + assertEquals("", charSequencesFromSpanned[6].toString()); + assertSpanCount(0, charSequencesFromSpanned[6]); + } + + @Test + public void testSplitCharSequencePreserveTrailingEmptySegmengs() { + assertEquals(1, SpannableStringUtils.split("", " ", + false /* preserveTrailingEmptySegmengs */).length); + assertEquals(1, SpannableStringUtils.split(new SpannedString(""), " ", + false /* preserveTrailingEmptySegmengs */).length); + + assertEquals(1, SpannableStringUtils.split("", " ", + true /* preserveTrailingEmptySegmengs */).length); + assertEquals(1, SpannableStringUtils.split(new SpannedString(""), " ", + true /* preserveTrailingEmptySegmengs */).length); + + assertEquals(0, SpannableStringUtils.split(" ", " ", + false /* preserveTrailingEmptySegmengs */).length); + assertEquals(0, SpannableStringUtils.split(new SpannedString(" "), " ", + false /* preserveTrailingEmptySegmengs */).length); + + assertEquals(2, SpannableStringUtils.split(" ", " ", + true /* preserveTrailingEmptySegmengs */).length); + assertEquals(2, SpannableStringUtils.split(new SpannedString(" "), " ", + true /* preserveTrailingEmptySegmengs */).length); + + assertEquals(3, SpannableStringUtils.split("a b c ", " ", + false /* preserveTrailingEmptySegmengs */).length); + assertEquals(3, SpannableStringUtils.split(new SpannedString("a b c "), " ", + false /* preserveTrailingEmptySegmengs */).length); + + assertEquals(5, SpannableStringUtils.split("a b c ", " ", + true /* preserveTrailingEmptySegmengs */).length); + assertEquals(5, SpannableStringUtils.split(new SpannedString("a b c "), " ", + true /* preserveTrailingEmptySegmengs */).length); + + assertEquals(6, SpannableStringUtils.split("a b ", " ", + false /* preserveTrailingEmptySegmengs */).length); + assertEquals(6, SpannableStringUtils.split(new SpannedString("a b "), " ", + false /* preserveTrailingEmptySegmengs */).length); + + assertEquals(7, SpannableStringUtils.split("a b ", " ", + true /* preserveTrailingEmptySegmengs */).length); + assertEquals(7, SpannableStringUtils.split(new SpannedString("a b "), " ", + true /* preserveTrailingEmptySegmengs */).length); + } +} diff --git a/tests/src/org/kelar/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/org/kelar/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java new file mode 100644 index 000000000..77b960a95 --- /dev/null +++ b/tests/src/org/kelar/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java @@ -0,0 +1,498 @@ +/* + * Copyright (C) 2011 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 org.kelar.inputmethod.latin.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.content.res.Resources; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodSubtype; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.kelar.inputmethod.latin.R; +import org.kelar.inputmethod.latin.RichInputMethodManager; +import org.kelar.inputmethod.latin.RichInputMethodSubtype; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.Locale; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class SubtypeLocaleUtilsTests { + // All input method subtypes of LatinIME. + private final ArrayList<RichInputMethodSubtype> mSubtypesList = new ArrayList<>(); + + private RichInputMethodManager mRichImm; + private Resources mRes; + private InputMethodSubtype mSavedAddtionalSubtypes[]; + + InputMethodSubtype EN_US; + InputMethodSubtype EN_GB; + InputMethodSubtype ES_US; + InputMethodSubtype FR; + InputMethodSubtype FR_CA; + InputMethodSubtype FR_CH; + InputMethodSubtype DE; + InputMethodSubtype DE_CH; + InputMethodSubtype HI; + InputMethodSubtype SR; + InputMethodSubtype ZZ; + InputMethodSubtype DE_QWERTY; + InputMethodSubtype FR_QWERTZ; + InputMethodSubtype EN_US_AZERTY; + InputMethodSubtype EN_UK_DVORAK; + InputMethodSubtype ES_US_COLEMAK; + InputMethodSubtype ZZ_AZERTY; + InputMethodSubtype ZZ_PC; + + // These are preliminary subtypes and may not exist. + InputMethodSubtype HI_LATN; // Hinglish + InputMethodSubtype SR_LATN; // Serbian Latin + InputMethodSubtype HI_LATN_DVORAK; // Hinglis Dvorak + InputMethodSubtype SR_LATN_QWERTY; // Serbian Latin Qwerty + + @Before + public void setUp() throws Exception { + final Context context = InstrumentationRegistry.getTargetContext(); + mRes = context.getResources(); + RichInputMethodManager.init(context); + mRichImm = RichInputMethodManager.getInstance(); + + // Save and reset additional subtypes + mSavedAddtionalSubtypes = mRichImm.getAdditionalSubtypes(); + final InputMethodSubtype[] predefinedAddtionalSubtypes = + AdditionalSubtypeUtils.createAdditionalSubtypesArray( + AdditionalSubtypeUtils.createPrefSubtypes( + mRes.getStringArray(R.array.predefined_subtypes))); + mRichImm.setAdditionalInputMethodSubtypes(predefinedAddtionalSubtypes); + + final InputMethodInfo imi = mRichImm.getInputMethodInfoOfThisIme(); + final int subtypeCount = imi.getSubtypeCount(); + for (int index = 0; index < subtypeCount; index++) { + final InputMethodSubtype subtype = imi.getSubtypeAt(index); + mSubtypesList.add(new RichInputMethodSubtype(subtype)); + } + + EN_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.US.toString(), "qwerty"); + EN_GB = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.UK.toString(), "qwerty"); + ES_US = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "es_US", "spanish"); + FR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.FRENCH.toString(), "azerty"); + FR_CA = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.CANADA_FRENCH.toString(), "qwerty"); + FR_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "fr_CH", "swiss"); + DE = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + Locale.GERMAN.toString(), "qwertz"); + DE_CH = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "de_CH", "swiss"); + HI = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "hi", "hindi"); + SR = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + "sr", "south_slavic"); + ZZ = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet( + SubtypeLocaleUtils.NO_LANGUAGE, "qwerty"); + DE_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + Locale.GERMAN.toString(), "qwerty"); + FR_QWERTZ = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + Locale.FRENCH.toString(), "qwertz"); + EN_US_AZERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + Locale.US.toString(), "azerty"); + EN_UK_DVORAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + Locale.UK.toString(), "dvorak"); + ES_US_COLEMAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + "es_US", "colemak"); + ZZ_AZERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + SubtypeLocaleUtils.NO_LANGUAGE, "azerty"); + ZZ_PC = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty"); + + HI_LATN = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet("hi_ZZ", "qwerty"); + if (HI_LATN != null) { + HI_LATN_DVORAK = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + "hi_ZZ", "dvorak"); + } + SR_LATN = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet("sr_ZZ", "serbian_qwertz"); + if (SR_LATN != null) { + SR_LATN_QWERTY = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype( + "sr_ZZ", "qwerty"); + } + } + + @After + public void tearDown() throws Exception { + // Restore additional subtypes. + mRichImm.setAdditionalInputMethodSubtypes(mSavedAddtionalSubtypes); + } + + @Test + public void testAllFullDisplayName() { + for (final RichInputMethodSubtype subtype : mSubtypesList) { + final String subtypeName = SubtypeLocaleUtils + .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype()); + if (subtype.isNoLanguage()) { + final String layoutName = SubtypeLocaleUtils + .getKeyboardLayoutSetDisplayName(subtype.getRawSubtype()); + assertTrue(subtypeName, subtypeName.contains(layoutName)); + } else { + final String languageName = SubtypeLocaleUtils + .getSubtypeLocaleDisplayNameInSystemLocale(subtype.getLocale().toString()); + assertTrue(subtypeName, subtypeName.contains(languageName)); + } + } + } + + @Test + public void testKeyboardLayoutSetName() { + assertEquals("en_US", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_US)); + assertEquals("en_GB", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_GB)); + assertEquals("es_US", "spanish", SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US)); + assertEquals("fr", "azerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR)); + assertEquals("fr_CA", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CA)); + assertEquals("fr_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_CH)); + assertEquals("de", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE)); + assertEquals("de_CH", "swiss", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_CH)); + assertEquals("hi", "hindi", SubtypeLocaleUtils.getKeyboardLayoutSetName(HI)); + assertEquals("sr", "south_slavic", SubtypeLocaleUtils.getKeyboardLayoutSetName(SR)); + assertEquals("zz", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ)); + + assertEquals("de qwerty", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(DE_QWERTY)); + assertEquals("fr qwertz", "qwertz", SubtypeLocaleUtils.getKeyboardLayoutSetName(FR_QWERTZ)); + assertEquals("en_US azerty", "azerty", + SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_US_AZERTY)); + assertEquals("en_UK dvorak", "dvorak", + SubtypeLocaleUtils.getKeyboardLayoutSetName(EN_UK_DVORAK)); + assertEquals("es_US colemak", "colemak", + SubtypeLocaleUtils.getKeyboardLayoutSetName(ES_US_COLEMAK)); + assertEquals("zz azerty", "azerty", + SubtypeLocaleUtils.getKeyboardLayoutSetName(ZZ_AZERTY)); + + // These are preliminary subtypes and may not exist. + if (HI_LATN != null) { + assertEquals("hi_ZZ", "qwerty", SubtypeLocaleUtils.getKeyboardLayoutSetName(HI_LATN)); + assertEquals("hi_ZZ dvorak", "dvorak", + SubtypeLocaleUtils.getKeyboardLayoutSetName(HI_LATN_DVORAK)); + } + if (SR_LATN != null) { + assertEquals("sr_ZZ", "serbian_qwertz", + SubtypeLocaleUtils.getKeyboardLayoutSetName(SR_LATN)); + assertEquals("sr_ZZ qwerty", "qwerty", + SubtypeLocaleUtils.getKeyboardLayoutSetName(SR_LATN_QWERTY)); + } + } + + // InputMethodSubtype's display name in system locale (en_US). + // isAdditionalSubtype (T=true, F=false) + // locale layout | display name + // ------ -------------- - ---------------------- + // en_US qwerty F English (US) exception + // en_GB qwerty F English (UK) exception + // es_US spanish F Spanish (US) exception + // fr azerty F French + // fr_CA qwerty F French (Canada) + // fr_CH swiss F French (Switzerland) + // de qwertz F German + // de_CH swiss F German (Switzerland) + // hi hindi F Hindi + // hi_ZZ qwerty F Hinglish exception + // sr south_slavic F Serbian + // sr_ZZ serbian_qwertz F Serbian (Latin) exception + // zz qwerty F Alphabet (QWERTY) + // fr qwertz T French (QWERTZ) + // de qwerty T German (QWERTY) + // en_US azerty T English (US) (AZERTY) exception + // en_UK dvorak T English (UK) (Dvorak) exception + // es_US colemak T Spanish (US) (Colemak) exception + // hi_ZZ dvorak T Hinglish (Dvorka) exception + // sr_ZZ qwerty T Serbian (QWERTY) exception + // zz pc T Alphabet (PC) + + @Test + public void testPredefinedSubtypesInEnglishSystemLocale() { + final RunInLocale<Void> tests = new RunInLocale<Void>() { + @Override + protected Void job(final Resources res) { + assertEquals("en_US", "English (US)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US)); + assertEquals("en_GB", "English (UK)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_GB)); + assertEquals("es_US", "Spanish (US)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US)); + assertEquals("fr", "French", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR)); + assertEquals("fr_CA", "French (Canada)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA)); + assertEquals("fr_CH", "French (Switzerland)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CH)); + assertEquals("de", "German", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE)); + assertEquals("de_CH", "German (Switzerland)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH)); + assertEquals("hi", "Hindi", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI)); + assertEquals("sr", "Serbian", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR)); + assertEquals("zz", "Alphabet (QWERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ)); + // These are preliminary subtypes and may not exist. + if (HI_LATN != null) { + assertEquals("hi_ZZ", "Hinglish", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN)); + } + if (SR_LATN != null) { + assertEquals("sr_ZZ", "Serbian (Latin)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN)); + } + return null; + } + }; + tests.runInLocale(mRes, Locale.ENGLISH); + } + + @Test + public void testAdditionalSubtypesInEnglishSystemLocale() { + final RunInLocale<Void> tests = new RunInLocale<Void>() { + @Override + protected Void job(final Resources res) { + assertEquals("fr qwertz", "French (QWERTZ)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ)); + assertEquals("de qwerty", "German (QWERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_QWERTY)); + assertEquals("en_US azerty", "English (US) (AZERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY)); + assertEquals("en_UK dvorak","English (UK) (Dvorak)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK)); + assertEquals("es_US colemak", "Spanish (US) (Colemak)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK)); + assertEquals("zz azerty", "Alphabet (AZERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY)); + assertEquals("zz pc", "Alphabet (PC)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC)); + // These are preliminary subtypes and may not exist. + if (HI_LATN_DVORAK != null) { + assertEquals("hi_ZZ", "Hinglish (Dvorak)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK)); + } + if (SR_LATN_QWERTY != null) { + assertEquals("sr_ZZ", "Serbian (QWERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY)); + } + return null; + } + }; + tests.runInLocale(mRes, Locale.ENGLISH); + } + + // InputMethodSubtype's display name in system locale (fr). + // isAdditionalSubtype (T=true, F=false) + // locale layout | display name + // ------ ------- - ---------------------- + // en_US qwerty F Anglais (États-Unis) exception + // en_GB qwerty F Anglais (Royaume-Uni) exception + // es_US spanish F Espagnol (États-Unis) exception + // fr azerty F Français + // fr_CA qwerty F Français (Canada) + // fr_CH swiss F Français (Suisse) + // de qwertz F Allemand + // de_CH swiss F Allemand (Suisse) + // hi hindi F Hindi exception + // hi_ZZ qwerty F Hindi/Anglais exception + // sr south_slavic F Serbe exception + // sr_ZZ serbian_qwertz F Serbe (latin) exception + // zz qwerty F Alphabet latin (QWERTY) + // fr qwertz T Français (QWERTZ) + // de qwerty T Allemand (QWERTY) + // en_US azerty T Anglais (États-Unis) (AZERTY) exception + // en_UK dvorak T Anglais (Royaume-Uni) (Dvorak) exception + // es_US colemak T Espagnol (États-Unis) (Colemak) exception + // hi_ZZ dvorak T Hindi/Anglais (Dvorka) exception + // sr_ZZ qwerty T Serbe (QWERTY) exception + // zz pc T Alphabet latin (PC) + + @Test + public void testPredefinedSubtypesInFrenchSystemLocale() { + final RunInLocale<Void> tests = new RunInLocale<Void>() { + @Override + protected Void job(final Resources res) { + assertEquals("en_US", "Anglais (États-Unis)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US)); + assertEquals("en_GB", "Anglais (Royaume-Uni)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_GB)); + assertEquals("es_US", "Espagnol (États-Unis)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US)); + assertEquals("fr", "Français", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR)); + assertEquals("fr_CA", "Français (Canada)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CA)); + assertEquals("fr_CH", "Français (Suisse)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_CH)); + assertEquals("de", "Allemand", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE)); + assertEquals("de_CH", "Allemand (Suisse)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_CH)); + assertEquals("hi", "Hindi", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI)); + assertEquals("sr", "Serbe", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR)); + assertEquals("zz", "Alphabet latin (QWERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ)); + // These are preliminary subtypes and may not exist. + if (HI_LATN != null) { + assertEquals("hi_ZZ", "Hindi/Anglais", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN)); + } + if (SR_LATN != null) { + assertEquals("sr_ZZ", "Serbe (latin)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN)); + } + return null; + } + }; + tests.runInLocale(mRes, Locale.FRENCH); + } + + @Test + public void testAdditionalSubtypesInFrenchSystemLocale() { + final RunInLocale<Void> tests = new RunInLocale<Void>() { + @Override + protected Void job(final Resources res) { + assertEquals("fr qwertz", "Français (QWERTZ)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(FR_QWERTZ)); + assertEquals("de qwerty", "Allemand (QWERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(DE_QWERTY)); + assertEquals("en_US azerty", "Anglais (États-Unis) (AZERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_US_AZERTY)); + assertEquals("en_UK dvorak", "Anglais (Royaume-Uni) (Dvorak)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(EN_UK_DVORAK)); + assertEquals("es_US colemak", "Espagnol (États-Unis) (Colemak)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ES_US_COLEMAK)); + assertEquals("zz azerty", "Alphabet latin (AZERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_AZERTY)); + assertEquals("zz pc", "Alphabet latin (PC)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(ZZ_PC)); + // These are preliminary subtypes and may not exist. + if (HI_LATN_DVORAK != null) { + assertEquals("hi_ZZ", "Hindi/Anglais (Dvorak)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK)); + } + if (SR_LATN_QWERTY != null) { + assertEquals("sr_ZZ", "Serbe (QWERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY)); + } + return null; + } + }; + tests.runInLocale(mRes, Locale.FRENCH); + } + + // InputMethodSubtype's display name in system locale (hi). + // isAdditionalSubtype (T=true, F=false) + // locale layout | display name + // ------ ------- - ---------------------- + // hi hindi F हिन्दी + // hi_ZZ qwerty F हिंग्लिश + // hi_ZZ dvorak T हिंग्लिश (Dvorak) + + @Test + public void testHinglishSubtypesInHindiSystemLocale() { + final RunInLocale<Void> tests = new RunInLocale<Void>() { + @Override + protected Void job (final Resources res) { + assertEquals("hi", "हिन्दी", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI)); + // These are preliminary subtypes and may not exist. + if (HI_LATN != null) { + assertEquals("hi_ZZ", "हिंग्लिश", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN)); + assertEquals("hi_ZZ", "हिंग्लिश (Dvorak)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(HI_LATN_DVORAK)); + } + return null; + } + }; + tests.runInLocale(mRes, new Locale("hi")); + } + + // InputMethodSubtype's display name in system locale (sr). + // isAdditionalSubtype (T=true, F=false) + // locale layout | display name + // ------ -------------- - ---------------------- + // sr south_slavic F Српски + // sr_ZZ serbian_qwertz F Српски (латиница) + // sr_ZZ qwerty T Српски (QWERTY) + + @Test + public void testSerbianLatinSubtypesInSerbianSystemLocale() { + final RunInLocale<Void> tests = new RunInLocale<Void>() { + @Override + protected Void job (final Resources res) { + assertEquals("sr", "Српски", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR)); + // These are preliminary subtypes and may not exist. + if (SR_LATN != null) { + assertEquals("sr_ZZ", "Српски (латиница)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN)); + assertEquals("sr_ZZ", "Српски (QWERTY)", + SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(SR_LATN_QWERTY)); + } + return null; + } + }; + tests.runInLocale(mRes, new Locale("sr")); + } + + @Test + public void testIsRtlLanguage() { + // Known Right-to-Left language subtypes. + final InputMethodSubtype ARABIC = mRichImm + .findSubtypeByLocaleAndKeyboardLayoutSet("ar", "arabic"); + assertNotNull("Arabic", ARABIC); + final InputMethodSubtype FARSI = mRichImm + .findSubtypeByLocaleAndKeyboardLayoutSet("fa", "farsi"); + assertNotNull("Farsi", FARSI); + final InputMethodSubtype HEBREW = mRichImm + .findSubtypeByLocaleAndKeyboardLayoutSet("iw", "hebrew"); + assertNotNull("Hebrew", HEBREW); + + for (final RichInputMethodSubtype subtype : mSubtypesList) { + final InputMethodSubtype rawSubtype = subtype.getRawSubtype(); + final String subtypeName = SubtypeLocaleUtils + .getSubtypeDisplayNameInSystemLocale(rawSubtype); + if (rawSubtype.equals(ARABIC) || rawSubtype.equals(FARSI) + || rawSubtype.equals(HEBREW)) { + assertTrue(subtypeName, subtype.isRtlSubtype()); + } else { + assertFalse(subtypeName, subtype.isRtlSubtype()); + } + } + } +} |