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