Index: ui/base/ime/input_method_auralinux_unittest.cc |
diff --git a/ui/base/ime/input_method_auralinux_unittest.cc b/ui/base/ime/input_method_auralinux_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9dd90c811906afb81798b4cd974d8bb11fce3858 |
--- /dev/null |
+++ b/ui/base/ime/input_method_auralinux_unittest.cc |
@@ -0,0 +1,515 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/base/ime/input_method_auralinux.h" |
+ |
+#include "base/strings/string_split.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "ui/base/ime/dummy_text_input_client.h" |
+#include "ui/base/ime/input_method_delegate.h" |
+#include "ui/base/ime/input_method_initializer.h" |
+#include "ui/base/ime/linux/fake_input_method_context.h" |
+#include "ui/base/ime/linux/linux_input_method_context_factory.h" |
+#include "ui/events/event.h" |
+ |
+namespace ui { |
+namespace { |
+ |
+const base::char16 kActionCommit = L'C'; |
+const base::char16 kActionCompositionStart = L'S'; |
+const base::char16 kActionCompositionUpdate = L'U'; |
+const base::char16 kActionCompositionEnd = L'E'; |
+ |
+class LinuxInputMethodContextForTesting : public LinuxInputMethodContext { |
+ public: |
+ LinuxInputMethodContextForTesting( |
+ LinuxInputMethodContextDelegate* delegate, bool is_simple) |
+ : delegate_(delegate), is_simple_(is_simple), is_sync_mode_(false), |
+ eat_key_(false), focused_(false) {} |
+ |
+ void SetSyncMode(bool is_sync_mode) { is_sync_mode_ = is_sync_mode; } |
+ void SetEatKey(bool eat_key) { eat_key_ = eat_key; } |
+ |
+ void AddAction(const std::string& action) { |
+ actions_.push_back(base::ASCIIToUTF16(action)); |
+ } |
+ |
+ protected: |
+ bool DispatchKeyEvent(const ui::KeyEvent& key_event) override { |
+ if (!is_sync_mode_) { |
+ actions_.clear(); |
+ return eat_key_; |
+ } |
+ |
+ for (size_t i = 0; i < actions_.size(); i++) { |
+ base::string16 action = actions_[i]; |
+ std::vector<base::string16> parts; |
+ base::SplitString(action, L':', &parts); |
+ base::char16 id = parts[0][0]; |
+ base::string16 param; |
+ if (parts.size() > 1) |
+ param = parts[1]; |
+ if (id == kActionCommit) { |
+ delegate_->OnCommit(param); |
+ } else if (id == kActionCompositionStart) { |
+ delegate_->OnPreeditStart(); |
+ } else if (id == kActionCompositionUpdate) { |
+ CompositionText comp; |
+ comp.text = param; |
+ delegate_->OnPreeditChanged(comp); |
+ } else if (id == kActionCompositionEnd) { |
+ delegate_->OnPreeditEnd(); |
+ } |
+ } |
+ |
+ actions_.clear(); |
+ return eat_key_; |
+ } |
+ |
+ void Reset() override { |
+ } |
+ |
+ void Focus() override { |
+ focused_ = true; |
+ } |
+ |
+ void Blur() override { |
+ focused_ = false; |
+ } |
+ |
+ void SetCursorLocation(const gfx::Rect& rect) override { |
+ cursor_position_ = rect; |
+ } |
+ |
+ private: |
+ LinuxInputMethodContextDelegate* delegate_; |
+ std::vector<base::string16> actions_; |
+ bool is_simple_; |
+ bool is_sync_mode_; |
+ bool eat_key_; |
+ bool focused_; |
+ gfx::Rect cursor_position_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(LinuxInputMethodContextForTesting); |
+}; |
+ |
+class LinuxInputMethodContextFactoryForTesting : |
+ public LinuxInputMethodContextFactory { |
+ public: |
+ LinuxInputMethodContextFactoryForTesting() {}; |
+ |
+ scoped_ptr<LinuxInputMethodContext> CreateInputMethodContext( |
+ LinuxInputMethodContextDelegate* delegate, |
+ bool is_simple) const override { |
+ return scoped_ptr<ui::LinuxInputMethodContext>( |
+ new LinuxInputMethodContextForTesting(delegate, is_simple)); |
+ }; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(LinuxInputMethodContextFactoryForTesting); |
+}; |
+ |
+class InputMethodDelegateForTesting : public internal::InputMethodDelegate { |
+ public: |
+ InputMethodDelegateForTesting() |
+ : key_type(ET_UNKNOWN), key_code(VKEY_UNKNOWN), key_flags(0) {}; |
+ ~InputMethodDelegateForTesting() override {}; |
+ |
+ bool DispatchKeyEventPostIME(const ui::KeyEvent& key_event) override { |
+ key_type = key_event.type(); |
+ key_code = key_event.key_code(); |
+ key_flags = key_event.flags(); |
+ return false; |
+ } |
+ |
+ void Clear() { |
+ key_type = ET_UNKNOWN; |
+ key_code = VKEY_UNKNOWN; |
+ key_flags = 0; |
+ } |
+ |
+ EventType key_type; |
+ KeyboardCode key_code; |
+ int key_flags; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(InputMethodDelegateForTesting); |
+}; |
+ |
+class TextInputClientForTesting : public DummyTextInputClient { |
+ public: |
+ explicit TextInputClientForTesting(TextInputType text_input_type) |
+ : DummyTextInputClient(text_input_type), |
+ called_clear_composition(false), called_confirm_composition(false), |
+ called_set_composition(false), called_insert_text(false), |
+ called_insert_char(false) {}; |
+ |
+ void Clear() { |
+ composition_text.clear(); |
+ result_text.clear(); |
+ called_clear_composition = called_confirm_composition = |
+ called_set_composition = called_insert_text = called_insert_char = |
+ false; |
+ } |
+ |
+ base::string16 composition_text; |
+ base::string16 result_text; |
+ bool called_clear_composition; |
+ bool called_confirm_composition; |
+ bool called_set_composition; |
+ bool called_insert_text; |
+ bool called_insert_char; |
+ |
+ protected: |
+ void SetCompositionText(const CompositionText& composition) override { |
+ composition_text = composition.text; |
+ called_set_composition = true; |
+ } |
+ |
+ bool HasCompositionText() const override { |
+ return !composition_text.empty(); |
+ } |
+ |
+ void ConfirmCompositionText() override { |
+ composition_text.clear(); |
+ called_confirm_composition = true; |
+ } |
+ |
+ void ClearCompositionText() override { |
+ composition_text.clear(); |
+ called_clear_composition = true; |
+ } |
+ |
+ void InsertText(const base::string16& text) override { |
+ result_text = text; |
+ called_insert_text = true; |
+ } |
+ |
+ void InsertChar(base::char16 ch, int flags) override { |
+ result_text = ch; |
+ called_insert_char = true; |
+ } |
+}; |
+ |
+class InputMethodAuraLinuxTest : public testing::Test { |
+ protected: |
+ InputMethodAuraLinuxTest() |
+ : factory_(NULL), input_method_auralinux_(NULL), delegate_(NULL), |
+ context_(NULL), context_simple_(NULL) { |
+ factory_ = new LinuxInputMethodContextFactoryForTesting(); |
+ LinuxInputMethodContextFactory::SetInstance(factory_); |
+ } |
+ ~InputMethodAuraLinuxTest() override { |
+ delete factory_; |
+ factory_ = NULL; |
+ } |
+ |
+ void SetUp() override { |
+ delegate_ = new InputMethodDelegateForTesting(); |
+ input_method_auralinux_ = new InputMethodAuraLinux(delegate_); |
+ input_method_auralinux_->OnFocus(); |
+ context_ = static_cast<LinuxInputMethodContextForTesting*>( |
+ input_method_auralinux_->GetContextForTesting(false)); |
+ context_simple_ = static_cast<LinuxInputMethodContextForTesting*>( |
+ input_method_auralinux_->GetContextForTesting(true)); |
+ } |
+ |
+ void TearDown() override { |
+ context_->SetSyncMode(false); |
+ context_->SetEatKey(false); |
+ |
+ context_simple_->SetSyncMode(false); |
+ context_simple_->SetEatKey(false); |
+ |
+ context_ = NULL; |
+ context_simple_ = NULL; |
+ |
+ delete input_method_auralinux_; |
+ input_method_auralinux_ = NULL; |
+ delete delegate_; |
+ delegate_ = NULL; |
+ } |
+ |
+ LinuxInputMethodContextFactoryForTesting* factory_; |
+ InputMethodAuraLinux* input_method_auralinux_; |
+ InputMethodDelegateForTesting* delegate_; |
+ LinuxInputMethodContextForTesting* context_; |
+ LinuxInputMethodContextForTesting* context_simple_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(InputMethodAuraLinuxTest); |
+}; |
+ |
+TEST_F(InputMethodAuraLinuxTest, BasicSyncModeTest) { |
+ context_->SetSyncMode(true); |
+ context_->SetEatKey(true); |
+ context_->AddAction("C:a"); |
+ |
+ TextInputClientForTesting* client = new TextInputClientForTesting( |
Seigo Nonaka
2015/04/08 07:14:58
Optional: I recommend you to use scoped_ptr for th
Shu Chen
2015/04/08 08:24:12
Done.
|
+ TEXT_INPUT_TYPE_TEXT); |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ |
+ KeyEvent key(ET_KEY_PRESSED, VKEY_A, 0); |
+ key.set_character(L'a'); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ EXPECT_EQ(key.type(), delegate_->key_type); |
+ EXPECT_EQ(key.key_code(), delegate_->key_code); |
+ EXPECT_EQ(key.flags(), delegate_->key_flags); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_TRUE(client->called_insert_char); |
+ EXPECT_EQ(1U, client->result_text.size()); |
+ EXPECT_EQ(key.GetCharacter(), client->result_text[0]); |
+ |
+ delete client; |
+ client = new TextInputClientForTesting(TEXT_INPUT_TYPE_PASSWORD); |
+ context_simple_->SetSyncMode(true); |
+ context_simple_->SetEatKey(false); |
+ |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ EXPECT_EQ(key.type(), delegate_->key_type); |
+ EXPECT_EQ(key.key_code(), delegate_->key_code); |
+ EXPECT_EQ(key.flags(), delegate_->key_flags); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_TRUE(client->called_insert_char); |
+ EXPECT_EQ(1U, client->result_text.size()); |
+ EXPECT_EQ(key.GetCharacter(), client->result_text[0]); |
+ |
+ delete client; |
+} |
+ |
+TEST_F(InputMethodAuraLinuxTest, BasicAsyncModeTest) { |
+ context_->SetSyncMode(false); |
+ context_->SetEatKey(true); |
+ |
+ TextInputClientForTesting* client = new TextInputClientForTesting( |
+ TEXT_INPUT_TYPE_TEXT); |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ KeyEvent key(ET_KEY_PRESSED, VKEY_A, 0); |
+ key.set_character(L'a'); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ input_method_auralinux_->OnCommit(base::ASCIIToUTF16("a")); |
+ |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_PROCESSKEY, delegate_->key_code); |
+ EXPECT_EQ(0, delegate_->key_flags); |
+ EXPECT_TRUE(client->called_insert_text); |
+ EXPECT_FALSE(client->called_insert_char); |
+ EXPECT_EQ(1U, client->result_text.size()); |
+ EXPECT_EQ(key.GetCharacter(), client->result_text[0]); |
+ |
+ delete client; |
+ client = new TextInputClientForTesting(TEXT_INPUT_TYPE_PASSWORD); |
+ context_simple_->SetSyncMode(false); |
+ context_simple_->SetEatKey(false); |
+ |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_A, delegate_->key_code); |
+ EXPECT_EQ(0, delegate_->key_flags); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_TRUE(client->called_insert_char); |
+ EXPECT_EQ(1U, client->result_text.size()); |
+ EXPECT_EQ(key.GetCharacter(), client->result_text[0]); |
+ |
+ delete client; |
+} |
+ |
+TEST_F(InputMethodAuraLinuxTest, IBusUSTest) { |
+ context_->SetSyncMode(false); |
+ context_->SetEatKey(true); |
+ |
+ TextInputClientForTesting* client = new TextInputClientForTesting( |
+ TEXT_INPUT_TYPE_TEXT); |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ KeyEvent key(ET_KEY_PRESSED, VKEY_A, 0); |
+ key.set_character(L'a'); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ // iBus mutes the key down. |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_PROCESSKEY, delegate_->key_code); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_FALSE(client->called_insert_char); |
+ |
+ // iBus simulates a faked key down and handle it in sync mode. |
+ context_->SetSyncMode(true); |
+ context_->AddAction("C:a"); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ EXPECT_EQ(VKEY_A, delegate_->key_code); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_TRUE(client->called_insert_char); |
+ EXPECT_EQ(1U, client->result_text.size()); |
+ EXPECT_EQ(key.GetCharacter(), client->result_text[0]); |
+ |
+ // iBus does NOT handle the key up. |
+ client->Clear(); |
+ context_->SetEatKey(false); |
+ input_method_auralinux_->DispatchKeyEvent(KeyEvent( |
+ ET_KEY_RELEASED, VKEY_A, 0)); |
+ |
+ EXPECT_EQ(ET_KEY_RELEASED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_A, delegate_->key_code); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_FALSE(client->called_insert_char); |
+ |
+ delete client; |
+} |
+ |
+TEST_F(InputMethodAuraLinuxTest, IBusPinyinTest) { |
+ context_->SetSyncMode(false); |
+ context_->SetEatKey(true); |
+ |
+ TextInputClientForTesting* client = new TextInputClientForTesting( |
+ TEXT_INPUT_TYPE_TEXT); |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ KeyEvent key(ET_KEY_PRESSED, VKEY_A, 0); |
+ key.set_character(L'a'); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ // iBus mutes the key down. |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_PROCESSKEY, delegate_->key_code); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_FALSE(client->called_insert_char); |
+ delegate_->Clear(); |
+ |
+ // iBus issues a standalone set_composition action. |
+ input_method_auralinux_->OnPreeditStart(); |
+ CompositionText comp; |
+ comp.text = base::ASCIIToUTF16("a"); |
+ input_method_auralinux_->OnPreeditChanged(comp); |
+ |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_PROCESSKEY, delegate_->key_code); |
+ EXPECT_TRUE(client->called_set_composition); |
+ EXPECT_EQ(1U, client->composition_text.size()); |
+ EXPECT_EQ(L'a', client->composition_text[0]); |
+ delegate_->Clear(); |
+ // iBus issues a commit text with composition after muting the space key down. |
+ input_method_auralinux_->DispatchKeyEvent(KeyEvent( |
+ ET_KEY_PRESSED, VKEY_SPACE, 0)); |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_PROCESSKEY, delegate_->key_code); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_FALSE(client->called_insert_char); |
+ delegate_->Clear(); |
+ |
+ input_method_auralinux_->OnPreeditEnd(); |
+ input_method_auralinux_->OnCommit(base::ASCIIToUTF16("A")); |
+ |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_PROCESSKEY, delegate_->key_code); |
+ EXPECT_TRUE(client->called_clear_composition); |
+ EXPECT_TRUE(client->called_insert_text); |
+ EXPECT_EQ(1U, client->result_text.size()); |
+ EXPECT_EQ(L'A', client->result_text[0]); |
+ |
+ delete client; |
+} |
+ |
+// crbug.com/463491 |
+TEST_F(InputMethodAuraLinuxTest, DeadKeyTest) { |
+ context_simple_->SetSyncMode(true); |
+ context_simple_->SetEatKey(true); |
+ |
+ TextInputClientForTesting* client = new TextInputClientForTesting( |
+ TEXT_INPUT_TYPE_NONE); |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ KeyEvent dead_key(ET_KEY_PRESSED, VKEY_OEM_7, 0); |
+ dead_key.set_character(L'\''); |
+ input_method_auralinux_->DispatchKeyEvent(dead_key); |
+ |
+ // The single quote key is muted. |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_OEM_7, delegate_->key_code); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_FALSE(client->called_insert_char); |
+ delegate_->Clear(); |
+ |
+ context_simple_->AddAction("C:X"); |
+ KeyEvent key(ET_KEY_PRESSED, VKEY_A, 0); |
+ key.set_character(L'a'); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ // The following A key generates the accent key: รก. |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_A, delegate_->key_code); |
+ EXPECT_FALSE(client->called_insert_text); |
+ EXPECT_TRUE(client->called_insert_char); |
+ EXPECT_EQ(1U, client->result_text.size()); |
+ EXPECT_EQ(L'X', client->result_text[0]); |
+ |
+ delete client; |
+} |
+ |
+TEST_F(InputMethodAuraLinuxTest, MultiCommitsTest) { |
+ context_->SetSyncMode(true); |
+ context_->SetEatKey(true); |
+ context_->AddAction("C:a"); |
+ context_->AddAction("C:b"); |
+ context_->AddAction("C:c"); |
+ |
+ TextInputClientForTesting* client = new TextInputClientForTesting( |
+ TEXT_INPUT_TYPE_TEXT); |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ |
+ KeyEvent key(ET_KEY_PRESSED, VKEY_A, 0); |
+ key.set_character(L'a'); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_PROCESSKEY, delegate_->key_code); |
+ EXPECT_TRUE(client->called_insert_text); |
+ EXPECT_FALSE(client->called_insert_char); |
+ EXPECT_EQ(base::ASCIIToUTF16("abc"), client->result_text); |
+ |
+ delete client; |
+} |
+ |
+TEST_F(InputMethodAuraLinuxTest, MixedCompositionAndCommitTest) { |
+ context_->SetSyncMode(true); |
+ context_->SetEatKey(true); |
+ context_->AddAction("C:a"); |
+ context_->AddAction("S"); |
+ context_->AddAction("U:b"); |
+ context_->AddAction("C:c"); |
+ context_->AddAction("U:d"); |
+ |
+ TextInputClientForTesting* client = new TextInputClientForTesting( |
+ TEXT_INPUT_TYPE_TEXT); |
+ input_method_auralinux_->SetFocusedTextInputClient(client); |
+ input_method_auralinux_->OnTextInputTypeChanged(client); |
+ |
+ KeyEvent key(ET_KEY_PRESSED, VKEY_A, 0); |
+ key.set_character(L'a'); |
+ input_method_auralinux_->DispatchKeyEvent(key); |
+ |
+ EXPECT_EQ(ET_KEY_PRESSED, delegate_->key_type); |
+ EXPECT_EQ(VKEY_PROCESSKEY, delegate_->key_code); |
+ EXPECT_TRUE(client->called_set_composition); |
+ EXPECT_TRUE(client->called_insert_text); |
+ EXPECT_FALSE(client->called_insert_char); |
+ EXPECT_EQ(base::ASCIIToUTF16("d"), client->composition_text); |
+ EXPECT_EQ(base::ASCIIToUTF16("ac"), client->result_text); |
+ |
+ delete client; |
+} |
+ |
+} // namespace |
+} // namespace ui |
+ |