Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / input_method / input_method_util_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/input_method/input_method_util.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chromeos/ime/extension_ime_util.h"
13 #include "chromeos/ime/fake_input_method_delegate.h"
14 #include "chromeos/ime/input_method_manager.h"
15 #include "chromeos/ime/input_method_whitelist.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/base/l10n/l10n_util.h"
18
19 using base::ASCIIToUTF16;
20
21 namespace chromeos {
22
23 extern const char* kExtensionImePrefix;
24
25 namespace input_method {
26
27 namespace {
28
29 const char pinyin_ime_id[] = "zh-t-i0-pinyin";
30 const char zhuyin_ime_id[] = "zh-hant-t-i0-und";
31
32 class TestableInputMethodUtil : public InputMethodUtil {
33  public:
34   explicit TestableInputMethodUtil(InputMethodDelegate* delegate,
35                                    scoped_ptr<InputMethodDescriptors> methods)
36       : InputMethodUtil(delegate) {
37     ResetInputMethods(*methods);
38   }
39   // Change access rights.
40   using InputMethodUtil::GetInputMethodIdsFromLanguageCodeInternal;
41   using InputMethodUtil::GetKeyboardLayoutName;
42 };
43
44 }  // namespace
45
46 class InputMethodUtilTest : public testing::Test {
47  public:
48   InputMethodUtilTest()
49       : util_(&delegate_, whitelist_.GetSupportedInputMethods()) {
50     delegate_.set_get_localized_string_callback(
51         base::Bind(&l10n_util::GetStringUTF16));
52     delegate_.set_get_display_language_name_callback(
53         base::Bind(&InputMethodUtilTest::GetDisplayLanguageName));
54   }
55
56   virtual void SetUp() OVERRIDE {
57     InputMethodDescriptors input_methods;
58
59     std::vector<std::string> layouts;
60     std::vector<std::string> languages;
61     layouts.push_back("us");
62     languages.push_back("zh-CN");
63
64     InputMethodDescriptor pinyin_ime(Id(pinyin_ime_id),
65                                      "Pinyin input for testing",
66                                      "CN",
67                                      layouts,
68                                      languages,
69                                      false,
70                                      GURL(""),
71                                      GURL(""));
72     input_methods.push_back(pinyin_ime);
73
74     languages.clear();
75     languages.push_back("zh-TW");
76     InputMethodDescriptor zhuyin_ime(zhuyin_ime_id,
77                                      "Zhuyin input for testing",
78                                      "TW",
79                                      layouts,
80                                      languages,
81                                      false,
82                                      GURL(""),
83                                      GURL(""));
84     input_methods.push_back(zhuyin_ime);
85
86     util_.InitXkbInputMethodsForTesting();
87     util_.AppendInputMethods(input_methods);
88   }
89
90   std::string Id(const std::string& id) {
91     return extension_ime_util::GetInputMethodIDByEngineID(id);
92   }
93
94   InputMethodDescriptor GetDesc(const std::string& id,
95                                 const std::string& raw_layout,
96                                 const std::string& language_code,
97                                 const std::string& indicator) {
98     std::vector<std::string> layouts;
99     layouts.push_back(raw_layout);
100     std::vector<std::string> languages;
101     languages.push_back(language_code);
102     return InputMethodDescriptor(Id(id),
103                                  "",         // Description.
104                                  indicator,  // Short name used for indicator.
105                                  layouts,
106                                  languages,
107                                  true,
108                                  GURL(),   // options page url
109                                  GURL());  // input view page url
110   }
111
112   static base::string16 GetDisplayLanguageName(const std::string& language_code) {
113     return l10n_util::GetDisplayNameForLocale(language_code, "en", true);
114   }
115
116   FakeInputMethodDelegate delegate_;
117   InputMethodWhitelist whitelist_;
118   TestableInputMethodUtil util_;
119 };
120
121 TEST_F(InputMethodUtilTest, GetInputMethodShortNameTest) {
122   // Test invalid cases. Two-letter language code should be returned.
123   {
124     InputMethodDescriptor desc = GetDesc("invalid-id", "us", "xx", "");
125     // Upper-case string of the unknown language code, "xx", should be returned.
126     EXPECT_EQ(ASCIIToUTF16("XX"), util_.GetInputMethodShortName(desc));
127   }
128
129   // Test special cases.
130   {
131     InputMethodDescriptor desc =
132         GetDesc("xkb:us:dvorak:eng", "us", "en-US", "DV");
133     EXPECT_EQ(ASCIIToUTF16("DV"), util_.GetInputMethodShortName(desc));
134   }
135   {
136     InputMethodDescriptor desc =
137         GetDesc("xkb:us:colemak:eng", "us", "en-US", "CO");
138     EXPECT_EQ(ASCIIToUTF16("CO"), util_.GetInputMethodShortName(desc));
139   }
140   {
141     InputMethodDescriptor desc =
142         GetDesc("xkb:us:altgr-intl:eng", "us", "en-US", "EXTD");
143     EXPECT_EQ(ASCIIToUTF16("EXTD"), util_.GetInputMethodShortName(desc));
144   }
145   {
146     InputMethodDescriptor desc =
147         GetDesc("xkb:us:intl:eng", "us", "en-US", "INTL");
148     EXPECT_EQ(ASCIIToUTF16("INTL"), util_.GetInputMethodShortName(desc));
149   }
150   {
151     InputMethodDescriptor desc =
152         GetDesc("xkb:de:neo:ger", "de(neo)", "de", "NEO");
153     EXPECT_EQ(ASCIIToUTF16("NEO"), util_.GetInputMethodShortName(desc));
154   }
155   {
156     InputMethodDescriptor desc =
157         GetDesc("xkb:es:cat:cat", "es(cat)", "ca", "CAS");
158     EXPECT_EQ(ASCIIToUTF16("CAS"), util_.GetInputMethodShortName(desc));
159   }
160   {
161     InputMethodDescriptor desc =
162         GetDesc(pinyin_ime_id, "us", "zh-CN", "");
163     EXPECT_EQ(base::UTF8ToUTF16("\xe6\x8b\xbc"),
164               util_.GetInputMethodShortName(desc));
165   }
166   {
167     InputMethodDescriptor desc = GetDesc(zhuyin_ime_id, "us", "zh-TW", "");
168     EXPECT_EQ(base::UTF8ToUTF16("\xE6\xB3\xA8"),
169               util_.GetInputMethodShortName(desc));
170   }
171 }
172
173 TEST_F(InputMethodUtilTest, GetInputMethodMediumNameTest) {
174   {
175     // input methods with medium name equal to short name
176     const char * input_method_id[] = {
177       "xkb:us:altgr-intl:eng",
178       "xkb:us:dvorak:eng",
179       "xkb:us:intl:eng",
180       "xkb:us:colemak:eng",
181       "xkb:de:neo:ger",
182       "xkb:es:cat:cat",
183       "xkb:gb:dvorak:eng",
184     };
185     const int len = ARRAYSIZE_UNSAFE(input_method_id);
186     for (int i=0; i<len; ++i) {
187       InputMethodDescriptor desc = GetDesc(input_method_id[i], "", "", "");
188       base::string16 medium_name = util_.GetInputMethodMediumName(desc);
189       base::string16 short_name = util_.GetInputMethodShortName(desc);
190       EXPECT_EQ(medium_name,short_name);
191     }
192   }
193   {
194     // input methods with medium name not equal to short name
195     const char * input_method_id[] = {
196       pinyin_ime_id,
197       zhuyin_ime_id,
198     };
199     const int len = ARRAYSIZE_UNSAFE(input_method_id);
200     for (int i=0; i<len; ++i) {
201       InputMethodDescriptor desc = GetDesc(input_method_id[i], "", "", "");
202       base::string16 medium_name = util_.GetInputMethodMediumName(desc);
203       base::string16 short_name = util_.GetInputMethodShortName(desc);
204       EXPECT_NE(medium_name,short_name);
205     }
206   }
207 }
208
209 TEST_F(InputMethodUtilTest, GetInputMethodLongNameTest) {
210   // For most languages input method or keyboard layout name is returned.
211   // See below for exceptions.
212   {
213     InputMethodDescriptor desc = GetDesc("xkb:jp::jpn", "jp", "ja", "");
214     EXPECT_EQ(ASCIIToUTF16("Japanese"),
215               util_.GetInputMethodLongName(desc));
216   }
217   {
218     InputMethodDescriptor desc =
219         GetDesc("xkb:us:dvorak:eng", "us(dvorak)", "en-US", "");
220     EXPECT_EQ(ASCIIToUTF16("US Dvorak"),
221               util_.GetInputMethodLongName(desc));
222   }
223   {
224     InputMethodDescriptor desc =
225         GetDesc("xkb:gb:dvorak:eng", "gb(dvorak)", "en-US", "");
226     EXPECT_EQ(ASCIIToUTF16("UK Dvorak"),
227               util_.GetInputMethodLongName(desc));
228   }
229
230   // For Dutch, French, German and Hindi,
231   // "language - keyboard layout" pair is returned.
232   {
233     InputMethodDescriptor desc = GetDesc("xkb:be::nld", "be", "nl", "");
234     EXPECT_EQ(ASCIIToUTF16("Dutch - Belgian"),
235               util_.GetInputMethodLongName(desc));
236   }
237   {
238     InputMethodDescriptor desc = GetDesc("xkb:fr::fra", "fr", "fr", "");
239     EXPECT_EQ(ASCIIToUTF16("French - French"),
240               util_.GetInputMethodLongName(desc));
241   }
242   {
243     InputMethodDescriptor desc = GetDesc("xkb:be::fra", "be", "fr", "");
244     EXPECT_EQ(ASCIIToUTF16("French - Belgian"),
245               util_.GetInputMethodLongName(desc));
246   }
247   {
248     InputMethodDescriptor desc = GetDesc("xkb:de::ger", "de", "de", "");
249     EXPECT_EQ(ASCIIToUTF16("German - German"),
250               util_.GetInputMethodLongName(desc));
251   }
252   {
253     InputMethodDescriptor desc = GetDesc("xkb:be::ger", "be", "de", "");
254     EXPECT_EQ(ASCIIToUTF16("German - Belgian"),
255               util_.GetInputMethodLongName(desc));
256   }
257
258   {
259     InputMethodDescriptor desc = GetDesc("invalid-id", "us", "xx", "");
260     // You can safely ignore the "Resouce ID is not found for: invalid-id"
261     // error.
262     EXPECT_EQ(ASCIIToUTF16("invalid-id"),
263               util_.GetInputMethodLongName(desc));
264   }
265 }
266
267 TEST_F(InputMethodUtilTest, TestIsValidInputMethodId) {
268   EXPECT_TRUE(util_.IsValidInputMethodId(Id("xkb:us:colemak:eng")));
269   EXPECT_TRUE(util_.IsValidInputMethodId(Id(pinyin_ime_id)));
270   EXPECT_FALSE(util_.IsValidInputMethodId("unsupported-input-method"));
271 }
272
273 TEST_F(InputMethodUtilTest, TestIsKeyboardLayout) {
274   EXPECT_TRUE(InputMethodUtil::IsKeyboardLayout("xkb:us::eng"));
275   EXPECT_FALSE(InputMethodUtil::IsKeyboardLayout(Id(pinyin_ime_id)));
276 }
277
278 TEST_F(InputMethodUtilTest, TestGetKeyboardLayoutName) {
279   // Unsupported case.
280   EXPECT_EQ("", util_.GetKeyboardLayoutName("UNSUPPORTED_ID"));
281
282   // Supported cases (samples).
283   EXPECT_EQ("us", util_.GetKeyboardLayoutName(Id(pinyin_ime_id)));
284   EXPECT_EQ("es", util_.GetKeyboardLayoutName(Id("xkb:es::spa")));
285   EXPECT_EQ("es(cat)", util_.GetKeyboardLayoutName(Id("xkb:es:cat:cat")));
286   EXPECT_EQ("gb(extd)", util_.GetKeyboardLayoutName(Id("xkb:gb:extd:eng")));
287   EXPECT_EQ("us", util_.GetKeyboardLayoutName(Id("xkb:us::eng")));
288   EXPECT_EQ("us(dvorak)", util_.GetKeyboardLayoutName(Id("xkb:us:dvorak:eng")));
289   EXPECT_EQ("us(colemak)",
290             util_.GetKeyboardLayoutName(Id("xkb:us:colemak:eng")));
291   EXPECT_EQ("de(neo)", util_.GetKeyboardLayoutName(Id("xkb:de:neo:ger")));
292 }
293
294 TEST_F(InputMethodUtilTest, TestGetInputMethodDisplayNameFromId) {
295   EXPECT_EQ("US",
296             util_.GetInputMethodDisplayNameFromId("xkb:us::eng"));
297   EXPECT_EQ("", util_.GetInputMethodDisplayNameFromId("nonexistent"));
298 }
299
300 TEST_F(InputMethodUtilTest, TestGetInputMethodDescriptorFromId) {
301   EXPECT_EQ(NULL, util_.GetInputMethodDescriptorFromId("non_existent"));
302
303   const InputMethodDescriptor* descriptor =
304       util_.GetInputMethodDescriptorFromId(Id(pinyin_ime_id));
305   ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
306   EXPECT_EQ(Id(pinyin_ime_id), descriptor->id());
307   EXPECT_EQ("us", descriptor->GetPreferredKeyboardLayout());
308   // This used to be "zh" but now we have "zh-CN" in input_methods.h,
309   // hence this should be zh-CN now.
310   ASSERT_TRUE(!descriptor->language_codes().empty());
311   EXPECT_EQ("zh-CN", descriptor->language_codes().at(0));
312 }
313
314 TEST_F(InputMethodUtilTest, TestGetInputMethodIdsForLanguageCode) {
315   std::multimap<std::string, std::string> language_code_to_ids_map;
316   language_code_to_ids_map.insert(std::make_pair("ja", pinyin_ime_id));
317   language_code_to_ids_map.insert(std::make_pair("ja", pinyin_ime_id));
318   language_code_to_ids_map.insert(std::make_pair("ja", "xkb:jp:jpn"));
319   language_code_to_ids_map.insert(std::make_pair("fr", "xkb:fr:fra"));
320
321   std::vector<std::string> result;
322   EXPECT_TRUE(util_.GetInputMethodIdsFromLanguageCodeInternal(
323       language_code_to_ids_map, "ja", kAllInputMethods, &result));
324   EXPECT_EQ(3U, result.size());
325   EXPECT_TRUE(util_.GetInputMethodIdsFromLanguageCodeInternal(
326       language_code_to_ids_map, "ja", kKeyboardLayoutsOnly, &result));
327   ASSERT_EQ(1U, result.size());
328   EXPECT_EQ("xkb:jp:jpn", result[0]);
329
330   EXPECT_TRUE(util_.GetInputMethodIdsFromLanguageCodeInternal(
331       language_code_to_ids_map, "fr", kAllInputMethods, &result));
332   ASSERT_EQ(1U, result.size());
333   EXPECT_EQ("xkb:fr:fra", result[0]);
334   EXPECT_TRUE(util_.GetInputMethodIdsFromLanguageCodeInternal(
335       language_code_to_ids_map, "fr", kKeyboardLayoutsOnly, &result));
336   ASSERT_EQ(1U, result.size());
337   EXPECT_EQ("xkb:fr:fra", result[0]);
338
339   EXPECT_FALSE(util_.GetInputMethodIdsFromLanguageCodeInternal(
340       language_code_to_ids_map, "invalid_lang", kAllInputMethods, &result));
341   EXPECT_FALSE(util_.GetInputMethodIdsFromLanguageCodeInternal(
342       language_code_to_ids_map, "invalid_lang", kKeyboardLayoutsOnly, &result));
343 }
344
345 // US keyboard + English US UI = US keyboard only.
346 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_EnUs) {
347   const InputMethodDescriptor* descriptor =
348       util_.GetInputMethodDescriptorFromId(Id("xkb:us::eng"));  // US keyboard.
349   ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
350   std::vector<std::string> input_method_ids;
351   util_.GetFirstLoginInputMethodIds("en-US", *descriptor, &input_method_ids);
352   ASSERT_EQ(1U, input_method_ids.size());
353   EXPECT_EQ(Id("xkb:us::eng"), input_method_ids[0]);
354 }
355
356 // US keyboard + Chinese UI = US keyboard + Pinyin IME.
357 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Zh) {
358   const InputMethodDescriptor* descriptor =
359       util_.GetInputMethodDescriptorFromId(Id("xkb:us::eng"));  // US keyboard.
360   ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
361   std::vector<std::string> input_method_ids;
362   util_.GetFirstLoginInputMethodIds("zh-CN", *descriptor, &input_method_ids);
363   ASSERT_EQ(2U, input_method_ids.size());
364   EXPECT_EQ(Id("xkb:us::eng"), input_method_ids[0]);
365   EXPECT_EQ(Id(pinyin_ime_id), input_method_ids[1]);  // Pinyin for US keybaord.
366 }
367
368 // US keyboard + Russian UI = US keyboard + Russsian keyboard
369 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Ru) {
370   const InputMethodDescriptor* descriptor =
371       util_.GetInputMethodDescriptorFromId(Id("xkb:us::eng"));  // US keyboard.
372   ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
373   std::vector<std::string> input_method_ids;
374   util_.GetFirstLoginInputMethodIds("ru", *descriptor, &input_method_ids);
375   ASSERT_EQ(2U, input_method_ids.size());
376   EXPECT_EQ(Id("xkb:us::eng"), input_method_ids[0]);
377   EXPECT_EQ(Id("xkb:ru::rus"), input_method_ids[1]);  // Russian keyboard.
378 }
379
380 // US keyboard + Traditional Chinese = US keyboard + chewing.
381 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_ZhTw) {
382   const InputMethodDescriptor* descriptor =
383       util_.GetInputMethodDescriptorFromId(Id("xkb:us::eng"));  // US keyboard.
384   ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
385   std::vector<std::string> input_method_ids;
386   util_.GetFirstLoginInputMethodIds("zh-TW", *descriptor, &input_method_ids);
387   ASSERT_EQ(2U, input_method_ids.size());
388   EXPECT_EQ(Id("xkb:us::eng"), input_method_ids[0]);
389   EXPECT_EQ(Id(zhuyin_ime_id), input_method_ids[1]);  // Chewing.
390 }
391
392 // US keyboard + Thai = US keyboard + kesmanee.
393 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Th) {
394   const InputMethodDescriptor* descriptor =
395       util_.GetInputMethodDescriptorFromId(Id("xkb:us::eng"));  // US keyboard.
396   ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
397   std::vector<std::string> input_method_ids;
398   util_.GetFirstLoginInputMethodIds("th", *descriptor, &input_method_ids);
399   ASSERT_EQ(2U, input_method_ids.size());
400   EXPECT_EQ(Id("xkb:us::eng"), input_method_ids[0]);
401   EXPECT_EQ(Id("vkd_th"), input_method_ids[1]);  // Kesmanee.
402 }
403
404 // US keyboard + Vietnamese = US keyboard + TCVN6064.
405 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Vi) {
406   const InputMethodDescriptor* descriptor =
407       util_.GetInputMethodDescriptorFromId(Id("xkb:us::eng"));  // US keyboard.
408   ASSERT_TRUE(NULL != descriptor);  // ASSERT_NE doesn't compile.
409   std::vector<std::string> input_method_ids;
410   util_.GetFirstLoginInputMethodIds("vi", *descriptor, &input_method_ids);
411   ASSERT_EQ(2U, input_method_ids.size());
412   EXPECT_EQ(Id("xkb:us::eng"), input_method_ids[0]);
413   EXPECT_EQ(Id("vkd_vi_tcvn"), input_method_ids[1]);  // TCVN6064.
414 }
415
416 TEST_F(InputMethodUtilTest, TestGetLanguageCodesFromInputMethodIds) {
417   std::vector<std::string> input_method_ids;
418   input_method_ids.push_back(Id("xkb:us::eng"));        // English US.
419   input_method_ids.push_back(Id("xkb:us:dvorak:eng"));  // English US Dvorak.
420   input_method_ids.push_back(Id(pinyin_ime_id));        // Pinyin
421   input_method_ids.push_back(Id("xkb:fr::fra"));        // French France.
422   std::vector<std::string> language_codes;
423   util_.GetLanguageCodesFromInputMethodIds(input_method_ids, &language_codes);
424   ASSERT_EQ(3U, language_codes.size());
425   EXPECT_EQ("en", language_codes[0]);
426   EXPECT_EQ("zh-CN", language_codes[1]);
427   EXPECT_EQ("fr", language_codes[2]);
428 }
429
430 // Test all supported descriptors to detect a typo in input_methods.txt.
431 TEST_F(InputMethodUtilTest, TestIBusInputMethodText) {
432   const std::map<std::string, InputMethodDescriptor>& id_to_descriptor =
433       util_.GetIdToDesciptorMapForTesting();
434   for (std::map<std::string, InputMethodDescriptor>::const_iterator it =
435        id_to_descriptor.begin(); it != id_to_descriptor.end(); ++it) {
436     const std::string language_code = it->second.language_codes().at(0);
437     const base::string16 display_name =
438         l10n_util::GetDisplayNameForLocale(language_code, "en", false);
439     // Only two formats, like "fr" (lower case) and "en-US" (lower-upper), are
440     // allowed. See the text file for details.
441     EXPECT_TRUE(language_code == "fil" || language_code.length() == 2 ||
442                 (language_code.length() == 5 && language_code[2] == '-'))
443         << "Invalid language code " << language_code;
444     EXPECT_TRUE(l10n_util::IsValidLocaleSyntax(language_code))
445         << "Invalid language code " << language_code;
446     EXPECT_FALSE(display_name.empty())
447         << "Invalid language code " << language_code;
448     // On error, GetDisplayNameForLocale() returns the |language_code| as-is.
449     EXPECT_NE(language_code, base::UTF16ToUTF8(display_name))
450         << "Invalid language code " << language_code;
451   }
452 }
453
454 }  // namespace input_method
455 }  // namespace chromeos