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
16namespace {
17
18void 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
43void 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
50void 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
57void 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
77void 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
103TEST(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
111TEST(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
119TEST(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
133TEST(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
143TEST(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
152TEST(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)
163TEST(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
179TEST(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
189TEST(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
199TEST(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
218TEST(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
247TEST(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
279TEST(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
301TEST(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
334TEST(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
379TEST(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
399TEST(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