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 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 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(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(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(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 string16 keys; 139 keys.push_back(static_cast<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 string16 keys; 148 keys.push_back(static_cast<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(WideToUTF8(L"\u00E9"), WideToUTF8(L"\u00E9"), 0), 156 CreateKeyUpEvent(ui::VKEY_UNKNOWN, 0)}; 157 CheckEventsReleaseModifiers(WideToUTF16(L"\u00E9"), 158 event_array, arraysize(event_array)); 159 } 160 161 #if defined(OS_WIN) 162 TEST(KeyConverter, NeedsCtrlAndAlt) { 163 RestoreKeyboardLayoutOnDestruct restore; 164 int ctrl_and_alt = kControlKeyModifierMask | kAltKeyModifierMask; 165 KeyEvent event_array[] = { 166 CreateKeyDownEvent(ui::VKEY_CONTROL, 0), 167 CreateKeyDownEvent(ui::VKEY_MENU, 0), 168 CreateKeyDownEvent(ui::VKEY_Q, ctrl_and_alt), 169 CreateCharEvent("q", "@", ctrl_and_alt), 170 CreateKeyUpEvent(ui::VKEY_Q, ctrl_and_alt), 171 CreateKeyUpEvent(ui::VKEY_MENU, 0), 172 CreateKeyUpEvent(ui::VKEY_CONTROL, 0)}; 173 ASSERT_TRUE(SwitchKeyboardLayout("00000407")); 174 CheckEventsReleaseModifiers("@", event_array, arraysize(event_array)); 175 } 176 #endif 177 178 TEST(KeyConverter, UppercaseCharDoesShift) { 179 KeyEvent event_array[] = { 180 CreateKeyDownEvent(ui::VKEY_SHIFT, 0), 181 CreateKeyDownEvent(ui::VKEY_A, kShiftKeyModifierMask), 182 CreateCharEvent("a", "A", kShiftKeyModifierMask), 183 CreateKeyUpEvent(ui::VKEY_A, kShiftKeyModifierMask), 184 CreateKeyUpEvent(ui::VKEY_SHIFT, 0)}; 185 CheckEventsReleaseModifiers("A", event_array, arraysize(event_array)); 186 } 187 188 TEST(KeyConverter, UppercaseSymbolCharDoesShift) { 189 KeyEvent event_array[] = { 190 CreateKeyDownEvent(ui::VKEY_SHIFT, 0), 191 CreateKeyDownEvent(ui::VKEY_1, kShiftKeyModifierMask), 192 CreateCharEvent("1", "!", kShiftKeyModifierMask), 193 CreateKeyUpEvent(ui::VKEY_1, kShiftKeyModifierMask), 194 CreateKeyUpEvent(ui::VKEY_SHIFT, 0)}; 195 CheckEventsReleaseModifiers("!", event_array, arraysize(event_array)); 196 } 197 198 TEST(KeyConverter, UppercaseCharUsesShiftOnlyIfNecessary) { 199 KeyEvent event_array[] = { 200 CreateKeyDownEvent(ui::VKEY_SHIFT, kShiftKeyModifierMask), 201 CreateKeyDownEvent(ui::VKEY_A, kShiftKeyModifierMask), 202 CreateCharEvent("a", "A", kShiftKeyModifierMask), 203 CreateKeyUpEvent(ui::VKEY_A, kShiftKeyModifierMask), 204 CreateKeyDownEvent(ui::VKEY_B, kShiftKeyModifierMask), 205 CreateCharEvent("b", "B", kShiftKeyModifierMask), 206 CreateKeyUpEvent(ui::VKEY_B, kShiftKeyModifierMask), 207 CreateKeyDownEvent(ui::VKEY_C, kShiftKeyModifierMask), 208 CreateCharEvent("c", "C", kShiftKeyModifierMask), 209 CreateKeyUpEvent(ui::VKEY_C, kShiftKeyModifierMask), 210 CreateKeyUpEvent(ui::VKEY_SHIFT, 0)}; 211 string16 keys; 212 keys.push_back(static_cast<char16>(0xE008U)); 213 keys.append(UTF8ToUTF16("aBc")); 214 CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array)); 215 } 216 217 TEST(KeyConverter, ToggleModifiers) { 218 KeyEvent event_array[] = { 219 CreateKeyDownEvent(ui::VKEY_SHIFT, kShiftKeyModifierMask), 220 CreateKeyUpEvent(ui::VKEY_SHIFT, 0), 221 CreateKeyDownEvent(ui::VKEY_CONTROL, kControlKeyModifierMask), 222 CreateKeyUpEvent(ui::VKEY_CONTROL, 0), 223 CreateKeyDownEvent(ui::VKEY_MENU, kAltKeyModifierMask), 224 CreateKeyUpEvent(ui::VKEY_MENU, 0), 225 CreateKeyDownEvent(ui::VKEY_COMMAND, kMetaKeyModifierMask), 226 CreateKeyUpEvent(ui::VKEY_COMMAND, 0)}; 227 string16 keys; 228 keys.push_back(static_cast<char16>(0xE008U)); 229 keys.push_back(static_cast<char16>(0xE008U)); 230 keys.push_back(static_cast<char16>(0xE009U)); 231 keys.push_back(static_cast<char16>(0xE009U)); 232 keys.push_back(static_cast<char16>(0xE00AU)); 233 keys.push_back(static_cast<char16>(0xE00AU)); 234 keys.push_back(static_cast<char16>(0xE03DU)); 235 keys.push_back(static_cast<char16>(0xE03DU)); 236 CheckEventsReleaseModifiers(keys, event_array, arraysize(event_array)); 237 } 238 239 TEST(KeyConverter, AllShorthandKeys) { 240 KeyEvent event_array[] = { 241 CreateKeyDownEvent(ui::VKEY_RETURN, 0), 242 CreateCharEvent("\r", "\r", 0), 243 CreateKeyUpEvent(ui::VKEY_RETURN, 0), 244 CreateKeyDownEvent(ui::VKEY_RETURN, 0), 245 CreateCharEvent("\r", "\r", 0), 246 CreateKeyUpEvent(ui::VKEY_RETURN, 0), 247 CreateKeyDownEvent(ui::VKEY_TAB, 0), 248 #if defined(USE_AURA) || defined(OS_LINUX) 249 CreateCharEvent("\t", "\t", 0), 250 #endif 251 CreateKeyUpEvent(ui::VKEY_TAB, 0), 252 CreateKeyDownEvent(ui::VKEY_BACK, 0), 253 #if defined(USE_AURA) || defined(OS_LINUX) 254 CreateCharEvent("\b", "\b", 0), 255 #endif 256 CreateKeyUpEvent(ui::VKEY_BACK, 0), 257 CreateKeyDownEvent(ui::VKEY_SPACE, 0), 258 CreateCharEvent(" ", " ", 0), 259 CreateKeyUpEvent(ui::VKEY_SPACE, 0)}; 260 CheckEventsReleaseModifiers("\n\r\n\t\b ", 261 event_array,arraysize(event_array)); 262 } 263 264 #if defined(OS_LINUX) 265 // Fails on bots: crbug.com/174962 266 #define MAYBE_AllEnglishKeyboardSymbols DISABLED_AllEnglishKeyboardSymbols 267 #else 268 #define MAYBE_AllEnglishKeyboardSymbols AllEnglishKeyboardSymbols 269 #endif 270 271 TEST(KeyConverter, MAYBE_AllEnglishKeyboardSymbols) { 272 string16 keys; 273 const ui::KeyboardCode kSymbolKeyCodes[] = { 274 ui::VKEY_OEM_3, 275 ui::VKEY_OEM_MINUS, 276 ui::VKEY_OEM_PLUS, 277 ui::VKEY_OEM_4, 278 ui::VKEY_OEM_6, 279 ui::VKEY_OEM_5, 280 ui::VKEY_OEM_1, 281 ui::VKEY_OEM_7, 282 ui::VKEY_OEM_COMMA, 283 ui::VKEY_OEM_PERIOD, 284 ui::VKEY_OEM_2}; 285 std::string kLowerSymbols = "`-=[]\\;',./"; 286 std::string kUpperSymbols = "~_+{}|:\"<>?"; 287 for (size_t i = 0; i < kLowerSymbols.length(); ++i) 288 CheckNonShiftChar(kSymbolKeyCodes[i], kLowerSymbols[i]); 289 for (size_t i = 0; i < kUpperSymbols.length(); ++i) 290 CheckShiftChar(kSymbolKeyCodes[i], kUpperSymbols[i], kLowerSymbols[i]); 291 } 292 293 TEST(KeyConverter, AllEnglishKeyboardTextChars) { 294 std::string kLowerChars = "0123456789abcdefghijklmnopqrstuvwxyz"; 295 std::string kUpperChars = ")!@#$%^&*(ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 296 for (size_t i = 0; i < kLowerChars.length(); ++i) { 297 int offset = 0; 298 if (i < 10) 299 offset = ui::VKEY_0; 300 else 301 offset = ui::VKEY_0 + 7; 302 ui::KeyboardCode expected_code = static_cast<ui::KeyboardCode>(offset + i); 303 CheckNonShiftChar(expected_code, kLowerChars[i]); 304 } 305 for (size_t i = 0; i < kUpperChars.length(); ++i) { 306 int offset = 0; 307 if (i < 10) 308 offset = ui::VKEY_0; 309 else 310 offset = ui::VKEY_0 + 7; 311 ui::KeyboardCode expected_code = static_cast<ui::KeyboardCode>(offset + i); 312 CheckShiftChar(expected_code, kUpperChars[i], kLowerChars[i]); 313 } 314 } 315 316 #if defined(OS_LINUX) 317 // Fails on bots: crbug.com/174962 318 #define MAYBE_AllSpecialWebDriverKeysOnEnglishKeyboard \ 319 DISABLED_AllSpecialWebDriverKeysOnEnglishKeyboard 320 #else 321 #define MAYBE_AllSpecialWebDriverKeysOnEnglishKeyboard \ 322 AllSpecialWebDriverKeysOnEnglishKeyboard 323 #endif 324 325 TEST(KeyConverter, MAYBE_AllSpecialWebDriverKeysOnEnglishKeyboard) { 326 const char kTextForKeys[] = { 327 #if defined(USE_AURA) || defined(OS_LINUX) 328 0, 0, 0, '\b', '\t', 0, '\r', '\r', 0, 0, 0, 0, 0x1B, 329 ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x7F, ';', '=', 330 #else 331 0, 0, 0, 0, 0, 0, '\r', '\r', 0, 0, 0, 0, 0, 332 ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ';', '=', 333 #endif 334 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 335 '*', '+', ',', '-', '.', '/'}; 336 for (size_t i = 0; i <= 0x3D; ++i) { 337 if (i > 0x29 && i < 0x31) 338 continue; 339 string16 keys; 340 int modifiers = 0; 341 keys.push_back(0xE000U + i); 342 std::list<KeyEvent> events; 343 if (i == 1) { 344 EXPECT_NE(kOk, ConvertKeysToKeyEvents(keys, 345 true /* release_modifiers*/, 346 &modifiers, &events).code()) 347 << "Index: " << i; 348 EXPECT_EQ(0u, events.size()) << "Index: " << i; 349 } else { 350 EXPECT_EQ(kOk, ConvertKeysToKeyEvents(keys, 351 true /* release_modifiers */, 352 &modifiers, &events).code()) 353 << "Index: " << i; 354 if (i == 0) { 355 EXPECT_EQ(0u, events.size()) << "Index: " << i; 356 } else if (i >= arraysize(kTextForKeys) || kTextForKeys[i] == 0) { 357 EXPECT_EQ(2u, events.size()) << "Index: " << i; 358 } else { 359 ASSERT_EQ(3u, events.size()) << "Index: " << i; 360 std::list<KeyEvent>::const_iterator it = events.begin(); 361 ++it; // Move to the second event. 362 ASSERT_EQ(1u, it->unmodified_text.length()) << "Index: " << i; 363 EXPECT_EQ(kTextForKeys[i], it->unmodified_text[0]) 364 << "Index: " << i; 365 } 366 } 367 } 368 } 369 370 TEST(KeyConverter, ModifiersState) { 371 int shift_key_modifier = kShiftKeyModifierMask; 372 int control_key_modifier = shift_key_modifier | kControlKeyModifierMask; 373 int alt_key_modifier = control_key_modifier | kAltKeyModifierMask; 374 int meta_key_modifier = alt_key_modifier | kMetaKeyModifierMask; 375 KeyEvent event_array[] = { 376 CreateKeyDownEvent(ui::VKEY_SHIFT, shift_key_modifier), 377 CreateKeyDownEvent(ui::VKEY_CONTROL, control_key_modifier), 378 CreateKeyDownEvent(ui::VKEY_MENU, alt_key_modifier), 379 CreateKeyDownEvent(ui::VKEY_COMMAND, meta_key_modifier)}; 380 string16 keys; 381 keys.push_back(static_cast<char16>(0xE008U)); 382 keys.push_back(static_cast<char16>(0xE009U)); 383 keys.push_back(static_cast<char16>(0xE00AU)); 384 keys.push_back(static_cast<char16>(0xE03DU)); 385 386 CheckEvents(keys, event_array, false /* release_modifiers */, 387 arraysize(event_array), meta_key_modifier); 388 } 389 390 TEST(KeyConverter, ReleaseModifiers) { 391 KeyEvent event_array[] = { 392 CreateKeyDownEvent(ui::VKEY_SHIFT, kShiftKeyModifierMask), 393 CreateKeyDownEvent(ui::VKEY_CONTROL, 394 kShiftKeyModifierMask | kControlKeyModifierMask), 395 CreateKeyUpEvent(ui::VKEY_SHIFT, 0), 396 CreateKeyUpEvent(ui::VKEY_CONTROL, 0)}; 397 string16 keys; 398 keys.push_back(static_cast<char16>(0xE008U)); 399 keys.push_back(static_cast<char16>(0xE009U)); 400 401 CheckEvents(keys, event_array, true /* release_modifiers */, 402 arraysize(event_array), 0); 403 } 404