1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.inputmethod.latin.utils;
18 
19 import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_FULL_LOCALE;
20 import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_LANGUAGE_ONLY;
21 import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_NONE;
22 
23 import static org.junit.Assert.assertEquals;
24 
25 import android.content.Context;
26 import android.view.inputmethod.InputMethodSubtype;
27 
28 import androidx.test.InstrumentationRegistry;
29 import androidx.test.filters.SmallTest;
30 import androidx.test.runner.AndroidJUnit4;
31 
32 import com.android.inputmethod.latin.RichInputMethodManager;
33 import com.android.inputmethod.latin.RichInputMethodSubtype;
34 import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
35 import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
36 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
37 
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 import java.util.ArrayList;
43 import java.util.Locale;
44 
45 import javax.annotation.Nonnull;
46 
47 @SmallTest
48 @RunWith(AndroidJUnit4.class)
49 public class LanguageOnSpacebarUtilsTests {
50     private RichInputMethodManager mRichImm;
51 
52     RichInputMethodSubtype EN_US_QWERTY;
53     RichInputMethodSubtype EN_GB_QWERTY;
54     RichInputMethodSubtype FR_AZERTY;
55     RichInputMethodSubtype FR_CA_QWERTY;
56     RichInputMethodSubtype FR_CH_SWISS;
57     RichInputMethodSubtype FR_CH_QWERTY;
58     RichInputMethodSubtype FR_CH_QWERTZ;
59     RichInputMethodSubtype IW_HEBREW;
60     RichInputMethodSubtype ZZ_QWERTY;
61 
62     @Before
setUp()63     public void setUp() throws Exception {
64         final Context context = InstrumentationRegistry.getTargetContext();
65         RichInputMethodManager.init(context);
66         mRichImm = RichInputMethodManager.getInstance();
67 
68         EN_US_QWERTY = findSubtypeOf(Locale.US.toString(), "qwerty");
69         EN_GB_QWERTY = findSubtypeOf(Locale.UK.toString(), "qwerty");
70         FR_AZERTY = findSubtypeOf(Locale.FRENCH.toString(), "azerty");
71         FR_CA_QWERTY = findSubtypeOf(Locale.CANADA_FRENCH.toString(), "qwerty");
72         FR_CH_SWISS = findSubtypeOf("fr_CH", "swiss");
73         FR_CH_QWERTZ = new RichInputMethodSubtype(
74                 AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwertz"));
75         FR_CH_QWERTY = new RichInputMethodSubtype(
76                 AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwerty"));
77         IW_HEBREW = findSubtypeOf("iw", "hebrew");
78         ZZ_QWERTY = findSubtypeOf(SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
79     }
80 
81     @Nonnull
findSubtypeOf(final String localeString, final String keyboardLayoutSetName)82     private RichInputMethodSubtype findSubtypeOf(final String localeString,
83             final String keyboardLayoutSetName) {
84         final InputMethodSubtype subtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
85                 localeString, keyboardLayoutSetName);
86         if (subtype == null) {
87             throw new RuntimeException("Can't find subtype of " + localeString + " with "
88                     + keyboardLayoutSetName);
89         }
90         return new RichInputMethodSubtype(subtype);
91     }
92 
enableSubtypes(final RichInputMethodSubtype ... subtypes)93     private static void enableSubtypes(final RichInputMethodSubtype ... subtypes) {
94         final ArrayList<InputMethodSubtype> enabledSubtypes = new ArrayList<>();
95         for (final RichInputMethodSubtype subtype : subtypes) {
96             enabledSubtypes.add(subtype.getRawSubtype());
97         }
98         LanguageOnSpacebarUtils.setEnabledSubtypes(enabledSubtypes);
99     }
100 
assertFormatType(final RichInputMethodSubtype subtype, final boolean implicitlyEnabledSubtype, final Locale systemLocale, final int expectedFormat)101     private static void assertFormatType(final RichInputMethodSubtype subtype,
102             final boolean implicitlyEnabledSubtype, final Locale systemLocale,
103             final int expectedFormat) {
104         LanguageOnSpacebarUtils.onSubtypeChanged(subtype, implicitlyEnabledSubtype, systemLocale);
105         assertEquals(subtype.getLocale() + " implicitly=" + implicitlyEnabledSubtype
106                 + " in " + systemLocale, expectedFormat,
107                 LanguageOnSpacebarUtils.getLanguageOnSpacebarFormatType(subtype));
108     }
109 
110     @Test
testOneSubtypeImplicitlyEnabled()111     public void testOneSubtypeImplicitlyEnabled() {
112         enableSubtypes(EN_US_QWERTY);
113         assertFormatType(EN_US_QWERTY, true, Locale.US,            FORMAT_TYPE_NONE);
114 
115         enableSubtypes(EN_GB_QWERTY);
116         assertFormatType(EN_GB_QWERTY, true, Locale.UK,            FORMAT_TYPE_NONE);
117 
118         enableSubtypes(FR_AZERTY);
119         assertFormatType(FR_AZERTY,    true, Locale.FRANCE,        FORMAT_TYPE_NONE);
120 
121         enableSubtypes(FR_CA_QWERTY);
122         assertFormatType(FR_CA_QWERTY, true, Locale.CANADA_FRENCH, FORMAT_TYPE_NONE);
123     }
124 
125     @Test
testOneSubtypeExplicitlyEnabled()126     public void testOneSubtypeExplicitlyEnabled() {
127         enableSubtypes(EN_US_QWERTY);
128         assertFormatType(EN_US_QWERTY, false, Locale.UK,     FORMAT_TYPE_LANGUAGE_ONLY);
129         assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
130 
131         enableSubtypes(EN_GB_QWERTY);
132         assertFormatType(EN_GB_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
133         assertFormatType(EN_GB_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
134 
135         enableSubtypes(FR_AZERTY);
136         assertFormatType(FR_AZERTY,    false, Locale.US,            FORMAT_TYPE_LANGUAGE_ONLY);
137         assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
138 
139         enableSubtypes(FR_CA_QWERTY);
140         assertFormatType(FR_CA_QWERTY, false, Locale.US,            FORMAT_TYPE_LANGUAGE_ONLY);
141         assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE,        FORMAT_TYPE_LANGUAGE_ONLY);
142     }
143 
144     @Test
testOneSubtypeImplicitlyEnabledWithNoLanguageSubtype()145     public void testOneSubtypeImplicitlyEnabledWithNoLanguageSubtype() {
146         final Locale Locale_IW = new Locale("iw");
147         enableSubtypes(IW_HEBREW, ZZ_QWERTY);
148         // TODO: Should this be FORMAT_TYPE_NONE?
149         assertFormatType(IW_HEBREW,    true, Locale_IW, FORMAT_TYPE_LANGUAGE_ONLY);
150         // TODO: Should this be FORMAT_TYPE_NONE?
151         assertFormatType(ZZ_QWERTY,    true, Locale_IW, FORMAT_TYPE_FULL_LOCALE);
152     }
153 
154     @Test
testTwoSubtypesExplicitlyEnabled()155     public void testTwoSubtypesExplicitlyEnabled() {
156         enableSubtypes(EN_US_QWERTY, FR_AZERTY);
157         assertFormatType(EN_US_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
158         assertFormatType(FR_AZERTY,    false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
159         assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
160         assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
161         assertFormatType(EN_US_QWERTY, false, Locale.JAPAN,  FORMAT_TYPE_LANGUAGE_ONLY);
162         assertFormatType(FR_AZERTY,    false, Locale.JAPAN,  FORMAT_TYPE_LANGUAGE_ONLY);
163 
164         enableSubtypes(EN_US_QWERTY, ZZ_QWERTY);
165         assertFormatType(EN_US_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
166         assertFormatType(ZZ_QWERTY,    false, Locale.US,     FORMAT_TYPE_FULL_LOCALE);
167         assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
168         assertFormatType(ZZ_QWERTY,    false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
169 
170     }
171 
172     @Test
testMultiSubtypeWithSameLanuageAndSameLayout()173     public void testMultiSubtypeWithSameLanuageAndSameLayout() {
174         // Explicitly enable en_US, en_GB, fr_FR, and no language keyboards.
175         enableSubtypes(EN_US_QWERTY, EN_GB_QWERTY, FR_CA_QWERTY, ZZ_QWERTY);
176 
177         assertFormatType(EN_US_QWERTY, false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
178         assertFormatType(EN_GB_QWERTY, false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
179         assertFormatType(FR_CA_QWERTY, false, Locale.US,    FORMAT_TYPE_LANGUAGE_ONLY);
180         assertFormatType(ZZ_QWERTY,    false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
181 
182         assertFormatType(EN_US_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
183         assertFormatType(EN_GB_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
184         assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
185         assertFormatType(ZZ_QWERTY,    false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
186     }
187 
188     @Test
testMultiSubtypesWithSameLanguageButHaveDifferentLayout()189     public void testMultiSubtypesWithSameLanguageButHaveDifferentLayout() {
190         enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTZ);
191 
192         assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
193         assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
194         assertFormatType(FR_CH_SWISS,  false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
195         assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
196 
197         assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
198         assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
199         assertFormatType(FR_CH_SWISS,  false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
200         assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
201 
202         assertFormatType(FR_AZERTY,    false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
203         assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
204         assertFormatType(FR_CH_SWISS,  false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
205         assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
206     }
207 
208     @Test
testMultiSubtypesWithSameLanguageAndMayHaveSameLayout()209     public void testMultiSubtypesWithSameLanguageAndMayHaveSameLayout() {
210         enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTY, FR_CH_QWERTZ);
211 
212         assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
213         assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
214         assertFormatType(FR_CH_SWISS,  false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
215         assertFormatType(FR_CH_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
216         assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
217 
218         assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
219         assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE);
220         assertFormatType(FR_CH_SWISS,  false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
221         assertFormatType(FR_CH_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE);
222         assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
223 
224         assertFormatType(FR_AZERTY,    false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
225         assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
226         assertFormatType(FR_CH_SWISS,  false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
227         assertFormatType(FR_CH_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
228         assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
229     }
230 }
231