1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include "composer/key_event_util.h"
31
32 #include <string>
33
34 #include "base/util.h"
35 #include "composer/key_parser.h"
36 #include "protocol/commands.pb.h"
37 #include "testing/base/public/gunit.h"
38
39 namespace mozc {
40 using commands::KeyEvent;
41
42 namespace {
CompareKeyEvent(const char * expected_expr,const char * actual_expr,const KeyEvent & expected,const KeyEvent & actual)43 ::testing::AssertionResult CompareKeyEvent(const char *expected_expr,
44 const char *actual_expr,
45 const KeyEvent &expected,
46 const KeyEvent &actual) {
47 { // Key code
48 const int expected_key_code =
49 (expected.has_key_code()) ? expected.key_code() : -1;
50 const int actual_key_code =
51 (actual.has_key_code()) ? actual.key_code() : -1;
52 if (expected_key_code != actual_key_code) {
53 const string expected_value = (expected_key_code == -1)
54 ? "None"
55 : Util::StringPrintf("%c (%d)", expected_key_code, expected_key_code);
56 const string actual_value = (actual_key_code == -1)
57 ? string("None")
58 : Util::StringPrintf("%c (%d)", actual_key_code, actual_key_code);
59 return ::testing::AssertionFailure() <<
60 "Key codes are not same\n" <<
61 "Expected: " << expected_value << "\n" <<
62 "Actual : " << actual_value;
63 }
64 }
65
66 { // Special key
67 const int expected_special_key =
68 (expected.has_special_key()) ? expected.special_key() : -1;
69 const int actual_special_key =
70 (actual.has_special_key()) ? actual.special_key() : -1;
71 if (expected_special_key != actual_special_key) {
72 const string expected_value = (expected_special_key == -1)
73 ? "None" : std::to_string(expected_special_key);
74 const string actual_value = (actual_special_key == -1)
75 ? "None" : std::to_string(actual_special_key);
76 return ::testing::AssertionFailure() <<
77 "Special keys are not same\n" <<
78 "Expected: " << expected_value << "\n" <<
79 "Actual : " << actual_value;
80 }
81 }
82
83 { // Modifier keys
84 const int expected_modifier_keys = KeyEventUtil::GetModifiers(expected);
85 const int actual_modifier_keys = KeyEventUtil::GetModifiers(actual);
86 if (expected_modifier_keys != actual_modifier_keys) {
87 return ::testing::AssertionFailure() <<
88 "Modifier keys are not same\n" <<
89 "Expected: " << expected_modifier_keys << "\n" <<
90 "Actual : " << actual_modifier_keys;
91 }
92 }
93
94 return ::testing::AssertionSuccess();
95 }
96
97 #define EXPECT_EQ_KEY_EVENT(expected, actual) \
98 EXPECT_PRED_FORMAT2(CompareKeyEvent, expected, actual)
99 } // namespace
100
TEST(KeyEventUtilTest,GetModifiers)101 TEST(KeyEventUtilTest, GetModifiers) {
102 KeyEvent key_event;
103
104 KeyParser::ParseKey("a", &key_event);
105 EXPECT_EQ(0, KeyEventUtil::GetModifiers(key_event));
106
107 KeyParser::ParseKey("Alt", &key_event);
108 EXPECT_EQ(KeyEvent::ALT, KeyEventUtil::GetModifiers(key_event));
109
110 KeyParser::ParseKey("Ctrl", &key_event);
111 EXPECT_EQ(KeyEvent::CTRL, KeyEventUtil::GetModifiers(key_event));
112
113 KeyParser::ParseKey("Shift", &key_event);
114 EXPECT_EQ(KeyEvent::SHIFT, KeyEventUtil::GetModifiers(key_event));
115
116 KeyParser::ParseKey("Caps", &key_event);
117 EXPECT_EQ(KeyEvent::CAPS, KeyEventUtil::GetModifiers(key_event));
118
119 KeyParser::ParseKey("LeftAlt RightAlt", &key_event);
120 EXPECT_EQ((KeyEvent::ALT | KeyEvent::LEFT_ALT | KeyEvent::RIGHT_ALT),
121 KeyEventUtil::GetModifiers(key_event));
122
123 KeyParser::ParseKey("LeftAlt Ctrl RightShift", &key_event);
124 EXPECT_EQ((KeyEvent::ALT | KeyEvent::LEFT_ALT | KeyEvent::CTRL |
125 KeyEvent::SHIFT | KeyEvent::RIGHT_SHIFT),
126 KeyEventUtil::GetModifiers(key_event));
127 }
128
TEST(KeyEventUtilTest,GetKeyInformation)129 TEST(KeyEventUtilTest, GetKeyInformation) {
130 const char *kTestKeys[] = {
131 "a",
132 "Space",
133 "Shift",
134 "Shift a",
135 "Shift Space",
136 "Space a",
137 "LeftShift Space a",
138 };
139
140 KeyEvent key_event;
141 uint64 output;
142
143 for (size_t i = 0; i < arraysize(kTestKeys); ++i) {
144 SCOPED_TRACE(kTestKeys[i]);
145 KeyParser::ParseKey(kTestKeys[i], &key_event);
146 ASSERT_TRUE(KeyEventUtil::GetKeyInformation(key_event, &output));
147
148 uint64 expected = 0;
149 if (key_event.has_key_code()) {
150 expected |= static_cast<uint64>(key_event.key_code());
151 }
152 if (key_event.has_special_key()) {
153 expected |= static_cast<uint64>(key_event.special_key()) << 32;
154 }
155 expected |=
156 static_cast<uint64>(KeyEventUtil::GetModifiers(key_event)) << 48;
157
158 EXPECT_EQ(expected, output);
159 }
160
161 const uint32 kEscapeKeyCode = 27;
162 key_event.Clear();
163 key_event.set_key_code(kEscapeKeyCode);
164 // Escape key should not set on key_code field.
165 EXPECT_FALSE(KeyEventUtil::GetKeyInformation(key_event, &output));
166 }
167
TEST(KeyEventUtilTest,NormalizeModifiers)168 TEST(KeyEventUtilTest, NormalizeModifiers) {
169 KeyEvent key_event;
170 KeyEvent normalized_key_event;
171
172 { // Removes caps
173 KeyParser::ParseKey("CAPS H", &key_event);
174 ASSERT_EQ(1, key_event.modifier_keys_size());
175 ASSERT_EQ(KeyEvent::CAPS, KeyEventUtil::GetModifiers(key_event));
176 ASSERT_EQ('H', key_event.key_code());
177
178 KeyEventUtil::NormalizeModifiers(key_event, &normalized_key_event);
179 EXPECT_EQ(0, normalized_key_event.modifier_keys_size());
180 EXPECT_EQ('h', normalized_key_event.key_code());
181 }
182
183 { // Removes left_shift
184 KeyParser::ParseKey("LeftShift", &key_event);
185 ASSERT_EQ(2, key_event.modifier_keys_size());
186 ASSERT_EQ((KeyEvent::SHIFT | KeyEvent::LEFT_SHIFT),
187 KeyEventUtil::GetModifiers(key_event));
188
189 KeyEventUtil::NormalizeModifiers(key_event, &normalized_key_event);
190 EXPECT_EQ(1, normalized_key_event.modifier_keys_size());
191 ASSERT_EQ(KeyEvent::SHIFT,
192 KeyEventUtil::GetModifiers(normalized_key_event));
193 }
194
195 { // Removes caps and left_shift
196 KeyParser::ParseKey("CAPS LeftShift H", &key_event);
197 ASSERT_EQ(3, key_event.modifier_keys_size());
198 ASSERT_EQ((KeyEvent::CAPS | KeyEvent::SHIFT | KeyEvent::LEFT_SHIFT),
199 KeyEventUtil::GetModifiers(key_event));
200
201 ASSERT_EQ('H', key_event.key_code());
202
203 KeyEventUtil::NormalizeModifiers(key_event, &normalized_key_event);
204 EXPECT_EQ(1, normalized_key_event.modifier_keys_size());
205 EXPECT_EQ(KeyEvent::SHIFT,
206 KeyEventUtil::GetModifiers(normalized_key_event));
207 EXPECT_EQ('h', normalized_key_event.key_code());
208 }
209 }
210
TEST(KeyEventUtilTest,NormalizeNumpadKey)211 TEST(KeyEventUtilTest, NormalizeNumpadKey) {
212 const struct NormalizeNumpadKeyTestData {
213 const char *from;
214 const char *to;
215 } kNormalizeNumpadKeyTestData[] = {
216 { "a", "a" },
217 { "Shift", "Shift" },
218 { "Caps", "Caps" },
219 { "Enter", "Enter" },
220 { "Shift Caps a", "Shift Caps a" },
221 { "NUMPAD0", "0" },
222 { "NUMPAD9", "9" },
223 { "MULTIPLY", "*" },
224 { "SEPARATOR", "Enter" },
225 { "EQUALS", "=" },
226 { "Ctrl NUMPAD0", "Ctrl 0" },
227 { "NUMPAD0 a", "0" },
228 };
229
230 for (size_t i = 0; i < arraysize(kNormalizeNumpadKeyTestData); ++i) {
231 const NormalizeNumpadKeyTestData &data = kNormalizeNumpadKeyTestData[i];
232 SCOPED_TRACE(data.from);
233
234 KeyEvent key_event_from, key_event_to, key_event_normalized;
235 KeyParser::ParseKey(data.from, &key_event_from);
236 KeyParser::ParseKey(data.to, &key_event_to);
237 KeyEventUtil::NormalizeNumpadKey(key_event_from, &key_event_normalized);
238 EXPECT_EQ_KEY_EVENT(key_event_to, key_event_normalized);
239 }
240 }
241
TEST(KeyEventUtilTest,MaybeGetKeyStub)242 TEST(KeyEventUtilTest, MaybeGetKeyStub) {
243 KeyEvent key_event;
244 KeyInformation key;
245
246 KeyParser::ParseKey("Shift", &key_event);
247 EXPECT_FALSE(KeyEventUtil::MaybeGetKeyStub(key_event, &key));
248
249 KeyParser::ParseKey("Space", &key_event);
250 EXPECT_FALSE(KeyEventUtil::MaybeGetKeyStub(key_event, &key));
251
252 const uint32 kEscapeKeyCode = 27;
253 key_event.Clear();
254 key_event.set_key_code(kEscapeKeyCode);
255 EXPECT_FALSE(KeyEventUtil::MaybeGetKeyStub(key_event, &key));
256
257 KeyParser::ParseKey("a", &key_event);
258 EXPECT_TRUE(KeyEventUtil::MaybeGetKeyStub(key_event, &key));
259 EXPECT_EQ(static_cast<KeyInformation>(KeyEvent::TEXT_INPUT) << 32, key);
260 }
261
TEST(KeyEventUtilTest,RemvoeModifiers)262 TEST(KeyEventUtilTest, RemvoeModifiers) {
263 const struct RemoveModifiersTestData {
264 const char *input;
265 const char *remove;
266 const char *output;
267 } kRemoveModifiersTestData[] = {
268 {
269 "",
270 "",
271 "",
272 }, {
273 "Ctrl Shift LeftAlt Caps",
274 "Ctrl Shift LeftAlt Caps",
275 "",
276 }, {
277 "Ctrl Shift LeftAlt Caps",
278 "Shift Caps",
279 "Ctrl LeftAlt",
280 }, {
281 "Ctrl Shift LeftAlt Caps",
282 "Alt",
283 "Ctrl Shift Caps",
284 }, {
285 "",
286 "Ctrl Shift LeftAlt Caps",
287 "",
288 },
289 };
290
291 for (size_t i = 0; i < arraysize(kRemoveModifiersTestData); ++i) {
292 SCOPED_TRACE(Util::StringPrintf("index = %d", static_cast<int>(i)));
293 const RemoveModifiersTestData &data = kRemoveModifiersTestData[i];
294
295 KeyEvent input, remove, output;
296 KeyParser::ParseKey(data.input, &input);
297 KeyParser::ParseKey(data.remove, &remove);
298 KeyParser::ParseKey(data.output, &output);
299 const uint32 remove_modifiers = KeyEventUtil::GetModifiers(remove);
300
301 KeyEvent removed_key_event;
302 KeyEventUtil::RemoveModifiers(input, remove_modifiers, &removed_key_event);
303 EXPECT_EQ_KEY_EVENT(output, removed_key_event);
304 }
305 }
306
TEST(KeyEventUtilTest,HasModifiers)307 TEST(KeyEventUtilTest, HasModifiers) {
308 EXPECT_TRUE(KeyEventUtil::HasAlt(KeyEvent::ALT));
309 EXPECT_TRUE(KeyEventUtil::HasAlt(KeyEvent::LEFT_ALT));
310 EXPECT_TRUE(KeyEventUtil::HasAlt(KeyEvent::ALT | KeyEvent::CTRL));
311 EXPECT_FALSE(KeyEventUtil::HasAlt(0));
312 EXPECT_FALSE(KeyEventUtil::HasAlt(KeyEvent::CTRL));
313 EXPECT_FALSE(KeyEventUtil::HasAlt(KeyEvent::SHIFT));
314
315 EXPECT_TRUE(KeyEventUtil::HasCtrl(KeyEvent::CTRL));
316 EXPECT_TRUE(KeyEventUtil::HasCtrl(KeyEvent::LEFT_CTRL));
317 EXPECT_TRUE(KeyEventUtil::HasCtrl(KeyEvent::CTRL | KeyEvent::SHIFT));
318 EXPECT_FALSE(KeyEventUtil::HasCtrl(0));
319 EXPECT_FALSE(KeyEventUtil::HasCtrl(KeyEvent::ALT));
320 EXPECT_FALSE(KeyEventUtil::HasCtrl(KeyEvent::SHIFT));
321
322 EXPECT_TRUE(KeyEventUtil::HasShift(KeyEvent::SHIFT));
323 EXPECT_TRUE(KeyEventUtil::HasShift(KeyEvent::LEFT_SHIFT));
324 EXPECT_TRUE(KeyEventUtil::HasShift(KeyEvent::SHIFT | KeyEvent::ALT));
325 EXPECT_FALSE(KeyEventUtil::HasShift(0));
326 EXPECT_FALSE(KeyEventUtil::HasShift(KeyEvent::ALT));
327 EXPECT_FALSE(KeyEventUtil::HasShift(KeyEvent::CTRL));
328
329 EXPECT_TRUE(KeyEventUtil::HasCaps(KeyEvent::CAPS));
330 EXPECT_TRUE(KeyEventUtil::HasCaps(KeyEvent::CAPS | KeyEvent::ALT));
331 EXPECT_FALSE(KeyEventUtil::HasCaps(0));
332 EXPECT_FALSE(KeyEventUtil::HasCaps(KeyEvent::CTRL));
333 }
334
TEST(KeyEventUtilTest,IsModifiers)335 TEST(KeyEventUtilTest, IsModifiers) {
336 const struct IsModifiersTestData {
337 uint32 modifiers;
338 bool is_alt;
339 bool is_ctrl;
340 bool is_shift;
341 bool is_alt_ctrl;
342 bool is_alt_shift;
343 bool is_ctrl_shift;
344 bool is_alt_ctrl_shift;
345 } kIsModifiersTestData[] = {
346 {
347 0,
348 false, false, false, false, false, false, false
349 }, {
350 KeyEvent::ALT,
351 true, false, false, false, false, false, false,
352 }, {
353 KeyEvent::CTRL,
354 false, true, false, false, false, false, false,
355 }, {
356 KeyEvent::SHIFT,
357 false, false, true, false, false, false, false,
358 }, {
359 KeyEvent::ALT | KeyEvent::CTRL,
360 false, false, false, true, false, false, false,
361 }, {
362 KeyEvent::ALT | KeyEvent::SHIFT,
363 false, false, false, false, true, false, false,
364 }, {
365 KeyEvent::CTRL | KeyEvent::SHIFT,
366 false, false, false, false, false, true, false,
367 }, {
368 KeyEvent::ALT | KeyEvent::CTRL | KeyEvent::SHIFT,
369 false, false, false, false, false, false, true,
370 }, {
371 KeyEvent::LEFT_ALT,
372 true, false, false, false, false, false, false,
373 }, {
374 KeyEvent::ALT | KeyEvent::LEFT_ALT | KeyEvent::RIGHT_ALT,
375 true, false, false, false, false, false, false,
376 }, {
377 KeyEvent::CAPS,
378 false, false, false, false, false, false, false,
379 }, {
380 KeyEvent::ALT | KeyEvent::CAPS,
381 true, false, false, false, false, false, false,
382 },
383 };
384
385 for (size_t i = 0; i < arraysize(kIsModifiersTestData); ++i) {
386 const IsModifiersTestData &data = kIsModifiersTestData[i];
387 SCOPED_TRACE(Util::StringPrintf("index: %d", static_cast<int>(i)));
388
389 EXPECT_EQ(data.is_alt, KeyEventUtil::IsAlt(data.modifiers));
390 EXPECT_EQ(data.is_ctrl, KeyEventUtil::IsCtrl(data.modifiers));
391 EXPECT_EQ(data.is_shift, KeyEventUtil::IsShift(data.modifiers));
392 EXPECT_EQ(data.is_alt_ctrl, KeyEventUtil::IsAltCtrl(data.modifiers));
393 EXPECT_EQ(data.is_alt_shift, KeyEventUtil::IsAltShift(data.modifiers));
394 EXPECT_EQ(data.is_ctrl_shift, KeyEventUtil::IsCtrlShift(data.modifiers));
395 EXPECT_EQ(data.is_alt_ctrl_shift,
396 KeyEventUtil::IsAltCtrlShift(data.modifiers));
397 }
398 }
399
TEST(KeyEventUtilTest,IsLowerUpperAlphabet)400 TEST(KeyEventUtilTest, IsLowerUpperAlphabet) {
401 const struct IsLowerUpperAlphabetTestData {
402 const char *key;
403 bool is_lower;
404 bool is_upper;
405 } kIsLowerUpperAlphabetTestData[] = {
406 { "a", true, false },
407 { "A", false, true },
408 { "Shift a", false, true },
409 { "Shift A", true, false },
410 { "Shift Caps a", true, false },
411 { "Shift Caps A", false, true },
412 { "0", false, false },
413 { "Shift", false, false },
414 { "Caps", false, false },
415 { "Space", false, false },
416 };
417
418 for (size_t i = 0; i < arraysize(kIsLowerUpperAlphabetTestData); ++i) {
419 const IsLowerUpperAlphabetTestData &data = kIsLowerUpperAlphabetTestData[i];
420 SCOPED_TRACE(data.key);
421 KeyEvent key_event;
422 KeyParser::ParseKey(data.key, &key_event);
423 EXPECT_EQ(data.is_lower, KeyEventUtil::IsLowerAlphabet(key_event));
424 EXPECT_EQ(data.is_upper, KeyEventUtil::IsUpperAlphabet(key_event));
425 }
426 }
427
TEST(KeyEventUtilTest,IsNumpadKey)428 TEST(KeyEventUtilTest, IsNumpadKey) {
429 const struct IsNumpadKeyTestData {
430 const char *key;
431 bool is_numpad_key;
432 } kIsNumpadKeyTestData[] = {
433 { "a", false },
434 { "A", false },
435 { "Shift", false },
436 { "Shift a", false },
437 { "0", false },
438 { "EISU", false },
439 { "NUMPAD0", true },
440 { "NUMPAD9", true },
441 { "MULTIPLY", true },
442 { "EQUALS", true },
443 { "COMMA", true },
444 { "TEXTINPUT", false },
445 };
446
447 for (size_t i = 0; i < arraysize(kIsNumpadKeyTestData); ++i) {
448 const IsNumpadKeyTestData &data = kIsNumpadKeyTestData[i];
449 SCOPED_TRACE(data.key);
450 KeyEvent key_event;
451 KeyParser::ParseKey(data.key, &key_event);
452 EXPECT_EQ(data.is_numpad_key, KeyEventUtil::IsNumpadKey(key_event));
453 }
454 }
455
456 } // namespace mozc
457