| // Copyright 2010-2015, Google Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #include "session/key_event_util.h" |
| |
| #include "base/number_util.h" |
| #include "base/util.h" |
| #include "session/commands.pb.h" |
| #include "session/key_parser.h" |
| #include "testing/base/public/gunit.h" |
| |
| namespace mozc { |
| using commands::KeyEvent; |
| |
| namespace { |
| ::testing::AssertionResult CompareKeyEvent(const char *expected_expr, |
| const char *actual_expr, |
| const KeyEvent &expected, |
| const KeyEvent &actual) { |
| { // Key code |
| const int expected_key_code = |
| (expected.has_key_code()) ? expected.key_code() : -1; |
| const int actual_key_code = |
| (actual.has_key_code()) ? actual.key_code() : -1; |
| if (expected_key_code != actual_key_code) { |
| const string expected_value = (expected_key_code == -1) |
| ? "None" |
| : Util::StringPrintf("%c (%d)", expected_key_code, expected_key_code); |
| const string actual_value = (actual_key_code == -1) |
| ? string("None") |
| : Util::StringPrintf("%c (%d)", actual_key_code, actual_key_code); |
| return ::testing::AssertionFailure() << |
| "Key codes are not same\n" << |
| "Expected: " << expected_value << "\n" << |
| "Actual : " << actual_value; |
| } |
| } |
| |
| { // Special key |
| const int expected_special_key = |
| (expected.has_special_key()) ? expected.special_key() : -1; |
| const int actual_special_key = |
| (actual.has_special_key()) ? actual.special_key() : -1; |
| if (expected_special_key != actual_special_key) { |
| const string expected_value = (expected_special_key == -1) |
| ? "None" : NumberUtil::SimpleItoa(expected_special_key); |
| const string actual_value = (actual_special_key == -1) |
| ? "None" : NumberUtil::SimpleItoa(actual_special_key); |
| return ::testing::AssertionFailure() << |
| "Special keys are not same\n" << |
| "Expected: " << expected_value << "\n" << |
| "Actual : " << actual_value; |
| } |
| } |
| |
| { // Modifier keys |
| const int expected_modifier_keys = KeyEventUtil::GetModifiers(expected); |
| const int actual_modifier_keys = KeyEventUtil::GetModifiers(actual); |
| if (expected_modifier_keys != actual_modifier_keys) { |
| return ::testing::AssertionFailure() << |
| "Modifier keys are not same\n" << |
| "Expected: " << expected_modifier_keys << "\n" << |
| "Actual : " << actual_modifier_keys; |
| } |
| } |
| |
| return ::testing::AssertionSuccess(); |
| } |
| |
| #define EXPECT_EQ_KEY_EVENT(expected, actual) \ |
| EXPECT_PRED_FORMAT2(CompareKeyEvent, expected, actual) |
| } // namespace |
| |
| TEST(KeyEventUtilTest, GetModifiers) { |
| KeyEvent key_event; |
| |
| KeyParser::ParseKey("a", &key_event); |
| EXPECT_EQ(0, KeyEventUtil::GetModifiers(key_event)); |
| |
| KeyParser::ParseKey("Alt", &key_event); |
| EXPECT_EQ(KeyEvent::ALT, KeyEventUtil::GetModifiers(key_event)); |
| |
| KeyParser::ParseKey("Ctrl", &key_event); |
| EXPECT_EQ(KeyEvent::CTRL, KeyEventUtil::GetModifiers(key_event)); |
| |
| KeyParser::ParseKey("Shift", &key_event); |
| EXPECT_EQ(KeyEvent::SHIFT, KeyEventUtil::GetModifiers(key_event)); |
| |
| KeyParser::ParseKey("Caps", &key_event); |
| EXPECT_EQ(KeyEvent::CAPS, KeyEventUtil::GetModifiers(key_event)); |
| |
| KeyParser::ParseKey("LeftAlt RightAlt", &key_event); |
| EXPECT_EQ((KeyEvent::ALT | KeyEvent::LEFT_ALT | KeyEvent::RIGHT_ALT), |
| KeyEventUtil::GetModifiers(key_event)); |
| |
| KeyParser::ParseKey("LeftAlt Ctrl RightShift", &key_event); |
| EXPECT_EQ((KeyEvent::ALT | KeyEvent::LEFT_ALT | KeyEvent::CTRL | |
| KeyEvent::SHIFT | KeyEvent::RIGHT_SHIFT), |
| KeyEventUtil::GetModifiers(key_event)); |
| } |
| |
| TEST(KeyEventUtilTest, GetKeyInformation) { |
| const char *kTestKeys[] = { |
| "a", |
| "Space", |
| "Shift", |
| "Shift a", |
| "Shift Space", |
| "Space a", |
| "LeftShift Space a", |
| }; |
| |
| KeyEvent key_event; |
| uint64 output; |
| |
| for (size_t i = 0; i < arraysize(kTestKeys); ++i) { |
| SCOPED_TRACE(kTestKeys[i]); |
| KeyParser::ParseKey(kTestKeys[i], &key_event); |
| ASSERT_TRUE(KeyEventUtil::GetKeyInformation(key_event, &output)); |
| |
| uint64 expected = 0; |
| if (key_event.has_key_code()) { |
| expected |= static_cast<uint64>(key_event.key_code()); |
| } |
| if (key_event.has_special_key()) { |
| expected |= static_cast<uint64>(key_event.special_key()) << 32; |
| } |
| expected |= |
| static_cast<uint64>(KeyEventUtil::GetModifiers(key_event)) << 48; |
| |
| EXPECT_EQ(expected, output); |
| } |
| |
| const uint32 kEscapeKeyCode = 27; |
| key_event.Clear(); |
| key_event.set_key_code(kEscapeKeyCode); |
| // Escape key should not set on key_code field. |
| EXPECT_FALSE(KeyEventUtil::GetKeyInformation(key_event, &output)); |
| } |
| |
| TEST(KeyEventUtilTest, NormalizeModifiers) { |
| KeyEvent key_event; |
| KeyEvent normalized_key_event; |
| |
| { // Removes caps |
| KeyParser::ParseKey("CAPS H", &key_event); |
| ASSERT_EQ(1, key_event.modifier_keys_size()); |
| ASSERT_EQ(KeyEvent::CAPS, KeyEventUtil::GetModifiers(key_event)); |
| ASSERT_EQ('H', key_event.key_code()); |
| |
| KeyEventUtil::NormalizeModifiers(key_event, &normalized_key_event); |
| EXPECT_EQ(0, normalized_key_event.modifier_keys_size()); |
| EXPECT_EQ('h', normalized_key_event.key_code()); |
| } |
| |
| { // Removes left_shift |
| KeyParser::ParseKey("LeftShift", &key_event); |
| ASSERT_EQ(2, key_event.modifier_keys_size()); |
| ASSERT_EQ((KeyEvent::SHIFT | KeyEvent::LEFT_SHIFT), |
| KeyEventUtil::GetModifiers(key_event)); |
| |
| KeyEventUtil::NormalizeModifiers(key_event, &normalized_key_event); |
| EXPECT_EQ(1, normalized_key_event.modifier_keys_size()); |
| ASSERT_EQ(KeyEvent::SHIFT, |
| KeyEventUtil::GetModifiers(normalized_key_event)); |
| } |
| |
| { // Removes caps and left_shift |
| KeyParser::ParseKey("CAPS LeftShift H", &key_event); |
| ASSERT_EQ(3, key_event.modifier_keys_size()); |
| ASSERT_EQ((KeyEvent::CAPS | KeyEvent::SHIFT | KeyEvent::LEFT_SHIFT), |
| KeyEventUtil::GetModifiers(key_event)); |
| |
| ASSERT_EQ('H', key_event.key_code()); |
| |
| KeyEventUtil::NormalizeModifiers(key_event, &normalized_key_event); |
| EXPECT_EQ(1, normalized_key_event.modifier_keys_size()); |
| EXPECT_EQ(KeyEvent::SHIFT, |
| KeyEventUtil::GetModifiers(normalized_key_event)); |
| EXPECT_EQ('h', normalized_key_event.key_code()); |
| } |
| } |
| |
| TEST(KeyEventUtilTest, NormalizeNumpadKey) { |
| const struct NormalizeNumpadKeyTestData { |
| const char *from; |
| const char *to; |
| } kNormalizeNumpadKeyTestData[] = { |
| { "a", "a" }, |
| { "Shift", "Shift" }, |
| { "Caps", "Caps" }, |
| { "Enter", "Enter" }, |
| { "Shift Caps a", "Shift Caps a" }, |
| { "NUMPAD0", "0" }, |
| { "NUMPAD9", "9" }, |
| { "MULTIPLY", "*" }, |
| { "SEPARATOR", "Enter" }, |
| { "EQUALS", "=" }, |
| { "Ctrl NUMPAD0", "Ctrl 0" }, |
| { "NUMPAD0 a", "0" }, |
| }; |
| |
| for (size_t i = 0; i < arraysize(kNormalizeNumpadKeyTestData); ++i) { |
| const NormalizeNumpadKeyTestData &data = kNormalizeNumpadKeyTestData[i]; |
| SCOPED_TRACE(data.from); |
| |
| KeyEvent key_event_from, key_event_to, key_event_normalized; |
| KeyParser::ParseKey(data.from, &key_event_from); |
| KeyParser::ParseKey(data.to, &key_event_to); |
| KeyEventUtil::NormalizeNumpadKey(key_event_from, &key_event_normalized); |
| EXPECT_EQ_KEY_EVENT(key_event_to, key_event_normalized); |
| } |
| } |
| |
| TEST(KeyEventUtilTest, MaybeGetKeyStub) { |
| KeyEvent key_event; |
| KeyInformation key; |
| |
| KeyParser::ParseKey("Shift", &key_event); |
| EXPECT_FALSE(KeyEventUtil::MaybeGetKeyStub(key_event, &key)); |
| |
| KeyParser::ParseKey("Space", &key_event); |
| EXPECT_FALSE(KeyEventUtil::MaybeGetKeyStub(key_event, &key)); |
| |
| const uint32 kEscapeKeyCode = 27; |
| key_event.Clear(); |
| key_event.set_key_code(kEscapeKeyCode); |
| EXPECT_FALSE(KeyEventUtil::MaybeGetKeyStub(key_event, &key)); |
| |
| KeyParser::ParseKey("a", &key_event); |
| EXPECT_TRUE(KeyEventUtil::MaybeGetKeyStub(key_event, &key)); |
| EXPECT_EQ(static_cast<KeyInformation>(KeyEvent::TEXT_INPUT) << 32, key); |
| } |
| |
| TEST(KeyEventUtilTest, RemvoeModifiers) { |
| const struct RemoveModifiersTestData { |
| const char *input; |
| const char *remove; |
| const char *output; |
| } kRemoveModifiersTestData[] = { |
| { |
| "", |
| "", |
| "", |
| }, { |
| "Ctrl Shift LeftAlt Caps", |
| "Ctrl Shift LeftAlt Caps", |
| "", |
| }, { |
| "Ctrl Shift LeftAlt Caps", |
| "Shift Caps", |
| "Ctrl LeftAlt", |
| }, { |
| "Ctrl Shift LeftAlt Caps", |
| "Alt", |
| "Ctrl Shift Caps", |
| }, { |
| "", |
| "Ctrl Shift LeftAlt Caps", |
| "", |
| }, |
| }; |
| |
| for (size_t i = 0; i < arraysize(kRemoveModifiersTestData); ++i) { |
| SCOPED_TRACE(Util::StringPrintf("index = %d", static_cast<int>(i))); |
| const RemoveModifiersTestData &data = kRemoveModifiersTestData[i]; |
| |
| KeyEvent input, remove, output; |
| KeyParser::ParseKey(data.input, &input); |
| KeyParser::ParseKey(data.remove, &remove); |
| KeyParser::ParseKey(data.output, &output); |
| const uint32 remove_modifiers = KeyEventUtil::GetModifiers(remove); |
| |
| KeyEvent removed_key_event; |
| KeyEventUtil::RemoveModifiers(input, remove_modifiers, &removed_key_event); |
| EXPECT_EQ_KEY_EVENT(output, removed_key_event); |
| } |
| } |
| |
| TEST(KeyEventUtilTest, HasModifiers) { |
| EXPECT_TRUE(KeyEventUtil::HasAlt(KeyEvent::ALT)); |
| EXPECT_TRUE(KeyEventUtil::HasAlt(KeyEvent::LEFT_ALT)); |
| EXPECT_TRUE(KeyEventUtil::HasAlt(KeyEvent::ALT | KeyEvent::CTRL)); |
| EXPECT_FALSE(KeyEventUtil::HasAlt(0)); |
| EXPECT_FALSE(KeyEventUtil::HasAlt(KeyEvent::CTRL)); |
| EXPECT_FALSE(KeyEventUtil::HasAlt(KeyEvent::SHIFT)); |
| |
| EXPECT_TRUE(KeyEventUtil::HasCtrl(KeyEvent::CTRL)); |
| EXPECT_TRUE(KeyEventUtil::HasCtrl(KeyEvent::LEFT_CTRL)); |
| EXPECT_TRUE(KeyEventUtil::HasCtrl(KeyEvent::CTRL | KeyEvent::SHIFT)); |
| EXPECT_FALSE(KeyEventUtil::HasCtrl(0)); |
| EXPECT_FALSE(KeyEventUtil::HasCtrl(KeyEvent::ALT)); |
| EXPECT_FALSE(KeyEventUtil::HasCtrl(KeyEvent::SHIFT)); |
| |
| EXPECT_TRUE(KeyEventUtil::HasShift(KeyEvent::SHIFT)); |
| EXPECT_TRUE(KeyEventUtil::HasShift(KeyEvent::LEFT_SHIFT)); |
| EXPECT_TRUE(KeyEventUtil::HasShift(KeyEvent::SHIFT | KeyEvent::ALT)); |
| EXPECT_FALSE(KeyEventUtil::HasShift(0)); |
| EXPECT_FALSE(KeyEventUtil::HasShift(KeyEvent::ALT)); |
| EXPECT_FALSE(KeyEventUtil::HasShift(KeyEvent::CTRL)); |
| |
| EXPECT_TRUE(KeyEventUtil::HasCaps(KeyEvent::CAPS)); |
| EXPECT_TRUE(KeyEventUtil::HasCaps(KeyEvent::CAPS | KeyEvent::ALT)); |
| EXPECT_FALSE(KeyEventUtil::HasCaps(0)); |
| EXPECT_FALSE(KeyEventUtil::HasCaps(KeyEvent::CTRL)); |
| } |
| |
| TEST(KeyEventUtilTest, IsModifiers) { |
| const struct IsModifiersTestData { |
| uint32 modifiers; |
| bool is_alt; |
| bool is_ctrl; |
| bool is_shift; |
| bool is_alt_ctrl; |
| bool is_alt_shift; |
| bool is_ctrl_shift; |
| bool is_alt_ctrl_shift; |
| } kIsModifiersTestData[] = { |
| { |
| 0, |
| false, false, false, false, false, false, false |
| }, { |
| KeyEvent::ALT, |
| true, false, false, false, false, false, false, |
| }, { |
| KeyEvent::CTRL, |
| false, true, false, false, false, false, false, |
| }, { |
| KeyEvent::SHIFT, |
| false, false, true, false, false, false, false, |
| }, { |
| KeyEvent::ALT | KeyEvent::CTRL, |
| false, false, false, true, false, false, false, |
| }, { |
| KeyEvent::ALT | KeyEvent::SHIFT, |
| false, false, false, false, true, false, false, |
| }, { |
| KeyEvent::CTRL | KeyEvent::SHIFT, |
| false, false, false, false, false, true, false, |
| }, { |
| KeyEvent::ALT | KeyEvent::CTRL | KeyEvent::SHIFT, |
| false, false, false, false, false, false, true, |
| }, { |
| KeyEvent::LEFT_ALT, |
| true, false, false, false, false, false, false, |
| }, { |
| KeyEvent::ALT | KeyEvent::LEFT_ALT | KeyEvent::RIGHT_ALT, |
| true, false, false, false, false, false, false, |
| }, { |
| KeyEvent::CAPS, |
| false, false, false, false, false, false, false, |
| }, { |
| KeyEvent::ALT | KeyEvent::CAPS, |
| true, false, false, false, false, false, false, |
| }, |
| }; |
| |
| for (size_t i = 0; i < arraysize(kIsModifiersTestData); ++i) { |
| const IsModifiersTestData &data = kIsModifiersTestData[i]; |
| SCOPED_TRACE(Util::StringPrintf("index: %d", static_cast<int>(i))); |
| |
| EXPECT_EQ(data.is_alt, KeyEventUtil::IsAlt(data.modifiers)); |
| EXPECT_EQ(data.is_ctrl, KeyEventUtil::IsCtrl(data.modifiers)); |
| EXPECT_EQ(data.is_shift, KeyEventUtil::IsShift(data.modifiers)); |
| EXPECT_EQ(data.is_alt_ctrl, KeyEventUtil::IsAltCtrl(data.modifiers)); |
| EXPECT_EQ(data.is_alt_shift, KeyEventUtil::IsAltShift(data.modifiers)); |
| EXPECT_EQ(data.is_ctrl_shift, KeyEventUtil::IsCtrlShift(data.modifiers)); |
| EXPECT_EQ(data.is_alt_ctrl_shift, |
| KeyEventUtil::IsAltCtrlShift(data.modifiers)); |
| } |
| } |
| |
| TEST(KeyEventUtilTest, IsLowerUpperAlphabet) { |
| const struct IsLowerUpperAlphabetTestData { |
| const char *key; |
| bool is_lower; |
| bool is_upper; |
| } kIsLowerUpperAlphabetTestData[] = { |
| { "a", true, false }, |
| { "A", false, true }, |
| { "Shift a", false, true }, |
| { "Shift A", true, false }, |
| { "Shift Caps a", true, false }, |
| { "Shift Caps A", false, true }, |
| { "0", false, false }, |
| { "Shift", false, false }, |
| { "Caps", false, false }, |
| { "Space", false, false }, |
| }; |
| |
| for (size_t i = 0; i < arraysize(kIsLowerUpperAlphabetTestData); ++i) { |
| const IsLowerUpperAlphabetTestData &data = kIsLowerUpperAlphabetTestData[i]; |
| SCOPED_TRACE(data.key); |
| KeyEvent key_event; |
| KeyParser::ParseKey(data.key, &key_event); |
| EXPECT_EQ(data.is_lower, KeyEventUtil::IsLowerAlphabet(key_event)); |
| EXPECT_EQ(data.is_upper, KeyEventUtil::IsUpperAlphabet(key_event)); |
| } |
| } |
| |
| TEST(KeyEventUtilTest, IsNumpadKey) { |
| const struct IsNumpadKeyTestData { |
| const char *key; |
| bool is_numpad_key; |
| } kIsNumpadKeyTestData[] = { |
| { "a", false }, |
| { "A", false }, |
| { "Shift", false }, |
| { "Shift a", false }, |
| { "0", false }, |
| { "EISU", false }, |
| { "NUMPAD0", true }, |
| { "NUMPAD9", true }, |
| { "MULTIPLY", true }, |
| { "EQUALS", true }, |
| { "COMMA", true }, |
| { "TEXTINPUT", false }, |
| }; |
| |
| for (size_t i = 0; i < arraysize(kIsNumpadKeyTestData); ++i) { |
| const IsNumpadKeyTestData &data = kIsNumpadKeyTestData[i]; |
| SCOPED_TRACE(data.key); |
| KeyEvent key_event; |
| KeyParser::ParseKey(data.key, &key_event); |
| EXPECT_EQ(data.is_numpad_key, KeyEventUtil::IsNumpadKey(key_event)); |
| } |
| } |
| |
| } // namespace mozc |