Fix infinite recursion on hiding panel when created during fullscreen mode.
[chromium-blink-merge.git] / chrome / browser / chromeos / input_method / input_method_util_unittest.cc
blobee88da97517d798e56648adb965b6e81fd05a662
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.
5 #include "chrome/browser/chromeos/input_method/input_method_util.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chromeos/ime/fake_input_method_delegate.h"
13 #include "chromeos/ime/input_method_manager.h"
14 #include "chromeos/ime/input_method_whitelist.h"
15 #include "grit/generated_resources.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/base/l10n/l10n_util.h"
19 using base::ASCIIToUTF16;
21 namespace chromeos {
23 extern const char* kExtensionImePrefix;
25 namespace input_method {
27 namespace {
29 const char pinyin_ime_id[] =
30 "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin";
31 const char zhuyin_ime_id[] =
32 "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und";
33 const char kKeyboardExtId[] =
34 #if defined(OFFICIAL_BUILD)
35 "habcdindjejkmepknlhkkloncjcpcnbf";
36 #else
37 "jhffeifommiaekmbkkjlpmilogcfdohp";
38 #endif
40 class TestableInputMethodUtil : public InputMethodUtil {
41 public:
42 explicit TestableInputMethodUtil(InputMethodDelegate* delegate,
43 scoped_ptr<InputMethodDescriptors> methods)
44 : InputMethodUtil(delegate, methods.Pass()) {
46 // Change access rights.
47 using InputMethodUtil::GetInputMethodIdsFromLanguageCodeInternal;
48 using InputMethodUtil::GetKeyboardLayoutName;
49 using InputMethodUtil::ReloadInternalMaps;
50 using InputMethodUtil::supported_input_methods_;
53 } // namespace
55 class InputMethodUtilTest : public testing::Test {
56 public:
57 InputMethodUtilTest()
58 : util_(&delegate_, whitelist_.GetSupportedInputMethods()) {
59 delegate_.set_get_localized_string_callback(
60 base::Bind(&l10n_util::GetStringUTF16));
61 delegate_.set_get_display_language_name_callback(
62 base::Bind(&InputMethodUtilTest::GetDisplayLanguageName));
65 virtual void SetUp() OVERRIDE {
66 InputMethodDescriptors input_methods;
68 std::vector<std::string> layouts;
69 std::vector<std::string> languages;
70 layouts.push_back("us");
71 languages.push_back("zh-CN");
73 InputMethodDescriptor pinyin_ime(pinyin_ime_id,
74 "Pinyin input for testing",
75 "CN",
76 layouts,
77 languages,
78 false,
79 GURL(""),
80 GURL(""));
81 input_methods.push_back(pinyin_ime);
83 languages.clear();
84 languages.push_back("zh-TW");
85 InputMethodDescriptor zhuyin_ime(zhuyin_ime_id,
86 "Zhuyin input for testing",
87 "TW",
88 layouts,
89 languages,
90 false,
91 GURL(""),
92 GURL(""));
93 input_methods.push_back(zhuyin_ime);
95 util_.SetComponentExtensions(input_methods);
98 InputMethodDescriptor GetDesc(const std::string& id,
99 const std::string& raw_layout,
100 const std::string& language_code,
101 const std::string& indicator) {
102 std::vector<std::string> layouts;
103 layouts.push_back(raw_layout);
104 std::vector<std::string> languages;
105 languages.push_back(language_code);
106 return InputMethodDescriptor(id,
107 "", // Description.
108 indicator, // Short name used for indicator.
109 layouts,
110 languages,
111 true,
112 GURL(), // options page url
113 GURL()); // input view page url
116 static base::string16 GetDisplayLanguageName(const std::string& language_code) {
117 return l10n_util::GetDisplayNameForLocale(language_code, "en", true);
120 FakeInputMethodDelegate delegate_;
121 InputMethodWhitelist whitelist_;
122 TestableInputMethodUtil util_;
125 TEST_F(InputMethodUtilTest, GetInputMethodShortNameTest) {
126 // Test normal cases. Two-letter language code should be returned.
128 InputMethodDescriptor desc = GetDesc("m17n:fa:isiri", // input method id
129 "us", // keyboard layout name
130 "fa", // language name
131 ""); // indicator
132 EXPECT_EQ(ASCIIToUTF16("FA"), util_.GetInputMethodShortName(desc));
135 InputMethodDescriptor desc = GetDesc("mozc-hangul", "us", "ko", "");
136 EXPECT_EQ(base::UTF8ToUTF16("\xed\x95\x9c"),
137 util_.GetInputMethodShortName(desc));
140 InputMethodDescriptor desc = GetDesc("invalid-id", "us", "xx", "");
141 // Upper-case string of the unknown language code, "xx", should be returned.
142 EXPECT_EQ(ASCIIToUTF16("XX"), util_.GetInputMethodShortName(desc));
145 // Test special cases.
147 InputMethodDescriptor desc =
148 GetDesc("xkb:us:dvorak:eng", "us", "en-US", "DV");
149 EXPECT_EQ(ASCIIToUTF16("DV"), util_.GetInputMethodShortName(desc));
152 InputMethodDescriptor desc =
153 GetDesc("xkb:us:colemak:eng", "us", "en-US", "CO");
154 EXPECT_EQ(ASCIIToUTF16("CO"), util_.GetInputMethodShortName(desc));
157 InputMethodDescriptor desc =
158 GetDesc("xkb:us:altgr-intl:eng", "us", "en-US", "EXTD");
159 EXPECT_EQ(ASCIIToUTF16("EXTD"), util_.GetInputMethodShortName(desc));
162 InputMethodDescriptor desc =
163 GetDesc("xkb:us:intl:eng", "us", "en-US", "INTL");
164 EXPECT_EQ(ASCIIToUTF16("INTL"), util_.GetInputMethodShortName(desc));
167 InputMethodDescriptor desc =
168 GetDesc("xkb:de:neo:ger", "de(neo)", "de", "NEO");
169 EXPECT_EQ(ASCIIToUTF16("NEO"), util_.GetInputMethodShortName(desc));
172 InputMethodDescriptor desc =
173 GetDesc("xkb:es:cat:cat", "es(cat)", "ca", "CAS");
174 EXPECT_EQ(ASCIIToUTF16("CAS"), util_.GetInputMethodShortName(desc));
177 InputMethodDescriptor desc =
178 GetDesc(pinyin_ime_id, "us", "zh-CN", "");
179 EXPECT_EQ(base::UTF8ToUTF16("\xe6\x8b\xbc"),
180 util_.GetInputMethodShortName(desc));
183 InputMethodDescriptor desc =
184 GetDesc(zhuyin_ime_id, "us", "zh-TW", "");
185 EXPECT_EQ(base::UTF8ToUTF16("\xE6\xB3\xA8"),
186 util_.GetInputMethodShortName(desc));
190 TEST_F(InputMethodUtilTest, GetInputMethodMediumNameTest) {
192 // input methods with medium name equal to short name
193 const char * input_method_id[] = {
194 "xkb:us:altgr-intl:eng",
195 "xkb:us:dvorak:eng",
196 "xkb:us:intl:eng",
197 "xkb:us:colemak:eng",
198 "xkb:de:neo:ger",
199 "xkb:es:cat:cat",
200 "xkb:gb:dvorak:eng",
202 const int len = ARRAYSIZE_UNSAFE(input_method_id);
203 for (int i=0; i<len; ++i) {
204 InputMethodDescriptor desc = GetDesc(input_method_id[i], "", "", "");
205 base::string16 medium_name = util_.GetInputMethodMediumName(desc);
206 base::string16 short_name = util_.GetInputMethodShortName(desc);
207 EXPECT_EQ(medium_name,short_name);
211 // input methods with medium name not equal to short name
212 const char * input_method_id[] = {
213 "m17n:zh:cangjie",
214 "m17n:zh:quick",
215 pinyin_ime_id,
216 zhuyin_ime_id,
217 "mozc-hangul",
218 pinyin_ime_id,
219 pinyin_ime_id,
221 const int len = ARRAYSIZE_UNSAFE(input_method_id);
222 for (int i=0; i<len; ++i) {
223 InputMethodDescriptor desc = GetDesc(input_method_id[i], "", "", "");
224 base::string16 medium_name = util_.GetInputMethodMediumName(desc);
225 base::string16 short_name = util_.GetInputMethodShortName(desc);
226 EXPECT_NE(medium_name,short_name);
231 TEST_F(InputMethodUtilTest, GetInputMethodLongNameTest) {
232 // For most languages input method or keyboard layout name is returned.
233 // See below for exceptions.
235 InputMethodDescriptor desc = GetDesc("m17n:fa:isiri", "us", "fa", "");
236 EXPECT_EQ(ASCIIToUTF16("Persian input method (ISIRI 2901 layout)"),
237 util_.GetInputMethodLongName(desc));
240 InputMethodDescriptor desc = GetDesc("mozc-hangul", "us", "ko", "");
241 EXPECT_EQ(ASCIIToUTF16("Korean input method"),
242 util_.GetInputMethodLongName(desc));
245 InputMethodDescriptor desc = GetDesc("m17n:vi:tcvn", "us", "vi", "");
246 EXPECT_EQ(ASCIIToUTF16("Vietnamese input method (TCVN6064)"),
247 util_.GetInputMethodLongName(desc));
250 InputMethodDescriptor desc = GetDesc("xkb:jp::jpn", "jp", "ja", "");
251 EXPECT_EQ(ASCIIToUTF16("Japanese"),
252 util_.GetInputMethodLongName(desc));
255 InputMethodDescriptor desc =
256 GetDesc("xkb:us:dvorak:eng", "us(dvorak)", "en-US", "");
257 EXPECT_EQ(ASCIIToUTF16("US Dvorak"),
258 util_.GetInputMethodLongName(desc));
261 InputMethodDescriptor desc =
262 GetDesc("xkb:gb:dvorak:eng", "gb(dvorak)", "en-US", "");
263 EXPECT_EQ(ASCIIToUTF16("UK Dvorak"),
264 util_.GetInputMethodLongName(desc));
267 // For Arabic, Dutch, French, German and Hindi,
268 // "language - keyboard layout" pair is returned.
270 InputMethodDescriptor desc = GetDesc("m17n:ar:kbd", "us", "ar", "");
271 EXPECT_EQ(ASCIIToUTF16("Arabic - Standard input method"),
272 util_.GetInputMethodLongName(desc));
275 InputMethodDescriptor desc = GetDesc("xkb:be::nld", "be", "nl", "");
276 EXPECT_EQ(ASCIIToUTF16("Dutch - Belgian"),
277 util_.GetInputMethodLongName(desc));
280 InputMethodDescriptor desc = GetDesc("xkb:fr::fra", "fr", "fr", "");
281 EXPECT_EQ(ASCIIToUTF16("French - French"),
282 util_.GetInputMethodLongName(desc));
285 InputMethodDescriptor desc = GetDesc("xkb:be::fra", "be", "fr", "");
286 EXPECT_EQ(ASCIIToUTF16("French - Belgian"),
287 util_.GetInputMethodLongName(desc));
290 InputMethodDescriptor desc = GetDesc("xkb:de::ger", "de", "de", "");
291 EXPECT_EQ(ASCIIToUTF16("German - German"),
292 util_.GetInputMethodLongName(desc));
295 InputMethodDescriptor desc = GetDesc("xkb:be::ger", "be", "de", "");
296 EXPECT_EQ(ASCIIToUTF16("German - Belgian"),
297 util_.GetInputMethodLongName(desc));
300 InputMethodDescriptor desc = GetDesc("m17n:hi:itrans", "us", "hi", "");
301 EXPECT_EQ(ASCIIToUTF16("Hindi - Standard input method"),
302 util_.GetInputMethodLongName(desc));
306 InputMethodDescriptor desc = GetDesc("invalid-id", "us", "xx", "");
307 // You can safely ignore the "Resouce ID is not found for: invalid-id"
308 // error.
309 EXPECT_EQ(ASCIIToUTF16("invalid-id"),
310 util_.GetInputMethodLongName(desc));
314 TEST_F(InputMethodUtilTest, TestIsValidInputMethodId) {
315 EXPECT_TRUE(util_.IsValidInputMethodId("xkb:us:colemak:eng"));
316 EXPECT_TRUE(util_.IsValidInputMethodId(pinyin_ime_id));
317 EXPECT_FALSE(util_.IsValidInputMethodId("unsupported-input-method"));
320 TEST_F(InputMethodUtilTest, TestIsKeyboardLayout) {
321 EXPECT_TRUE(InputMethodUtil::IsKeyboardLayout("xkb:us::eng"));
322 EXPECT_FALSE(InputMethodUtil::IsKeyboardLayout(pinyin_ime_id));
325 TEST_F(InputMethodUtilTest, TestGetKeyboardLayoutName) {
326 // Unsupported case.
327 EXPECT_EQ("", util_.GetKeyboardLayoutName("UNSUPPORTED_ID"));
329 // Supported cases (samples).
330 EXPECT_EQ("us", util_.GetKeyboardLayoutName(pinyin_ime_id));
331 EXPECT_EQ("es", util_.GetKeyboardLayoutName("xkb:es::spa"));
332 EXPECT_EQ("es(cat)", util_.GetKeyboardLayoutName("xkb:es:cat:cat"));
333 EXPECT_EQ("gb(extd)", util_.GetKeyboardLayoutName("xkb:gb:extd:eng"));
334 EXPECT_EQ("us", util_.GetKeyboardLayoutName("xkb:us::eng"));
335 EXPECT_EQ("us(dvorak)", util_.GetKeyboardLayoutName("xkb:us:dvorak:eng"));
336 EXPECT_EQ("us(colemak)", util_.GetKeyboardLayoutName("xkb:us:colemak:eng"));
337 EXPECT_EQ("de(neo)", util_.GetKeyboardLayoutName("xkb:de:neo:ger"));
340 TEST_F(InputMethodUtilTest, TestGetLanguageCodeFromInputMethodId) {
341 // Make sure that the -CN is added properly.
342 EXPECT_EQ("zh-CN", util_.GetLanguageCodeFromInputMethodId(pinyin_ime_id));
345 TEST_F(InputMethodUtilTest, TestGetInputMethodDisplayNameFromId) {
346 EXPECT_EQ("US",
347 util_.GetInputMethodDisplayNameFromId("xkb:us::eng"));
348 EXPECT_EQ("", util_.GetInputMethodDisplayNameFromId("nonexistent"));
351 TEST_F(InputMethodUtilTest, TestGetInputMethodDescriptorFromId) {
352 EXPECT_EQ(NULL, util_.GetInputMethodDescriptorFromId("non_existent"));
354 const InputMethodDescriptor* descriptor =
355 util_.GetInputMethodDescriptorFromId(pinyin_ime_id);
356 ASSERT_TRUE(NULL != descriptor); // ASSERT_NE doesn't compile.
357 EXPECT_EQ(pinyin_ime_id, descriptor->id());
358 EXPECT_EQ("us", descriptor->GetPreferredKeyboardLayout());
359 // This used to be "zh" but now we have "zh-CN" in input_methods.h,
360 // hence this should be zh-CN now.
361 ASSERT_TRUE(!descriptor->language_codes().empty());
362 EXPECT_EQ("zh-CN", descriptor->language_codes().at(0));
365 TEST_F(InputMethodUtilTest, TestGetInputMethodIdsForLanguageCode) {
366 std::multimap<std::string, std::string> language_code_to_ids_map;
367 language_code_to_ids_map.insert(std::make_pair("ja", pinyin_ime_id));
368 language_code_to_ids_map.insert(std::make_pair("ja", pinyin_ime_id));
369 language_code_to_ids_map.insert(std::make_pair("ja", "xkb:jp:jpn"));
370 language_code_to_ids_map.insert(std::make_pair("fr", "xkb:fr:fra"));
372 std::vector<std::string> result;
373 EXPECT_TRUE(util_.GetInputMethodIdsFromLanguageCodeInternal(
374 language_code_to_ids_map, "ja", kAllInputMethods, &result));
375 EXPECT_EQ(3U, result.size());
376 EXPECT_TRUE(util_.GetInputMethodIdsFromLanguageCodeInternal(
377 language_code_to_ids_map, "ja", kKeyboardLayoutsOnly, &result));
378 ASSERT_EQ(1U, result.size());
379 EXPECT_EQ("xkb:jp:jpn", result[0]);
381 EXPECT_TRUE(util_.GetInputMethodIdsFromLanguageCodeInternal(
382 language_code_to_ids_map, "fr", kAllInputMethods, &result));
383 ASSERT_EQ(1U, result.size());
384 EXPECT_EQ("xkb:fr:fra", result[0]);
385 EXPECT_TRUE(util_.GetInputMethodIdsFromLanguageCodeInternal(
386 language_code_to_ids_map, "fr", kKeyboardLayoutsOnly, &result));
387 ASSERT_EQ(1U, result.size());
388 EXPECT_EQ("xkb:fr:fra", result[0]);
390 EXPECT_FALSE(util_.GetInputMethodIdsFromLanguageCodeInternal(
391 language_code_to_ids_map, "invalid_lang", kAllInputMethods, &result));
392 EXPECT_FALSE(util_.GetInputMethodIdsFromLanguageCodeInternal(
393 language_code_to_ids_map, "invalid_lang", kKeyboardLayoutsOnly, &result));
396 // US keyboard + English US UI = US keyboard only.
397 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_EnUs) {
398 const InputMethodDescriptor* descriptor =
399 util_.GetInputMethodDescriptorFromId("xkb:us::eng"); // US keyboard.
400 ASSERT_TRUE(NULL != descriptor); // ASSERT_NE doesn't compile.
401 std::vector<std::string> input_method_ids;
402 util_.GetFirstLoginInputMethodIds("en-US", *descriptor, &input_method_ids);
403 ASSERT_EQ(1U, input_method_ids.size());
404 EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
407 // US keyboard + Chinese UI = US keyboard + Pinyin IME.
408 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Zh) {
409 const InputMethodDescriptor* descriptor =
410 util_.GetInputMethodDescriptorFromId("xkb:us::eng"); // US keyboard.
411 ASSERT_TRUE(NULL != descriptor); // ASSERT_NE doesn't compile.
412 std::vector<std::string> input_method_ids;
413 util_.GetFirstLoginInputMethodIds("zh-CN", *descriptor, &input_method_ids);
414 ASSERT_EQ(2U, input_method_ids.size());
415 EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
416 EXPECT_EQ(pinyin_ime_id, input_method_ids[1]); // Pinyin for US keybaord.
419 // US keyboard + Russian UI = US keyboard + Russsian keyboard
420 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Ru) {
421 const InputMethodDescriptor* descriptor =
422 util_.GetInputMethodDescriptorFromId("xkb:us::eng"); // US keyboard.
423 ASSERT_TRUE(NULL != descriptor); // ASSERT_NE doesn't compile.
424 std::vector<std::string> input_method_ids;
425 util_.GetFirstLoginInputMethodIds("ru", *descriptor, &input_method_ids);
426 ASSERT_EQ(2U, input_method_ids.size());
427 EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
428 EXPECT_EQ("xkb:ru::rus", input_method_ids[1]); // Russian keyboard.
431 // US keyboard + Traditional Chinese = US keyboard + chewing.
432 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_ZhTw) {
433 const InputMethodDescriptor* descriptor =
434 util_.GetInputMethodDescriptorFromId("xkb:us::eng"); // US keyboard.
435 ASSERT_TRUE(NULL != descriptor); // ASSERT_NE doesn't compile.
436 std::vector<std::string> input_method_ids;
437 util_.GetFirstLoginInputMethodIds("zh-TW", *descriptor, &input_method_ids);
438 ASSERT_EQ(2U, input_method_ids.size());
439 EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
440 EXPECT_EQ(zhuyin_ime_id, input_method_ids[1]); // Chewing.
443 // US keyboard + Thai = US keyboard + kesmanee.
444 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Th) {
445 const InputMethodDescriptor* descriptor =
446 util_.GetInputMethodDescriptorFromId("xkb:us::eng"); // US keyboard.
447 ASSERT_TRUE(NULL != descriptor); // ASSERT_NE doesn't compile.
448 std::vector<std::string> input_method_ids;
449 util_.GetFirstLoginInputMethodIds("th", *descriptor, &input_method_ids);
450 ASSERT_EQ(2U, input_method_ids.size());
451 EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
452 EXPECT_EQ(std::string("_comp_ime_") + kKeyboardExtId + "vkd_th",
453 input_method_ids[1]); // Kesmanee.
456 // US keyboard + Vietnamese = US keyboard + TCVN6064.
457 TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Vi) {
458 const InputMethodDescriptor* descriptor =
459 util_.GetInputMethodDescriptorFromId("xkb:us::eng"); // US keyboard.
460 ASSERT_TRUE(NULL != descriptor); // ASSERT_NE doesn't compile.
461 std::vector<std::string> input_method_ids;
462 util_.GetFirstLoginInputMethodIds("vi", *descriptor, &input_method_ids);
463 ASSERT_EQ(2U, input_method_ids.size());
464 EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
465 EXPECT_EQ(std::string("_comp_ime_") + kKeyboardExtId + "vkd_vi_tcvn",
466 input_method_ids[1]); // TCVN6064.
469 TEST_F(InputMethodUtilTest, TestGetLanguageCodesFromInputMethodIds) {
470 std::vector<std::string> input_method_ids;
471 input_method_ids.push_back("xkb:us::eng"); // English US.
472 input_method_ids.push_back("xkb:us:dvorak:eng"); // English US Dvorak.
473 input_method_ids.push_back(pinyin_ime_id); // Pinyin
474 input_method_ids.push_back("xkb:fr::fra"); // French France.
475 std::vector<std::string> language_codes;
476 util_.GetLanguageCodesFromInputMethodIds(input_method_ids, &language_codes);
477 ASSERT_EQ(3U, language_codes.size());
478 EXPECT_EQ("en-US", language_codes[0]);
479 EXPECT_EQ("zh-CN", language_codes[1]);
480 EXPECT_EQ("fr", language_codes[2]);
483 // Test all supported descriptors to detect a typo in input_methods.txt.
484 TEST_F(InputMethodUtilTest, TestIBusInputMethodText) {
485 for (size_t i = 0; i < util_.supported_input_methods_->size(); ++i) {
486 const std::string language_code =
487 util_.supported_input_methods_->at(i).language_codes().at(0);
488 const base::string16 display_name =
489 l10n_util::GetDisplayNameForLocale(language_code, "en", false);
490 // Only two formats, like "fr" (lower case) and "en-US" (lower-upper), are
491 // allowed. See the text file for details.
492 EXPECT_TRUE(language_code.length() == 2 ||
493 (language_code.length() == 5 && language_code[2] == '-'))
494 << "Invalid language code " << language_code;
495 EXPECT_TRUE(l10n_util::IsValidLocaleSyntax(language_code))
496 << "Invalid language code " << language_code;
497 EXPECT_FALSE(display_name.empty())
498 << "Invalid language code " << language_code;
499 // On error, GetDisplayNameForLocale() returns the |language_code| as-is.
500 EXPECT_NE(language_code, base::UTF16ToUTF8(display_name))
501 << "Invalid language code " << language_code;
505 } // namespace input_method
506 } // namespace chromeos