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
17package com.android.inputmethod.latin.utils;
18
19import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_FULL_LOCALE;
20import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_LANGUAGE_ONLY;
21import static com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils.FORMAT_TYPE_NONE;
22
23import android.content.Context;
24import android.test.AndroidTestCase;
25import android.test.suitebuilder.annotation.SmallTest;
26import android.view.inputmethod.InputMethodSubtype;
27
28import com.android.inputmethod.latin.RichInputMethodManager;
29import com.android.inputmethod.latin.RichInputMethodSubtype;
30import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
31import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
32import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
33
34import java.util.ArrayList;
35import java.util.Locale;
36
37import javax.annotation.Nonnull;
38
39@SmallTest
40public class LanguageOnSpacebarUtilsTests extends AndroidTestCase {
41    private RichInputMethodManager mRichImm;
42
43    RichInputMethodSubtype EN_US_QWERTY;
44    RichInputMethodSubtype EN_GB_QWERTY;
45    RichInputMethodSubtype FR_AZERTY;
46    RichInputMethodSubtype FR_CA_QWERTY;
47    RichInputMethodSubtype FR_CH_SWISS;
48    RichInputMethodSubtype FR_CH_QWERTY;
49    RichInputMethodSubtype FR_CH_QWERTZ;
50    RichInputMethodSubtype IW_HEBREW;
51    RichInputMethodSubtype ZZ_QWERTY;
52
53    @Override
54    protected void setUp() throws Exception {
55        super.setUp();
56        final Context context = getContext();
57        RichInputMethodManager.init(context);
58        mRichImm = RichInputMethodManager.getInstance();
59
60        EN_US_QWERTY = findSubtypeOf(Locale.US.toString(), "qwerty");
61        EN_GB_QWERTY = findSubtypeOf(Locale.UK.toString(), "qwerty");
62        FR_AZERTY = findSubtypeOf(Locale.FRENCH.toString(), "azerty");
63        FR_CA_QWERTY = findSubtypeOf(Locale.CANADA_FRENCH.toString(), "qwerty");
64        FR_CH_SWISS = findSubtypeOf("fr_CH", "swiss");
65        FR_CH_QWERTZ = new RichInputMethodSubtype(
66                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwertz"));
67        FR_CH_QWERTY = new RichInputMethodSubtype(
68                AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype("fr_CH", "qwerty"));
69        IW_HEBREW = findSubtypeOf("iw", "hebrew");
70        ZZ_QWERTY = findSubtypeOf(SubtypeLocaleUtils.NO_LANGUAGE, "qwerty");
71    }
72
73    @Nonnull
74    private RichInputMethodSubtype findSubtypeOf(final String localeString,
75            final String keyboardLayoutSetName) {
76        final InputMethodSubtype subtype = mRichImm.findSubtypeByLocaleAndKeyboardLayoutSet(
77                localeString, keyboardLayoutSetName);
78        if (subtype == null) {
79            throw new RuntimeException("Can't find subtype of " + localeString + " with "
80                    + keyboardLayoutSetName);
81        }
82        return new RichInputMethodSubtype(subtype);
83    }
84
85    private static void enableSubtypes(final RichInputMethodSubtype ... subtypes) {
86        final ArrayList<InputMethodSubtype> enabledSubtypes = new ArrayList<>();
87        for (final RichInputMethodSubtype subtype : subtypes) {
88            enabledSubtypes.add(subtype.getRawSubtype());
89        }
90        LanguageOnSpacebarUtils.setEnabledSubtypes(enabledSubtypes);
91    }
92
93    private static void assertFormatType(final RichInputMethodSubtype subtype,
94            final boolean implicitlyEnabledSubtype, final Locale systemLocale,
95            final int expectedFormat) {
96        LanguageOnSpacebarUtils.onSubtypeChanged(subtype, implicitlyEnabledSubtype, systemLocale);
97        assertEquals(subtype.getLocale() + " implicitly=" + implicitlyEnabledSubtype
98                + " in " + systemLocale, expectedFormat,
99                LanguageOnSpacebarUtils.getLanguageOnSpacebarFormatType(subtype));
100    }
101
102    public void testOneSubtypeImplicitlyEnabled() {
103        enableSubtypes(EN_US_QWERTY);
104        assertFormatType(EN_US_QWERTY, true, Locale.US,            FORMAT_TYPE_NONE);
105
106        enableSubtypes(EN_GB_QWERTY);
107        assertFormatType(EN_GB_QWERTY, true, Locale.UK,            FORMAT_TYPE_NONE);
108
109        enableSubtypes(FR_AZERTY);
110        assertFormatType(FR_AZERTY,    true, Locale.FRANCE,        FORMAT_TYPE_NONE);
111
112        enableSubtypes(FR_CA_QWERTY);
113        assertFormatType(FR_CA_QWERTY, true, Locale.CANADA_FRENCH, FORMAT_TYPE_NONE);
114    }
115
116    public void testOneSubtypeExplicitlyEnabled() {
117        enableSubtypes(EN_US_QWERTY);
118        assertFormatType(EN_US_QWERTY, false, Locale.UK,     FORMAT_TYPE_LANGUAGE_ONLY);
119        assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
120
121        enableSubtypes(EN_GB_QWERTY);
122        assertFormatType(EN_GB_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
123        assertFormatType(EN_GB_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
124
125        enableSubtypes(FR_AZERTY);
126        assertFormatType(FR_AZERTY,    false, Locale.US,            FORMAT_TYPE_LANGUAGE_ONLY);
127        assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
128
129        enableSubtypes(FR_CA_QWERTY);
130        assertFormatType(FR_CA_QWERTY, false, Locale.US,            FORMAT_TYPE_LANGUAGE_ONLY);
131        assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE,        FORMAT_TYPE_LANGUAGE_ONLY);
132    }
133
134    public void testOneSubtypeImplicitlyEnabledWithNoLanguageSubtype() {
135        final Locale Locale_IW = new Locale("iw");
136        enableSubtypes(IW_HEBREW, ZZ_QWERTY);
137        // TODO: Should this be FORMAT_TYPE_NONE?
138        assertFormatType(IW_HEBREW,    true, Locale_IW, FORMAT_TYPE_LANGUAGE_ONLY);
139        // TODO: Should this be FORMAT_TYPE_NONE?
140        assertFormatType(ZZ_QWERTY,    true, Locale_IW, FORMAT_TYPE_FULL_LOCALE);
141    }
142
143    public void testTwoSubtypesExplicitlyEnabled() {
144        enableSubtypes(EN_US_QWERTY, FR_AZERTY);
145        assertFormatType(EN_US_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
146        assertFormatType(FR_AZERTY,    false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
147        assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
148        assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
149        assertFormatType(EN_US_QWERTY, false, Locale.JAPAN,  FORMAT_TYPE_LANGUAGE_ONLY);
150        assertFormatType(FR_AZERTY,    false, Locale.JAPAN,  FORMAT_TYPE_LANGUAGE_ONLY);
151
152        enableSubtypes(EN_US_QWERTY, ZZ_QWERTY);
153        assertFormatType(EN_US_QWERTY, false, Locale.US,     FORMAT_TYPE_LANGUAGE_ONLY);
154        assertFormatType(ZZ_QWERTY,    false, Locale.US,     FORMAT_TYPE_FULL_LOCALE);
155        assertFormatType(EN_US_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
156        assertFormatType(ZZ_QWERTY,    false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
157
158    }
159
160    public void testMultiSubtypeWithSameLanuageAndSameLayout() {
161        // Explicitly enable en_US, en_GB, fr_FR, and no language keyboards.
162        enableSubtypes(EN_US_QWERTY, EN_GB_QWERTY, FR_CA_QWERTY, ZZ_QWERTY);
163
164        assertFormatType(EN_US_QWERTY, false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
165        assertFormatType(EN_GB_QWERTY, false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
166        assertFormatType(FR_CA_QWERTY, false, Locale.US,    FORMAT_TYPE_LANGUAGE_ONLY);
167        assertFormatType(ZZ_QWERTY,    false, Locale.US,    FORMAT_TYPE_FULL_LOCALE);
168
169        assertFormatType(EN_US_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
170        assertFormatType(EN_GB_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
171        assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
172        assertFormatType(ZZ_QWERTY,    false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
173    }
174
175    public void testMultiSubtypesWithSameLanguageButHaveDifferentLayout() {
176        enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTZ);
177
178        assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
179        assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
180        assertFormatType(FR_CH_SWISS,  false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
181        assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
182
183        assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
184        assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
185        assertFormatType(FR_CH_SWISS,  false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
186        assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
187
188        assertFormatType(FR_AZERTY,    false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
189        assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
190        assertFormatType(FR_CH_SWISS,  false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
191        assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
192    }
193
194    public void testMultiSubtypesWithSameLanguageAndMayHaveSameLayout() {
195        enableSubtypes(FR_AZERTY, FR_CA_QWERTY, FR_CH_SWISS, FR_CH_QWERTY, FR_CH_QWERTZ);
196
197        assertFormatType(FR_AZERTY,    false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
198        assertFormatType(FR_CA_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
199        assertFormatType(FR_CH_SWISS,  false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
200        assertFormatType(FR_CH_QWERTY, false, Locale.FRANCE, FORMAT_TYPE_FULL_LOCALE);
201        assertFormatType(FR_CH_QWERTZ, false, Locale.FRANCE, FORMAT_TYPE_LANGUAGE_ONLY);
202
203        assertFormatType(FR_AZERTY,    false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
204        assertFormatType(FR_CA_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE);
205        assertFormatType(FR_CH_SWISS,  false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
206        assertFormatType(FR_CH_QWERTY, false, Locale.CANADA_FRENCH, FORMAT_TYPE_FULL_LOCALE);
207        assertFormatType(FR_CH_QWERTZ, false, Locale.CANADA_FRENCH, FORMAT_TYPE_LANGUAGE_ONLY);
208
209        assertFormatType(FR_AZERTY,    false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
210        assertFormatType(FR_CA_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
211        assertFormatType(FR_CH_SWISS,  false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
212        assertFormatType(FR_CH_QWERTY, false, Locale.JAPAN, FORMAT_TYPE_FULL_LOCALE);
213        assertFormatType(FR_CH_QWERTZ, false, Locale.JAPAN, FORMAT_TYPE_LANGUAGE_ONLY);
214    }
215}
216