Chromium Code Reviews| 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 |
| + |