Home | History | Annotate | Download | only in chromedriver
      1 // Copyright (c) 2013 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 <list>
      6 #include <string>
      7 
      8 #include "base/strings/string16.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "chrome/test/chromedriver/chrome/status.h"
     11 #include "chrome/test/chromedriver/chrome/ui_events.h"
     12 #include "chrome/test/chromedriver/key_converter.h"
     13 #include "chrome/test/chromedriver/test_util.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace {
     17 
     18 void CheckEvents(const base::string16& keys,
     19                  KeyEvent expected_events[],
     20                  bool release_modifiers,
     21                  size_t expected_size,
     22                  int expected_modifiers) {
     23   int modifiers = 0;
     24   std::list<KeyEvent> events;
     25   EXPECT_EQ(kOk, ConvertKeysToKeyEvents(keys, release_modifiers,
     26                                         &modifiers, &events).code());
     27   EXPECT_EQ(expected_size, events.size());
     28   size_t i = 0;
     29   std::list<KeyEvent>::const_iterator it = events.begin();
     30   while (i < expected_size && it != events.end()) {
     31     EXPECT_EQ(expected_events[i].type, it->type);
     32     EXPECT_EQ(expected_events[i].modifiers, it->modifiers);
     33     EXPECT_EQ(expected_events[i].modified_text, it->modified_text);
     34     EXPECT_EQ(expected_events[i].unmodified_text, it->unmodified_text);
     35     EXPECT_EQ(expected_events[i].key_code, it->key_code);
     36 
     37     ++i;
     38     ++it;
     39   }
     40   EXPECT_EQ(expected_modifiers, modifiers);
     41 }
     42 
     43 void CheckEventsReleaseModifiers(const base::string16& keys,
     44                                  KeyEvent expected_events[],
     45                                  size_t expected_size) {
     46   CheckEvents(keys, expected_events, true /* release_modifier */,
     47       expected_size, 0 /* expected_modifiers */);
     48 }
     49 
     50 void CheckEventsReleaseModifiers(const std::string& keys,
     51                                  KeyEvent expected_events[],
     52                                  size_t expected_size) {
     53   CheckEventsReleaseModifiers(base::UTF8ToUTF16(keys),
     54       expected_events, expected_size);
     55 }
     56 
     57 void CheckNonShiftChar(ui::KeyboardCode key_code, char character) {
     58   int modifiers = 0;
     59   std::string char_string;
     60   char_string.push_back(character);
     61   std::list<KeyEvent> events;
     62   EXPECT_EQ(kOk, ConvertKeysToKeyEvents(base::ASCIIToUTF16(char_string),
     63                                         true /* release_modifiers*/,
     64                                         &modifiers, &events).code());
     65   ASSERT_EQ(3u, events.size()) << "Char: " << character;
     66   std::list<KeyEvent>::const_iterator it = events.begin();
     67   EXPECT_EQ(key_code, it->key_code) << "Char: " << character;
     68   ++it;  // Move to the second event.
     69   ASSERT_EQ(1u, it->modified_text.length()) << "Char: " << character;
     70   ASSERT_EQ(1u, it->unmodified_text.length()) << "Char: " << character;
     71   EXPECT_EQ(character, it->modified_text[0]) << "Char: " << character;
     72   EXPECT_EQ(character, it->unmodified_text[0]) << "Char: " << character;
     73   ++it;  // Move to the third event.
     74   EXPECT_EQ(key_code, it->key_code) << "Char: " << character;
     75 }
     76 
     77 void CheckShiftChar(ui::KeyboardCode key_code, char character, char lower) {
     78   int modifiers = 0;
     79   std::string char_string;
     80   char_string.push_back(character);
     81   std::list<KeyEvent> events;
     82   EXPECT_EQ(kOk, ConvertKeysToKeyEvents(base::ASCIIToUTF16(char_string),
     83                                         true /* release_modifiers*/,
     84                                         &modifiers, &events).code());
     85   ASSERT_EQ(5u, events.size()) << "Char: " << character;
     86   std::list<KeyEvent>::const_iterator it = events.begin();
     87   EXPECT_EQ(ui::VKEY_SHIFT, it->key_code) << "Char: " << character;
     88   ++it;  // Move to second event.
     89   EXPECT_EQ(key_code, it->key_code) << "Char: " << character;
     90   ++it;  // Move to third event.
     91   ASSERT_EQ(1u, it->modified_text.length()) << "Char: " << character;
     92   ASSERT_EQ(1u, it->unmodified_text.length()) << "Char: " << character;
     93   EXPECT_EQ(character, it->modified_text[0]) << "Char: " << character;
     94   EXPECT_EQ(lower, it->unmodified_text[0]) << "Char: " << character;
     95   ++it;  // Move to fourth event.
     96   EXPECT_EQ(key_code, it->key_code) << "Char: " << character;
     97   ++it;  // Move to fifth event.
     98   EXPECT_EQ(ui::VKEY_SHIFT, it->key_code) << "Char: " << character;
     99 }
    100 
    101 }  // namespace
    102 
    103 TEST(KeyConverter, SingleChar) {
    104   KeyEvent event_array[] = {
    105       CreateKeyDownEvent(ui::VKEY_H, 0),
    106       CreateCharEvent("h", "h", 0),
    107       CreateKeyUpEvent(ui::VKEY_H, 0)};
    108   CheckEventsReleaseModifiers("h", event_array, arraysize(event_array));
    109 }
    110 
    111 TEST(KeyConverter, SingleNumber) {
    112   KeyEvent event_array[] = {
    113       CreateKeyDownEvent(ui::VKEY_1, 0),
    114       CreateCharEvent("1", "1", 0),
    115       CreateKeyUpEvent(ui::VKEY_1, 0)};
    116   CheckEventsReleaseModifiers("1", event_array, arraysize(event_array));
    117 }
    118 
    119 TEST(KeyConverter, MultipleChars) {
    120   KeyEvent event_array[] = {
    121       CreateKeyDownEvent(ui::VKEY_H, 0),
    122       CreateCharEvent("h", "h", 0),
    123       CreateKeyUpEvent(ui::VKEY_H, 0),
    124       CreateKeyDownEvent(ui::VKEY_E, 0),
    125       CreateCharEvent("e", "e", 0),
    126       CreateKeyUpEvent(ui::VKEY_E, 0),
    127       CreateKeyDownEvent(ui::VKEY_Y, 0),
    128       CreateCharEvent("y", "y", 0),
    129       CreateKeyUpEvent(ui::VKEY_Y, 0)};
    130   CheckEventsReleaseModifiers("hey", event_array, arraysize(event_array));
    131 }
    132 
    133 TEST(KeyConverter, WebDriverSpecialChar) {
    134   KeyEvent event_array[] = {
    135       CreateKeyDownEvent(ui::VKEY_SPACE, 0),
    136       CreateCharEvent(" ", " ", 0),
    137       CreateKeyUpEvent(ui::VKEY_SPACE, 0)};
    138   base::string16 keys;
    139   keys.push_back(static_cast<base::char16>(0xE00DU));
    140   CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array));
    141 }
    142 
    143 TEST(KeyConverter, WebDriverSpecialNonCharKey) {
    144   KeyEvent event_array[] = {
    145       CreateKeyDownEvent(ui::VKEY_F1, 0),
    146       CreateKeyUpEvent(ui::VKEY_F1, 0)};
    147   base::string16 keys;
    148   keys.push_back(static_cast<base::char16>(0xE031U));
    149   CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array));
    150 }
    151 
    152 TEST(KeyConverter, FrenchKeyOnEnglishLayout) {
    153   KeyEvent event_array[] = {
    154       CreateKeyDownEvent(ui::VKEY_UNKNOWN, 0),
    155       CreateCharEvent(base::WideToUTF8(L"\u00E9"),
    156                       base::WideToUTF8(L"\u00E9"), 0),
    157       CreateKeyUpEvent(ui::VKEY_UNKNOWN, 0)};
    158   CheckEventsReleaseModifiers(base::WideToUTF16(L"\u00E9"),
    159       event_array, arraysize(event_array));
    160 }
    161 
    162 #if defined(OS_WIN)
    163 TEST(KeyConverter, NeedsCtrlAndAlt) {
    164   RestoreKeyboardLayoutOnDestruct restore;
    165   int ctrl_and_alt = kControlKeyModifierMask | kAltKeyModifierMask;
    166   KeyEvent event_array[] = {
    167       CreateKeyDownEvent(ui::VKEY_CONTROL, 0),
    168       CreateKeyDownEvent(ui::VKEY_MENU, 0),
    169       CreateKeyDownEvent(ui::VKEY_Q, ctrl_and_alt),
    170       CreateCharEvent("q", "@", ctrl_and_alt),
    171       CreateKeyUpEvent(ui::VKEY_Q, ctrl_and_alt),
    172       CreateKeyUpEvent(ui::VKEY_MENU, 0),
    173       CreateKeyUpEvent(ui::VKEY_CONTROL, 0)};
    174   ASSERT_TRUE(SwitchKeyboardLayout("00000407"));
    175   CheckEventsReleaseModifiers("@", event_array, arraysize(event_array));
    176 }
    177 #endif
    178 
    179 TEST(KeyConverter, UppercaseCharDoesShift) {
    180   KeyEvent event_array[] = {
    181       CreateKeyDownEvent(ui::VKEY_SHIFT, 0),
    182       CreateKeyDownEvent(ui::VKEY_A, kShiftKeyModifierMask),
    183       CreateCharEvent("a", "A", kShiftKeyModifierMask),
    184       CreateKeyUpEvent(ui::VKEY_A, kShiftKeyModifierMask),
    185       CreateKeyUpEvent(ui::VKEY_SHIFT, 0)};
    186   CheckEventsReleaseModifiers("A", event_array, arraysize(event_array));
    187 }
    188 
    189 TEST(KeyConverter, UppercaseSymbolCharDoesShift) {
    190   KeyEvent event_array[] = {
    191       CreateKeyDownEvent(ui::VKEY_SHIFT, 0),
    192       CreateKeyDownEvent(ui::VKEY_1, kShiftKeyModifierMask),
    193       CreateCharEvent("1", "!", kShiftKeyModifierMask),
    194       CreateKeyUpEvent(ui::VKEY_1, kShiftKeyModifierMask),
    195       CreateKeyUpEvent(ui::VKEY_SHIFT, 0)};
    196   CheckEventsReleaseModifiers("!", event_array, arraysize(event_array));
    197 }
    198 
    199 TEST(KeyConverter, UppercaseCharUsesShiftOnlyIfNecessary) {
    200   KeyEvent event_array[] = {
    201       CreateKeyDownEvent(ui::VKEY_SHIFT, kShiftKeyModifierMask),
    202       CreateKeyDownEvent(ui::VKEY_A, kShiftKeyModifierMask),
    203       CreateCharEvent("a", "A", kShiftKeyModifierMask),
    204       CreateKeyUpEvent(ui::VKEY_A, kShiftKeyModifierMask),
    205       CreateKeyDownEvent(ui::VKEY_B, kShiftKeyModifierMask),
    206       CreateCharEvent("b", "B", kShiftKeyModifierMask),
    207       CreateKeyUpEvent(ui::VKEY_B, kShiftKeyModifierMask),
    208       CreateKeyDownEvent(ui::VKEY_C, kShiftKeyModifierMask),
    209       CreateCharEvent("c", "C", kShiftKeyModifierMask),
    210       CreateKeyUpEvent(ui::VKEY_C, kShiftKeyModifierMask),
    211       CreateKeyUpEvent(ui::VKEY_SHIFT, 0)};
    212   base::string16 keys;
    213   keys.push_back(static_cast<base::char16>(0xE008U));
    214   keys.append(base::UTF8ToUTF16("aBc"));
    215   CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array));
    216 }
    217 
    218 TEST(KeyConverter, ToggleModifiers) {
    219   KeyEvent event_array[] = {
    220       CreateKeyDownEvent(ui::VKEY_SHIFT, kShiftKeyModifierMask),
    221       CreateKeyUpEvent(ui::VKEY_SHIFT, 0),
    222       CreateKeyDownEvent(ui::VKEY_CONTROL, kControlKeyModifierMask),
    223       CreateKeyUpEvent(ui::VKEY_CONTROL, 0),
    224       CreateKeyDownEvent(ui::VKEY_MENU, kAltKeyModifierMask),
    225       CreateKeyUpEvent(ui::VKEY_MENU, 0),
    226       CreateKeyDownEvent(ui::VKEY_COMMAND, kMetaKeyModifierMask),
    227       CreateKeyUpEvent(ui::VKEY_COMMAND, 0)};
    228   base::string16 keys;
    229   keys.push_back(static_cast<base::char16>(0xE008U));
    230   keys.push_back(static_cast<base::char16>(0xE008U));
    231   keys.push_back(static_cast<base::char16>(0xE009U));
    232   keys.push_back(static_cast<base::char16>(0xE009U));
    233   keys.push_back(static_cast<base::char16>(0xE00AU));
    234   keys.push_back(static_cast<base::char16>(0xE00AU));
    235   keys.push_back(static_cast<base::char16>(0xE03DU));
    236   keys.push_back(static_cast<base::char16>(0xE03DU));
    237   CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array));
    238 }
    239 
    240 #if defined(OS_WIN)
    241 // https://code.google.com/p/chromedriver/issues/detail?id=546
    242 #define MAYBE_AllShorthandKeys DISABLED_AllShorthandKeys
    243 #else
    244 #define MAYBE_AllShorthandKeys AllShorthandKeys
    245 #endif
    246 
    247 TEST(KeyConverter, MAYBE_AllShorthandKeys) {
    248   KeyEvent event_array[] = {
    249       CreateKeyDownEvent(ui::VKEY_RETURN, 0),
    250       CreateCharEvent("\r", "\r", 0),
    251       CreateKeyUpEvent(ui::VKEY_RETURN, 0),
    252       CreateKeyDownEvent(ui::VKEY_RETURN, 0),
    253       CreateCharEvent("\r", "\r", 0),
    254       CreateKeyUpEvent(ui::VKEY_RETURN, 0),
    255       CreateKeyDownEvent(ui::VKEY_TAB, 0),
    256 #if defined(USE_AURA) || defined(OS_LINUX)
    257       CreateCharEvent("\t", "\t", 0),
    258 #endif
    259       CreateKeyUpEvent(ui::VKEY_TAB, 0),
    260       CreateKeyDownEvent(ui::VKEY_BACK, 0),
    261 #if defined(USE_AURA) || defined(OS_LINUX)
    262       CreateCharEvent("\b", "\b", 0),
    263 #endif
    264       CreateKeyUpEvent(ui::VKEY_BACK, 0),
    265       CreateKeyDownEvent(ui::VKEY_SPACE, 0),
    266       CreateCharEvent(" ", " ", 0),
    267       CreateKeyUpEvent(ui::VKEY_SPACE, 0)};
    268   CheckEventsReleaseModifiers("\n\r\n\t\b ",
    269       event_array,arraysize(event_array));
    270 }
    271 
    272 #if defined(OS_LINUX)
    273 // Fails on bots: crbug.com/174962
    274 #define MAYBE_AllEnglishKeyboardSymbols DISABLED_AllEnglishKeyboardSymbols
    275 #else
    276 #define MAYBE_AllEnglishKeyboardSymbols AllEnglishKeyboardSymbols
    277 #endif
    278 
    279 TEST(KeyConverter, MAYBE_AllEnglishKeyboardSymbols) {
    280   base::string16 keys;
    281   const ui::KeyboardCode kSymbolKeyCodes[] = {
    282       ui::VKEY_OEM_3,
    283       ui::VKEY_OEM_MINUS,
    284       ui::VKEY_OEM_PLUS,
    285       ui::VKEY_OEM_4,
    286       ui::VKEY_OEM_6,
    287       ui::VKEY_OEM_5,
    288       ui::VKEY_OEM_1,
    289       ui::VKEY_OEM_7,
    290       ui::VKEY_OEM_COMMA,
    291       ui::VKEY_OEM_PERIOD,
    292       ui::VKEY_OEM_2};
    293   std::string kLowerSymbols = "`-=[]\\;',./";
    294   std::string kUpperSymbols = "~_+{}|:\"<>?";
    295   for (size_t i = 0; i < kLowerSymbols.length(); ++i)
    296     CheckNonShiftChar(kSymbolKeyCodes[i], kLowerSymbols[i]);
    297   for (size_t i = 0; i < kUpperSymbols.length(); ++i)
    298     CheckShiftChar(kSymbolKeyCodes[i], kUpperSymbols[i], kLowerSymbols[i]);
    299 }
    300 
    301 TEST(KeyConverter, AllEnglishKeyboardTextChars) {
    302   std::string kLowerChars = "0123456789abcdefghijklmnopqrstuvwxyz";
    303   std::string kUpperChars = ")!@#$%^&*(ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    304   for (size_t i = 0; i < kLowerChars.length(); ++i) {
    305     int offset = 0;
    306     if (i < 10)
    307       offset = ui::VKEY_0;
    308     else
    309       offset = ui::VKEY_0 + 7;
    310     ui::KeyboardCode expected_code = static_cast<ui::KeyboardCode>(offset + i);
    311     CheckNonShiftChar(expected_code, kLowerChars[i]);
    312   }
    313   for (size_t i = 0; i < kUpperChars.length(); ++i) {
    314     int offset = 0;
    315     if (i < 10)
    316       offset = ui::VKEY_0;
    317     else
    318       offset = ui::VKEY_0 + 7;
    319     ui::KeyboardCode expected_code = static_cast<ui::KeyboardCode>(offset + i);
    320     CheckShiftChar(expected_code, kUpperChars[i], kLowerChars[i]);
    321   }
    322 }
    323 
    324 #if defined(OS_LINUX) || defined(OS_WIN)
    325 // https://code.google.com/p/chromedriver/issues/detail?id=240
    326 // https://code.google.com/p/chromedriver/issues/detail?id=546
    327 #define MAYBE_AllSpecialWebDriverKeysOnEnglishKeyboard \
    328     DISABLED_AllSpecialWebDriverKeysOnEnglishKeyboard
    329 #else
    330 #define MAYBE_AllSpecialWebDriverKeysOnEnglishKeyboard \
    331     AllSpecialWebDriverKeysOnEnglishKeyboard
    332 #endif
    333 
    334 TEST(KeyConverter, MAYBE_AllSpecialWebDriverKeysOnEnglishKeyboard) {
    335   const char kTextForKeys[] = {
    336 #if defined(USE_AURA) || defined(OS_LINUX)
    337       0, 0, 0, '\b', '\t', 0, '\r', '\r', 0, 0, 0, 0, 0x1B,
    338       ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x7F, ';', '=',
    339 #else
    340       0, 0, 0, 0, 0, 0, '\r', '\r', 0, 0, 0, 0, 0,
    341       ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ';', '=',
    342 #endif
    343       '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    344       '*', '+', ',', '-', '.', '/'};
    345   for (size_t i = 0; i <= 0x3D; ++i) {
    346     if (i > 0x29 && i < 0x31)
    347       continue;
    348     base::string16 keys;
    349     int modifiers = 0;
    350     keys.push_back(0xE000U + i);
    351     std::list<KeyEvent> events;
    352     if (i == 1) {
    353       EXPECT_NE(kOk, ConvertKeysToKeyEvents(keys,
    354                                             true /* release_modifiers*/,
    355                                             &modifiers, &events).code())
    356           << "Index: " << i;
    357       EXPECT_EQ(0u, events.size()) << "Index: " << i;
    358     } else {
    359       EXPECT_EQ(kOk, ConvertKeysToKeyEvents(keys,
    360                                             true /* release_modifiers */,
    361                                             &modifiers, &events).code())
    362           << "Index: " << i;
    363       if (i == 0) {
    364         EXPECT_EQ(0u, events.size()) << "Index: " << i;
    365       } else if (i >= arraysize(kTextForKeys) || kTextForKeys[i] == 0) {
    366         EXPECT_EQ(2u, events.size()) << "Index: " << i;
    367       } else {
    368         ASSERT_EQ(3u, events.size()) << "Index: " << i;
    369         std::list<KeyEvent>::const_iterator it = events.begin();
    370         ++it;  // Move to the second event.
    371         ASSERT_EQ(1u, it->unmodified_text.length()) << "Index: " << i;
    372         EXPECT_EQ(kTextForKeys[i], it->unmodified_text[0])
    373             << "Index: " << i;
    374       }
    375     }
    376   }
    377 }
    378 
    379 TEST(KeyConverter, ModifiersState) {
    380   int shift_key_modifier = kShiftKeyModifierMask;
    381   int control_key_modifier = shift_key_modifier | kControlKeyModifierMask;
    382   int alt_key_modifier = control_key_modifier | kAltKeyModifierMask;
    383   int meta_key_modifier = alt_key_modifier | kMetaKeyModifierMask;
    384   KeyEvent event_array[] = {
    385       CreateKeyDownEvent(ui::VKEY_SHIFT, shift_key_modifier),
    386       CreateKeyDownEvent(ui::VKEY_CONTROL, control_key_modifier),
    387       CreateKeyDownEvent(ui::VKEY_MENU, alt_key_modifier),
    388       CreateKeyDownEvent(ui::VKEY_COMMAND, meta_key_modifier)};
    389   base::string16 keys;
    390   keys.push_back(static_cast<base::char16>(0xE008U));
    391   keys.push_back(static_cast<base::char16>(0xE009U));
    392   keys.push_back(static_cast<base::char16>(0xE00AU));
    393   keys.push_back(static_cast<base::char16>(0xE03DU));
    394 
    395   CheckEvents(keys, event_array, false /* release_modifiers */,
    396       arraysize(event_array), meta_key_modifier);
    397 }
    398 
    399 TEST(KeyConverter, ReleaseModifiers) {
    400   KeyEvent event_array[] = {
    401       CreateKeyDownEvent(ui::VKEY_SHIFT, kShiftKeyModifierMask),
    402       CreateKeyDownEvent(ui::VKEY_CONTROL,
    403           kShiftKeyModifierMask | kControlKeyModifierMask),
    404       CreateKeyUpEvent(ui::VKEY_SHIFT, 0),
    405       CreateKeyUpEvent(ui::VKEY_CONTROL, 0)};
    406   base::string16 keys;
    407   keys.push_back(static_cast<base::char16>(0xE008U));
    408   keys.push_back(static_cast<base::char16>(0xE009U));
    409 
    410   CheckEvents(keys, event_array, true /* release_modifiers */,
    411       arraysize(event_array), 0);
    412 }
    413