Loading core/java/com/android/internal/inputmethod/InputMethodUtils.java +1 −71 Original line number Original line Diff line number Diff line Loading @@ -34,10 +34,6 @@ import android.os.LocaleList; import android.os.RemoteException; import android.os.RemoteException; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Pair; import android.util.Pair; import android.util.Printer; import android.util.Printer; import android.util.Slog; import android.util.Slog; Loading Loading @@ -782,58 +778,6 @@ public class InputMethodUtils { } } } } /** * Parses the setting stored input methods and subtypes string value. * * @param inputMethodsAndSubtypesString The input method subtypes value stored in settings. * @return Map from input method ID to set of input method subtypes IDs. */ @VisibleForTesting public static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString( @Nullable final String inputMethodsAndSubtypesString) { final ArrayMap<String, ArraySet<String>> imeMap = new ArrayMap<>(); if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { return imeMap; } final SimpleStringSplitter typeSplitter = new SimpleStringSplitter(INPUT_METHOD_SEPARATOR); final SimpleStringSplitter subtypeSplitter = new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR); List<Pair<String, ArrayList<String>>> allImeSettings = InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString, typeSplitter, subtypeSplitter); for (Pair<String, ArrayList<String>> ime : allImeSettings) { ArraySet<String> subtypes = new ArraySet<>(); if (ime.second != null) { subtypes.addAll(ime.second); } imeMap.put(ime.first, subtypes); } return imeMap; } @NonNull public static String buildInputMethodsAndSubtypesString( @NonNull final ArrayMap<String, ArraySet<String>> map) { // we want to use the canonical InputMethodSettings implementation, // so we convert data structures first. List<Pair<String, ArrayList<String>>> imeMap = new ArrayList<>(4); for (ArrayMap.Entry<String, ArraySet<String>> entry : map.entrySet()) { final String imeName = entry.getKey(); final ArraySet<String> subtypeSet = entry.getValue(); final ArrayList<String> subtypes = new ArrayList<>(2); if (subtypeSet != null) { subtypes.addAll(subtypeSet); } imeMap.add(new Pair<>(imeName, subtypes)); } return InputMethodSettings.buildInputMethodsSettingString(imeMap); } /** /** * Utility class for putting and getting settings for InputMethod * Utility class for putting and getting settings for InputMethod * TODO: Move all putters and getters of settings to this class. * TODO: Move all putters and getters of settings to this class. Loading Loading @@ -871,21 +815,7 @@ public class InputMethodUtils { } } } } public static String buildInputMethodsSettingString( private static List<Pair<String, ArrayList<String>>> buildInputMethodsAndSubtypeList( List<Pair<String, ArrayList<String>>> allImeSettingsMap) { final StringBuilder b = new StringBuilder(); boolean needsSeparator = false; for (Pair<String, ArrayList<String>> ime : allImeSettingsMap) { if (needsSeparator) { b.append(INPUT_METHOD_SEPARATOR); } buildEnabledInputMethodsSettingString(b, ime); needsSeparator = true; } return b.toString(); } public static List<Pair<String, ArrayList<String>>> buildInputMethodsAndSubtypeList( String enabledInputMethodsStr, String enabledInputMethodsStr, TextUtils.SimpleStringSplitter inputMethodSplitter, TextUtils.SimpleStringSplitter inputMethodSplitter, TextUtils.SimpleStringSplitter subtypeSplitter) { TextUtils.SimpleStringSplitter subtypeSplitter) { Loading core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java +0 −244 Original line number Original line Diff line number Diff line Loading @@ -40,8 +40,6 @@ import android.os.Parcel; import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4; import android.util.ArrayMap; import android.util.ArraySet; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; Loading Loading @@ -1191,248 +1189,6 @@ public class InputMethodUtilsTest { } } } } @Test public void testParseInputMethodsAndSubtypesString() { // Trivial cases. { assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString("").isEmpty()); assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString(null).isEmpty()); } // No subtype cases. { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.get("ime0").isEmpty()); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0:ime1"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.get("ime0").isEmpty()); assertTrue(r.containsKey("ime1")); assertTrue(r.get("ime1").isEmpty()); } // Input metho IDs and their subtypes. { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(1, subtypes.size()); assertTrue(subtypes.contains("subtype0")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(1, subtypes.size()); assertTrue(subtypes.contains("subtype0")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype1"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(2, subtypes.size()); assertTrue(subtypes.contains("subtype0")); assertTrue(subtypes.contains("subtype1")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0:ime1;subtype1"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(1, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(1, subtypes1.size()); assertTrue(subtypes1.contains("subtype1")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype2"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(1, subtypes1.size()); assertTrue(subtypes1.contains("subtype2")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(2, subtypes1.size()); assertTrue(subtypes0.contains("subtype1")); assertTrue(subtypes1.contains("subtype2")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2"); assertEquals(3, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); assertTrue(r.containsKey("ime2")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(2, subtypes1.size()); assertTrue(subtypes0.contains("subtype1")); assertTrue(subtypes1.contains("subtype2")); ArraySet<String> subtypes2 = r.get("ime2"); assertTrue(subtypes2.isEmpty()); } } @Test public void testbuildInputMethodsAndSubtypesString() { { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); assertEquals("", InputMethodUtils.buildInputMethodsAndSubtypesString(map)); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); map.put("ime0", new ArraySet<>()); assertEquals("ime0", InputMethodUtils.buildInputMethodsAndSubtypesString(map)); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); map.put("ime0", subtypes1); assertEquals("ime0;subtype0", InputMethodUtils.buildInputMethodsAndSubtypesString(map)); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); subtypes1.add("subtype1"); map.put("ime0", subtypes1); // We do not expect what order will be used to concatenate items in // InputMethodUtils.buildInputMethodsAndSubtypesString() hence enumerate all possible // permutations here. ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0;subtype1"); validSequences.add("ime0;subtype1;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); map.put("ime0", new ArraySet<>()); map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0:ime1"); validSequences.add("ime1:ime0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); map.put("ime0", subtypes1); map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0:ime1"); validSequences.add("ime1;ime0;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); subtypes1.add("subtype1"); map.put("ime0", subtypes1); map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0;subtype1:ime1"); validSequences.add("ime0;subtype1;subtype0:ime1"); validSequences.add("ime1:ime0;subtype0;subtype1"); validSequences.add("ime1:ime0;subtype1;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); map.put("ime0", subtypes1); ArraySet<String> subtypes2 = new ArraySet<>(); subtypes2.add("subtype1"); map.put("ime1", subtypes2); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0:ime1;subtype1"); validSequences.add("ime1;subtype1:ime0;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); subtypes1.add("subtype1"); map.put("ime0", subtypes1); ArraySet<String> subtypes2 = new ArraySet<>(); subtypes2.add("subtype2"); subtypes2.add("subtype3"); map.put("ime1", subtypes2); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0;subtype1:ime1;subtype2;subtype3"); validSequences.add("ime0;subtype1;subtype0:ime1;subtype2;subtype3"); validSequences.add("ime0;subtype0;subtype1:ime1;subtype3;subtype2"); validSequences.add("ime0;subtype1;subtype0:ime1;subtype3;subtype2"); validSequences.add("ime1;subtype2;subtype3:ime0;subtype0;subtype1"); validSequences.add("ime2;subtype3;subtype2:ime0;subtype0;subtype1"); validSequences.add("ime3;subtype2;subtype3:ime0;subtype1;subtype0"); validSequences.add("ime4;subtype3;subtype2:ime0;subtype1;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } } @Test @Test public void testConstructLocaleFromString() throws Exception { public void testConstructLocaleFromString() throws Exception { assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en")); assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en")); Loading packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -60,7 +60,7 @@ public class InputMethodAndSubtypeUtil { // InputMethods and subtypes are saved in the settings as follows: // InputMethods and subtypes are saved in the settings as follows: // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1 // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1 private static String buildInputMethodsAndSubtypesString( public static String buildInputMethodsAndSubtypesString( final HashMap<String, HashSet<String>> imeToSubtypesMap) { final HashMap<String, HashSet<String>> imeToSubtypesMap) { final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder(); for (final String imi : imeToSubtypesMap.keySet()) { for (final String imi : imeToSubtypesMap.keySet()) { Loading Loading @@ -115,7 +115,7 @@ public class InputMethodAndSubtypeUtil { return parseInputMethodsAndSubtypesString(enabledInputMethodsStr); return parseInputMethodsAndSubtypesString(enabledInputMethodsStr); } } private static HashMap<String, HashSet<String>> parseInputMethodsAndSubtypesString( public static HashMap<String, HashSet<String>> parseInputMethodsAndSubtypesString( final String inputMethodsAndSubtypesString) { final String inputMethodsAndSubtypesString) { final HashMap<String, HashSet<String>> subtypesMap = new HashMap<>(); final HashMap<String, HashSet<String>> subtypesMap = new HashMap<>(); if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java 0 → 100644 +190 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settingslib.inputmethod; import static com.google.common.truth.Truth.assertThat; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import java.util.HashMap; import java.util.HashSet; @RunWith(RobolectricTestRunner.class) public class InputMethodAndSubtypeUtilTest { private static final HashSet<String> EMPTY_STRING_SET = new HashSet<>(); private static HashSet<String> asHashSet(String... strings) { HashSet<String> hashSet = new HashSet<>(); for (String s : strings) { hashSet.add(s); } return hashSet; } @Test public void testParseInputMethodsAndSubtypesString_EmptyString() { assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString("")).isEmpty(); assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString(null)).isEmpty(); } @Test public void testParseInputMethodsAndSubtypesString_SingleImeNoSubtype() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString("ime0"); assertThat(r).containsExactly("ime0", EMPTY_STRING_SET); } @Test public void testParseInputMethodsAndSubtypesString_MultipleImesNoSubtype() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString("ime0:ime1"); assertThat(r).containsExactly("ime0", EMPTY_STRING_SET, "ime1", EMPTY_STRING_SET); } @Test public void testParseInputMethodsAndSubtypesString_SingleImeSingleSubtype() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString("ime0;subtype0"); assertThat(r).containsExactly("ime0", asHashSet("subtype0")); } @Test public void testParseInputMethodsAndSubtypesString_SingleImeDuplicateSameSubtypes() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype0"); assertThat(r).containsExactly("ime0", asHashSet("subtype0")); } @Test public void testParseInputMethodsAndSubtypesString_SingleImeMultipleSubtypes() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1"); assertThat(r).containsExactly("ime0", asHashSet("subtype0", "subtype1")); } @Test public void testParseInputMethodsAndSubtypesString_MultiplePairsOfImeSubtype() { assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0:ime1;subtype1")) .containsExactly("ime0", asHashSet("subtype0"), "ime1", asHashSet("subtype1")); assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype2")) .containsExactly("ime0", asHashSet("subtype0", "subtype1"), "ime1", asHashSet("subtype2")); assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2")) .containsExactly("ime0", asHashSet("subtype0", "subtype1"), "ime1", asHashSet("subtype1", "subtype2")); } @Test public void testParseInputMethodsAndSubtypesString_MixedImeSubtypePairsAndImeNoSubtype() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2"); assertThat(r).containsExactly("ime0", asHashSet("subtype0", "subtype1"), "ime1", asHashSet("subtype1", "subtype2"), "ime2", EMPTY_STRING_SET); } @Test public void testBuildInputMethodsAndSubtypesString_EmptyInput() { HashMap<String, HashSet<String>> map = new HashMap<>(); assertThat(map).isEmpty(); } @Test public void testBuildInputMethodsAndSubtypesString_SingleIme() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", new HashSet<>()); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); assertThat(result).isEqualTo("ime0"); } @Test public void testBuildInputMethodsAndSubtypesString_SingleImeSingleSubtype() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", asHashSet("subtype0")); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); assertThat(result).isEqualTo("ime0;subtype0"); } @Test public void testBuildInputMethodsAndSubtypesString_SingleImeMultipleSubtypes() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", asHashSet("subtype0", "subtype1")); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); // We do not expect what order will be used to concatenate items in // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible // permutations here. assertThat(result).matches("(ime0;subtype0;subtype1)|(ime0;subtype1;subtype0)"); } @Test public void testBuildInputMethodsAndSubtypesString_MultipleImesNoSubtypes() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", EMPTY_STRING_SET); map.put("ime1", EMPTY_STRING_SET); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); // We do not expect what order will be used to concatenate items in // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible // permutations here. assertThat(result).matches("(ime0:ime1)|(ime1:ime0)"); } @Test public void testBuildInputMethodsAndSubtypesString_MultipleImesWithAndWithoutSubtypes() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", asHashSet("subtype0", "subtype1")); map.put("ime1", EMPTY_STRING_SET); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); // We do not expect what order will be used to concatenate items in // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible // permutations here. assertThat(result).matches("(ime0;subtype0;subtype1:ime1)|(ime0;subtype1;subtype0:ime1)" + "|(ime1:ime0;subtype0;subtype1)|(ime1:ime0;subtype1;subtype0)"); } @Test public void testBuildInputMethodsAndSubtypesString_MultipleImesWithSubtypes() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", asHashSet("subtype0", "subtype1")); map.put("ime1", asHashSet("subtype2", "subtype3")); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); // We do not expect what order will be used to concatenate items in // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible // permutations here. assertThat(result).matches("|(ime0;subtype0;subtype1:ime1;subtype2;subtype3)|" + "|(ime0;subtype1;subtype0:ime1;subtype2;subtype3)|" + "|(ime0;subtype0;subtype1:ime1;subtype3;subtype2)|" + "|(ime0;subtype1;subtype0:ime1;subtype3;subtype2)|" + "|(ime1;subtype2;subtype3:ime0;subtype0;subtype1)|" + "|(ime2;subtype3;subtype2:ime0;subtype0;subtype1)|" + "|(ime3;subtype2;subtype3:ime0;subtype1;subtype0)|" + "|(ime4;subtype3;subtype2:ime0;subtype1;subtype0)"); } } Loading
core/java/com/android/internal/inputmethod/InputMethodUtils.java +1 −71 Original line number Original line Diff line number Diff line Loading @@ -34,10 +34,6 @@ import android.os.LocaleList; import android.os.RemoteException; import android.os.RemoteException; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Pair; import android.util.Pair; import android.util.Printer; import android.util.Printer; import android.util.Slog; import android.util.Slog; Loading Loading @@ -782,58 +778,6 @@ public class InputMethodUtils { } } } } /** * Parses the setting stored input methods and subtypes string value. * * @param inputMethodsAndSubtypesString The input method subtypes value stored in settings. * @return Map from input method ID to set of input method subtypes IDs. */ @VisibleForTesting public static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString( @Nullable final String inputMethodsAndSubtypesString) { final ArrayMap<String, ArraySet<String>> imeMap = new ArrayMap<>(); if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { return imeMap; } final SimpleStringSplitter typeSplitter = new SimpleStringSplitter(INPUT_METHOD_SEPARATOR); final SimpleStringSplitter subtypeSplitter = new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR); List<Pair<String, ArrayList<String>>> allImeSettings = InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString, typeSplitter, subtypeSplitter); for (Pair<String, ArrayList<String>> ime : allImeSettings) { ArraySet<String> subtypes = new ArraySet<>(); if (ime.second != null) { subtypes.addAll(ime.second); } imeMap.put(ime.first, subtypes); } return imeMap; } @NonNull public static String buildInputMethodsAndSubtypesString( @NonNull final ArrayMap<String, ArraySet<String>> map) { // we want to use the canonical InputMethodSettings implementation, // so we convert data structures first. List<Pair<String, ArrayList<String>>> imeMap = new ArrayList<>(4); for (ArrayMap.Entry<String, ArraySet<String>> entry : map.entrySet()) { final String imeName = entry.getKey(); final ArraySet<String> subtypeSet = entry.getValue(); final ArrayList<String> subtypes = new ArrayList<>(2); if (subtypeSet != null) { subtypes.addAll(subtypeSet); } imeMap.add(new Pair<>(imeName, subtypes)); } return InputMethodSettings.buildInputMethodsSettingString(imeMap); } /** /** * Utility class for putting and getting settings for InputMethod * Utility class for putting and getting settings for InputMethod * TODO: Move all putters and getters of settings to this class. * TODO: Move all putters and getters of settings to this class. Loading Loading @@ -871,21 +815,7 @@ public class InputMethodUtils { } } } } public static String buildInputMethodsSettingString( private static List<Pair<String, ArrayList<String>>> buildInputMethodsAndSubtypeList( List<Pair<String, ArrayList<String>>> allImeSettingsMap) { final StringBuilder b = new StringBuilder(); boolean needsSeparator = false; for (Pair<String, ArrayList<String>> ime : allImeSettingsMap) { if (needsSeparator) { b.append(INPUT_METHOD_SEPARATOR); } buildEnabledInputMethodsSettingString(b, ime); needsSeparator = true; } return b.toString(); } public static List<Pair<String, ArrayList<String>>> buildInputMethodsAndSubtypeList( String enabledInputMethodsStr, String enabledInputMethodsStr, TextUtils.SimpleStringSplitter inputMethodSplitter, TextUtils.SimpleStringSplitter inputMethodSplitter, TextUtils.SimpleStringSplitter subtypeSplitter) { TextUtils.SimpleStringSplitter subtypeSplitter) { Loading
core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java +0 −244 Original line number Original line Diff line number Diff line Loading @@ -40,8 +40,6 @@ import android.os.Parcel; import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4; import android.util.ArrayMap; import android.util.ArraySet; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; Loading Loading @@ -1191,248 +1189,6 @@ public class InputMethodUtilsTest { } } } } @Test public void testParseInputMethodsAndSubtypesString() { // Trivial cases. { assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString("").isEmpty()); assertTrue(InputMethodUtils.parseInputMethodsAndSubtypesString(null).isEmpty()); } // No subtype cases. { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.get("ime0").isEmpty()); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0:ime1"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.get("ime0").isEmpty()); assertTrue(r.containsKey("ime1")); assertTrue(r.get("ime1").isEmpty()); } // Input metho IDs and their subtypes. { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(1, subtypes.size()); assertTrue(subtypes.contains("subtype0")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype0"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(1, subtypes.size()); assertTrue(subtypes.contains("subtype0")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString("ime0;subtype0;subtype1"); assertEquals(1, r.size()); assertTrue(r.containsKey("ime0")); ArraySet<String> subtypes = r.get("ime0"); assertEquals(2, subtypes.size()); assertTrue(subtypes.contains("subtype0")); assertTrue(subtypes.contains("subtype1")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0:ime1;subtype1"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(1, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(1, subtypes1.size()); assertTrue(subtypes1.contains("subtype1")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype2"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(1, subtypes1.size()); assertTrue(subtypes1.contains("subtype2")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2"); assertEquals(2, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(2, subtypes1.size()); assertTrue(subtypes0.contains("subtype1")); assertTrue(subtypes1.contains("subtype2")); } { ArrayMap<String, ArraySet<String>> r = InputMethodUtils.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2"); assertEquals(3, r.size()); assertTrue(r.containsKey("ime0")); assertTrue(r.containsKey("ime1")); assertTrue(r.containsKey("ime2")); ArraySet<String> subtypes0 = r.get("ime0"); assertEquals(2, subtypes0.size()); assertTrue(subtypes0.contains("subtype0")); assertTrue(subtypes0.contains("subtype1")); ArraySet<String> subtypes1 = r.get("ime1"); assertEquals(2, subtypes1.size()); assertTrue(subtypes0.contains("subtype1")); assertTrue(subtypes1.contains("subtype2")); ArraySet<String> subtypes2 = r.get("ime2"); assertTrue(subtypes2.isEmpty()); } } @Test public void testbuildInputMethodsAndSubtypesString() { { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); assertEquals("", InputMethodUtils.buildInputMethodsAndSubtypesString(map)); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); map.put("ime0", new ArraySet<>()); assertEquals("ime0", InputMethodUtils.buildInputMethodsAndSubtypesString(map)); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); map.put("ime0", subtypes1); assertEquals("ime0;subtype0", InputMethodUtils.buildInputMethodsAndSubtypesString(map)); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); subtypes1.add("subtype1"); map.put("ime0", subtypes1); // We do not expect what order will be used to concatenate items in // InputMethodUtils.buildInputMethodsAndSubtypesString() hence enumerate all possible // permutations here. ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0;subtype1"); validSequences.add("ime0;subtype1;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); map.put("ime0", new ArraySet<>()); map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0:ime1"); validSequences.add("ime1:ime0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); map.put("ime0", subtypes1); map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0:ime1"); validSequences.add("ime1;ime0;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); subtypes1.add("subtype1"); map.put("ime0", subtypes1); map.put("ime1", new ArraySet<>()); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0;subtype1:ime1"); validSequences.add("ime0;subtype1;subtype0:ime1"); validSequences.add("ime1:ime0;subtype0;subtype1"); validSequences.add("ime1:ime0;subtype1;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); map.put("ime0", subtypes1); ArraySet<String> subtypes2 = new ArraySet<>(); subtypes2.add("subtype1"); map.put("ime1", subtypes2); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0:ime1;subtype1"); validSequences.add("ime1;subtype1:ime0;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } { ArrayMap<String, ArraySet<String>> map = new ArrayMap<>(); ArraySet<String> subtypes1 = new ArraySet<>(); subtypes1.add("subtype0"); subtypes1.add("subtype1"); map.put("ime0", subtypes1); ArraySet<String> subtypes2 = new ArraySet<>(); subtypes2.add("subtype2"); subtypes2.add("subtype3"); map.put("ime1", subtypes2); ArraySet<String> validSequences = new ArraySet<>(); validSequences.add("ime0;subtype0;subtype1:ime1;subtype2;subtype3"); validSequences.add("ime0;subtype1;subtype0:ime1;subtype2;subtype3"); validSequences.add("ime0;subtype0;subtype1:ime1;subtype3;subtype2"); validSequences.add("ime0;subtype1;subtype0:ime1;subtype3;subtype2"); validSequences.add("ime1;subtype2;subtype3:ime0;subtype0;subtype1"); validSequences.add("ime2;subtype3;subtype2:ime0;subtype0;subtype1"); validSequences.add("ime3;subtype2;subtype3:ime0;subtype1;subtype0"); validSequences.add("ime4;subtype3;subtype2:ime0;subtype1;subtype0"); assertTrue(validSequences.contains( InputMethodUtils.buildInputMethodsAndSubtypesString(map))); } } @Test @Test public void testConstructLocaleFromString() throws Exception { public void testConstructLocaleFromString() throws Exception { assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en")); assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en")); Loading
packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -60,7 +60,7 @@ public class InputMethodAndSubtypeUtil { // InputMethods and subtypes are saved in the settings as follows: // InputMethods and subtypes are saved in the settings as follows: // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1 // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1 private static String buildInputMethodsAndSubtypesString( public static String buildInputMethodsAndSubtypesString( final HashMap<String, HashSet<String>> imeToSubtypesMap) { final HashMap<String, HashSet<String>> imeToSubtypesMap) { final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder(); for (final String imi : imeToSubtypesMap.keySet()) { for (final String imi : imeToSubtypesMap.keySet()) { Loading Loading @@ -115,7 +115,7 @@ public class InputMethodAndSubtypeUtil { return parseInputMethodsAndSubtypesString(enabledInputMethodsStr); return parseInputMethodsAndSubtypesString(enabledInputMethodsStr); } } private static HashMap<String, HashSet<String>> parseInputMethodsAndSubtypesString( public static HashMap<String, HashSet<String>> parseInputMethodsAndSubtypesString( final String inputMethodsAndSubtypesString) { final String inputMethodsAndSubtypesString) { final HashMap<String, HashSet<String>> subtypesMap = new HashMap<>(); final HashMap<String, HashSet<String>> subtypesMap = new HashMap<>(); if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) { Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java 0 → 100644 +190 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settingslib.inputmethod; import static com.google.common.truth.Truth.assertThat; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import java.util.HashMap; import java.util.HashSet; @RunWith(RobolectricTestRunner.class) public class InputMethodAndSubtypeUtilTest { private static final HashSet<String> EMPTY_STRING_SET = new HashSet<>(); private static HashSet<String> asHashSet(String... strings) { HashSet<String> hashSet = new HashSet<>(); for (String s : strings) { hashSet.add(s); } return hashSet; } @Test public void testParseInputMethodsAndSubtypesString_EmptyString() { assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString("")).isEmpty(); assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString(null)).isEmpty(); } @Test public void testParseInputMethodsAndSubtypesString_SingleImeNoSubtype() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString("ime0"); assertThat(r).containsExactly("ime0", EMPTY_STRING_SET); } @Test public void testParseInputMethodsAndSubtypesString_MultipleImesNoSubtype() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString("ime0:ime1"); assertThat(r).containsExactly("ime0", EMPTY_STRING_SET, "ime1", EMPTY_STRING_SET); } @Test public void testParseInputMethodsAndSubtypesString_SingleImeSingleSubtype() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString("ime0;subtype0"); assertThat(r).containsExactly("ime0", asHashSet("subtype0")); } @Test public void testParseInputMethodsAndSubtypesString_SingleImeDuplicateSameSubtypes() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype0"); assertThat(r).containsExactly("ime0", asHashSet("subtype0")); } @Test public void testParseInputMethodsAndSubtypesString_SingleImeMultipleSubtypes() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1"); assertThat(r).containsExactly("ime0", asHashSet("subtype0", "subtype1")); } @Test public void testParseInputMethodsAndSubtypesString_MultiplePairsOfImeSubtype() { assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0:ime1;subtype1")) .containsExactly("ime0", asHashSet("subtype0"), "ime1", asHashSet("subtype1")); assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype2")) .containsExactly("ime0", asHashSet("subtype0", "subtype1"), "ime1", asHashSet("subtype2")); assertThat(InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2")) .containsExactly("ime0", asHashSet("subtype0", "subtype1"), "ime1", asHashSet("subtype1", "subtype2")); } @Test public void testParseInputMethodsAndSubtypesString_MixedImeSubtypePairsAndImeNoSubtype() { HashMap<String, HashSet<String>> r = InputMethodAndSubtypeUtil.parseInputMethodsAndSubtypesString( "ime0;subtype0;subtype1:ime1;subtype1;subtype2:ime2"); assertThat(r).containsExactly("ime0", asHashSet("subtype0", "subtype1"), "ime1", asHashSet("subtype1", "subtype2"), "ime2", EMPTY_STRING_SET); } @Test public void testBuildInputMethodsAndSubtypesString_EmptyInput() { HashMap<String, HashSet<String>> map = new HashMap<>(); assertThat(map).isEmpty(); } @Test public void testBuildInputMethodsAndSubtypesString_SingleIme() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", new HashSet<>()); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); assertThat(result).isEqualTo("ime0"); } @Test public void testBuildInputMethodsAndSubtypesString_SingleImeSingleSubtype() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", asHashSet("subtype0")); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); assertThat(result).isEqualTo("ime0;subtype0"); } @Test public void testBuildInputMethodsAndSubtypesString_SingleImeMultipleSubtypes() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", asHashSet("subtype0", "subtype1")); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); // We do not expect what order will be used to concatenate items in // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible // permutations here. assertThat(result).matches("(ime0;subtype0;subtype1)|(ime0;subtype1;subtype0)"); } @Test public void testBuildInputMethodsAndSubtypesString_MultipleImesNoSubtypes() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", EMPTY_STRING_SET); map.put("ime1", EMPTY_STRING_SET); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); // We do not expect what order will be used to concatenate items in // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible // permutations here. assertThat(result).matches("(ime0:ime1)|(ime1:ime0)"); } @Test public void testBuildInputMethodsAndSubtypesString_MultipleImesWithAndWithoutSubtypes() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", asHashSet("subtype0", "subtype1")); map.put("ime1", EMPTY_STRING_SET); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); // We do not expect what order will be used to concatenate items in // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible // permutations here. assertThat(result).matches("(ime0;subtype0;subtype1:ime1)|(ime0;subtype1;subtype0:ime1)" + "|(ime1:ime0;subtype0;subtype1)|(ime1:ime0;subtype1;subtype0)"); } @Test public void testBuildInputMethodsAndSubtypesString_MultipleImesWithSubtypes() { HashMap<String, HashSet<String>> map = new HashMap<>(); map.put("ime0", asHashSet("subtype0", "subtype1")); map.put("ime1", asHashSet("subtype2", "subtype3")); String result = InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString(map); // We do not expect what order will be used to concatenate items in // InputMethodAndSubtypeUtil.buildInputMethodsAndSubtypesString() hence accept all possible // permutations here. assertThat(result).matches("|(ime0;subtype0;subtype1:ime1;subtype2;subtype3)|" + "|(ime0;subtype1;subtype0:ime1;subtype2;subtype3)|" + "|(ime0;subtype0;subtype1:ime1;subtype3;subtype2)|" + "|(ime0;subtype1;subtype0:ime1;subtype3;subtype2)|" + "|(ime1;subtype2;subtype3:ime0;subtype0;subtype1)|" + "|(ime2;subtype3;subtype2:ime0;subtype0;subtype1)|" + "|(ime3;subtype2;subtype3:ime0;subtype1;subtype0)|" + "|(ime4;subtype3;subtype2:ime0;subtype1;subtype0)"); } }