Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / base / ime / chromeos / character_composer_unittest.cc
blob51b585f0eccf7cf233294b0afe680779f568ab03
1 // Copyright 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.
5 #include "ui/base/ime/chromeos/character_composer.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/events/event.h"
11 #include "ui/events/event_constants.h"
12 #include "ui/events/event_utils.h"
13 #include "ui/events/keycodes/dom/dom_code.h"
14 #include "ui/events/keycodes/dom/dom_key.h"
15 #include "ui/events/keycodes/keyboard_code_conversion.h"
16 #include "ui/events/keycodes/keyboard_codes.h"
18 using base::ASCIIToUTF16;
20 namespace ui {
22 namespace {
24 const base::char16 kCombiningGrave = 0x0300;
25 const base::char16 kCombiningAcute = 0x0301;
26 const base::char16 kCombiningCircumflex = 0x0302;
27 const base::char16 kCombiningHorn = 0x031B;
29 } // namespace
31 class CharacterComposerTest : public testing::Test {
32 protected:
33 // Returns a |KeyEvent| for a dead key press.
34 KeyEvent* DeadKeyPress(base::char16 combining_character) const {
35 KeyEvent* event =
36 new KeyEvent(ET_KEY_PRESSED, VKEY_UNKNOWN, DomCode::NONE, EF_NONE,
37 DomKey::DeadKeyFromCombiningCharacter(combining_character),
38 EventTimeForNow());
39 return event;
42 // Expects key is filtered and no character is composed.
43 void ExpectDeadKeyFiltered(base::char16 combining_character) {
44 scoped_ptr<KeyEvent> event(DeadKeyPress(combining_character));
45 EXPECT_TRUE(character_composer_.FilterKeyPress(*event));
46 EXPECT_TRUE(character_composer_.composed_character().empty());
49 // Expects key is filtered and the given character is composed.
50 void ExpectDeadKeyComposed(base::char16 combining_character,
51 const base::string16& expected_character) {
52 scoped_ptr<KeyEvent> event(DeadKeyPress(combining_character));
53 EXPECT_TRUE(character_composer_.FilterKeyPress(*event));
54 EXPECT_EQ(expected_character, character_composer_.composed_character());
57 // Returns a |KeyEvent| for a character key press.
58 KeyEvent* UnicodeKeyPress(KeyboardCode vkey,
59 DomCode code,
60 int flags,
61 base::char16 character) const {
62 KeyEvent* event = new KeyEvent(ET_KEY_PRESSED, vkey, code, flags,
63 DomKey::FromCharacter(character),
64 EventTimeForNow());
65 return event;
68 // Expects key is not filtered and no character is composed.
69 void ExpectUnicodeKeyNotFiltered(KeyboardCode vkey,
70 DomCode code,
71 int flags,
72 base::char16 character) {
73 scoped_ptr<KeyEvent> event(UnicodeKeyPress(vkey, code, flags, character));
74 EXPECT_FALSE(character_composer_.FilterKeyPress(*event));
75 EXPECT_TRUE(character_composer_.composed_character().empty());
78 // Expects key is filtered and no character is composed.
79 void ExpectUnicodeKeyFiltered(KeyboardCode vkey,
80 DomCode code,
81 int flags,
82 base::char16 character) {
83 scoped_ptr<KeyEvent> event(UnicodeKeyPress(vkey, code, flags, character));
84 EXPECT_TRUE(character_composer_.FilterKeyPress(*event));
85 EXPECT_TRUE(character_composer_.composed_character().empty());
88 // Expects key is filtered and the given character is composed.
89 void ExpectUnicodeKeyComposed(KeyboardCode vkey,
90 DomCode code,
91 int flags,
92 base::char16 character,
93 const base::string16& expected_character) {
94 scoped_ptr<KeyEvent> event(UnicodeKeyPress(vkey, code, flags, character));
95 EXPECT_TRUE(character_composer_.FilterKeyPress(*event));
96 EXPECT_EQ(expected_character, character_composer_.composed_character());
99 CharacterComposer character_composer_;
102 TEST_F(CharacterComposerTest, InitialState) {
103 EXPECT_TRUE(character_composer_.composed_character().empty());
106 TEST_F(CharacterComposerTest, NormalKeyIsNotFiltered) {
107 ExpectUnicodeKeyNotFiltered(VKEY_B, DomCode::KEY_B, EF_NONE, 'B');
108 ExpectUnicodeKeyNotFiltered(VKEY_Z, DomCode::KEY_Z, EF_NONE, 'Z');
109 ExpectUnicodeKeyNotFiltered(VKEY_C, DomCode::KEY_C, EF_NONE, 'c');
110 ExpectUnicodeKeyNotFiltered(VKEY_M, DomCode::KEY_M, EF_NONE, 'm');
111 ExpectUnicodeKeyNotFiltered(VKEY_0, DomCode::DIGIT0, EF_NONE, '0');
112 ExpectUnicodeKeyNotFiltered(VKEY_1, DomCode::DIGIT1, EF_NONE, '1');
113 ExpectUnicodeKeyNotFiltered(VKEY_8, DomCode::DIGIT8, EF_NONE, '8');
116 TEST_F(CharacterComposerTest, PartiallyMatchingSequence) {
117 // Composition with sequence ['dead acute', '1'] will fail.
118 ExpectDeadKeyFiltered(kCombiningAcute);
119 ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, 0, '1');
121 // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail.
122 ExpectDeadKeyFiltered(kCombiningAcute);
123 ExpectDeadKeyFiltered(kCombiningCircumflex);
124 ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, 0, '1');
127 TEST_F(CharacterComposerTest, FullyMatchingSequences) {
128 // LATIN SMALL LETTER A WITH ACUTE
129 ExpectDeadKeyFiltered(kCombiningAcute);
130 ExpectUnicodeKeyComposed(VKEY_A, DomCode::KEY_A, EF_NONE, 'a',
131 base::string16(1, 0x00E1));
132 // LATIN CAPITAL LETTER A WITH ACUTE
133 ExpectDeadKeyFiltered(kCombiningAcute);
134 ExpectUnicodeKeyComposed(VKEY_A, DomCode::KEY_A, EF_NONE, 'A',
135 base::string16(1, 0x00C1));
136 // GRAVE ACCENT
137 ExpectDeadKeyFiltered(kCombiningGrave);
138 ExpectDeadKeyComposed(kCombiningGrave, base::string16(1, 0x0060));
139 // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
140 ExpectDeadKeyFiltered(kCombiningAcute);
141 ExpectDeadKeyFiltered(kCombiningCircumflex);
142 ExpectUnicodeKeyComposed(VKEY_A, DomCode::KEY_A, EF_NONE, 'a',
143 base::string16(1, 0x1EA5));
144 // LATIN CAPITAL LETTER U WITH HORN AND GRAVE
145 ExpectDeadKeyFiltered(kCombiningGrave);
146 ExpectDeadKeyFiltered(kCombiningHorn);
147 ExpectUnicodeKeyComposed(VKEY_U, DomCode::KEY_U, EF_NONE, 'U',
148 base::string16(1, 0x1EEA));
149 // LATIN CAPITAL LETTER C WITH CEDILLA
150 ExpectDeadKeyFiltered(kCombiningAcute);
151 ExpectUnicodeKeyComposed(VKEY_C, DomCode::KEY_C, EF_NONE, 'C',
152 base::string16(1, 0x00C7));
153 // LATIN SMALL LETTER C WITH CEDILLA
154 ExpectDeadKeyFiltered(kCombiningAcute);
155 ExpectUnicodeKeyComposed(VKEY_C, DomCode::KEY_C, EF_NONE, 'c',
156 base::string16(1, 0x00E7));
157 // GREEK SMALL LETTER EPSILON WITH TONOS
158 ExpectDeadKeyFiltered(kCombiningAcute);
159 ExpectUnicodeKeyComposed(VKEY_E, DomCode::KEY_E, EF_NONE, 0x03B5,
160 base::string16(1, 0x03AD));
163 TEST_F(CharacterComposerTest, FullyMatchingSequencesAfterMatchingFailure) {
164 // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail.
165 ExpectDeadKeyFiltered(kCombiningAcute);
166 ExpectDeadKeyFiltered(kCombiningCircumflex);
167 ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, 0, '1');
168 // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
169 ExpectDeadKeyFiltered(kCombiningAcute);
170 ExpectDeadKeyFiltered(kCombiningCircumflex);
171 ExpectUnicodeKeyComposed(VKEY_A, DomCode::KEY_A, EF_NONE, 'a',
172 base::string16(1, 0x1EA5));
175 TEST_F(CharacterComposerTest, ComposedCharacterIsClearedAfterReset) {
176 ExpectDeadKeyFiltered(kCombiningAcute);
177 ExpectUnicodeKeyComposed(VKEY_A, DomCode::KEY_A, EF_NONE, 'a',
178 base::string16(1, 0x00E1));
179 character_composer_.Reset();
180 EXPECT_TRUE(character_composer_.composed_character().empty());
183 TEST_F(CharacterComposerTest, CompositionStateIsClearedAfterReset) {
184 // Even though sequence ['dead acute', 'a'] will compose 'a with acute',
185 // no character is composed here because of reset.
186 ExpectDeadKeyFiltered(kCombiningAcute);
187 character_composer_.Reset();
188 ExpectUnicodeKeyNotFiltered(VKEY_A, DomCode::KEY_A, EF_NONE, 'a');
191 TEST_F(CharacterComposerTest, KeySequenceCompositionPreedit) {
192 // LATIN SMALL LETTER A WITH ACUTE
193 // preedit_string() is always empty in key sequence composition mode.
194 ExpectDeadKeyFiltered(kCombiningAcute);
195 EXPECT_TRUE(character_composer_.preedit_string().empty());
196 ExpectUnicodeKeyComposed(VKEY_A, DomCode::KEY_A, EF_NONE, 'a',
197 base::string16(1, 0x00E1));
198 EXPECT_TRUE(character_composer_.preedit_string().empty());
201 // Verify the structure of the primary |TreeComposeChecker| table.
202 TEST_F(CharacterComposerTest, MainTableIsCorrectlyOrdered) {
203 // This file is included here intentionally, instead of the top of the file,
204 // because including this file at the top of the file will define a
205 // global constant and contaminate the global namespace.
206 #include "ui/base/ime/chromeos/character_composer_data.h"
207 const int kTypes = 2;
209 // Record the subtree locations and check subtable sizes.
210 std::vector<uint16_t> subtrees;
211 uint16_t index = 0;
212 while (index < kCompositions.tree_entries) {
213 // Record the start of the subtree.
214 SCOPED_TRACE(index);
215 subtrees.push_back(index);
216 for (int t = 0; t < kTypes; ++t) {
217 // Skip the internal table and verify the next index is within the data.
218 index += 1 + 2 * kCompositions.tree[index];
219 EXPECT_GT(kCompositions.tree_entries, index);
220 // Skip the leaf table and verify that the next index is not past the
221 // end of the data.
222 index += 1 + 2 * kCompositions.tree[index];
223 EXPECT_GE(kCompositions.tree_entries, index);
226 // We should end up at the end of the data.
227 EXPECT_EQ(kCompositions.tree_entries, index);
229 // Check subtable structure.
230 index = 0;
231 while (index < kCompositions.tree_entries) {
232 SCOPED_TRACE(index);
233 for (int t = 0; t < kTypes; ++t) {
234 // Check the internal subtable.
235 uint16_t previous_key = 0;
236 uint16_t size = kCompositions.tree[index++];
237 for (uint16_t i = 0; i < size; ++i) {
238 // Verify that the subtable is sorted.
239 uint16_t key = kCompositions.tree[index];
240 uint16_t value = kCompositions.tree[index + 1];
241 if (i)
242 EXPECT_LT(previous_key, key) << index;
243 previous_key = key;
244 // Verify that the internal link is valid.
245 const auto it = std::find(subtrees.begin(), subtrees.end(), value);
246 EXPECT_FALSE(subtrees.end() == it) << index;
247 index += 2;
249 // Check the leaf subtable.
250 previous_key = 0;
251 size = kCompositions.tree[index++];
252 for (uint16_t i = 0; i < size; ++i) {
253 // Verify that the subtable is sorted.
254 uint16_t key = kCompositions.tree[index];
255 if (i)
256 EXPECT_LT(previous_key, key) << index;
257 previous_key = key;
258 index += 2;
264 TEST_F(CharacterComposerTest, HexadecimalComposition) {
265 // HIRAGANA LETTER A (U+3042)
266 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
267 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 'U');
268 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, EF_NONE, '3');
269 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, EF_NONE, '0');
270 ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4');
271 ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2');
272 ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ',
273 base::string16(1, 0x3042));
274 // MUSICAL KEYBOARD (U+1F3B9)
275 const base::char16 kMusicalKeyboard[] = {0xd83c, 0xdfb9};
276 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
277 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 'U');
278 ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, EF_NONE, '1');
279 ExpectUnicodeKeyFiltered(VKEY_F, DomCode::KEY_F, EF_NONE, 'f');
280 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, EF_NONE, '3');
281 ExpectUnicodeKeyFiltered(VKEY_B, DomCode::KEY_B, EF_NONE, 'b');
282 ExpectUnicodeKeyFiltered(VKEY_9, DomCode::DIGIT9, EF_NONE, '9');
283 ExpectUnicodeKeyComposed(
284 VKEY_RETURN, DomCode::ENTER, EF_NONE, '\r',
285 base::string16(kMusicalKeyboard,
286 kMusicalKeyboard + arraysize(kMusicalKeyboard)));
289 TEST_F(CharacterComposerTest, HexadecimalCompositionPreedit) {
290 // HIRAGANA LETTER A (U+3042)
291 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
292 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 'U');
293 EXPECT_EQ(ASCIIToUTF16("u"), character_composer_.preedit_string());
294 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, 0, '3');
295 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_.preedit_string());
296 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, 0, '0');
297 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string());
298 ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, 0, '4');
299 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string());
300 ExpectUnicodeKeyFiltered(VKEY_A, DomCode::KEY_A, 0, 'a');
301 EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer_.preedit_string());
302 ExpectUnicodeKeyFiltered(VKEY_BACK, DomCode::BACKSPACE, EF_NONE, '\b');
303 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string());
304 ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2');
305 ExpectUnicodeKeyComposed(VKEY_RETURN, DomCode::ENTER, EF_NONE,
306 '\r',
307 base::string16(1, 0x3042));
308 EXPECT_EQ(ASCIIToUTF16(""), character_composer_.preedit_string());
310 // Sequence with an ignored character ('x') and Escape.
311 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
312 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 'U');
313 EXPECT_EQ(ASCIIToUTF16("u"), character_composer_.preedit_string());
314 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, 0, '3');
315 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_.preedit_string());
316 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, 0, '0');
317 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string());
318 ExpectUnicodeKeyFiltered(VKEY_X, DomCode::KEY_X, 0, 'x');
319 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string());
320 ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, 0, '4');
321 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string());
322 ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, 0, '2');
323 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_.preedit_string());
324 ExpectUnicodeKeyFiltered(VKEY_ESCAPE, DomCode::ESCAPE, EF_NONE, 0x1B);
325 EXPECT_EQ(ASCIIToUTF16(""), character_composer_.preedit_string());
328 TEST_F(CharacterComposerTest, HexadecimalCompositionWithNonHexKey) {
329 // Sequence [Ctrl+Shift+U, x, space] does not compose a character.
330 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
331 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
332 ExpectUnicodeKeyFiltered(VKEY_X, DomCode::KEY_X, 0, 'x');
333 ExpectUnicodeKeyFiltered(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ');
334 EXPECT_TRUE(character_composer_.composed_character().empty());
336 // HIRAGANA LETTER A (U+3042) with a sequence [3, 0, x, 4, 2].
337 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
338 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
339 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, EF_NONE, '3');
340 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, EF_NONE, '0');
341 ExpectUnicodeKeyFiltered(VKEY_X, DomCode::KEY_X, EF_NONE, 'x');
342 ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4');
343 ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2');
344 ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ',
345 base::string16(1, 0x3042));
348 TEST_F(CharacterComposerTest, HexadecimalCompositionWithAdditionalModifiers) {
349 // Ctrl+Shift+Alt+U
350 // HIRAGANA LETTER A (U+3042)
351 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
352 EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_ALT_DOWN, 0x15);
353 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, EF_NONE, '3');
354 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, EF_NONE, '0');
355 ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4');
356 ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2');
357 ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ',
358 base::string16(1, 0x3042));
360 // Ctrl+Shift+u (CapsLock enabled)
361 ExpectUnicodeKeyNotFiltered(
362 VKEY_U, DomCode::KEY_U,
363 EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_CAPS_LOCK_DOWN, 'u');
366 TEST_F(CharacterComposerTest, CancelHexadecimalComposition) {
367 // Cancel composition with ESC.
368 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
369 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
370 ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, 0, '1');
371 ExpectUnicodeKeyFiltered(VKEY_ESCAPE, DomCode::ESCAPE, EF_NONE, 0x1B);
373 // Now we can start composition again since the last composition was
374 // cancelled.
375 // HIRAGANA LETTER A (U+3042)
376 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
377 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
378 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, EF_NONE, '3');
379 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, EF_NONE, '0');
380 ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4');
381 ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2');
382 ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ',
383 base::string16(1, 0x3042));
386 TEST_F(CharacterComposerTest, HexadecimalCompositionWithBackspace) {
387 // HIRAGANA LETTER A (U+3042)
388 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
389 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
390 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, 0, '3');
391 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, 0, '0');
392 ExpectUnicodeKeyFiltered(VKEY_F, DomCode::KEY_F, 0, 'f');
393 ExpectUnicodeKeyFiltered(VKEY_BACK, DomCode::BACKSPACE, EF_NONE, '\b');
394 ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4');
395 ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2');
396 ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ',
397 base::string16(1, 0x3042));
400 TEST_F(CharacterComposerTest, CancelHexadecimalCompositionWithBackspace) {
401 // Backspace just after Ctrl+Shift+U.
402 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
403 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
404 ExpectUnicodeKeyFiltered(VKEY_BACK, DomCode::BACKSPACE, EF_NONE, '\b');
405 ExpectUnicodeKeyNotFiltered(VKEY_3, DomCode::DIGIT3, EF_NONE, '3');
407 // Backspace twice after Ctrl+Shift+U and 3.
408 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
409 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
410 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, 0, '3');
411 ExpectUnicodeKeyFiltered(VKEY_BACK, DomCode::BACKSPACE, EF_NONE, '\b');
412 ExpectUnicodeKeyFiltered(VKEY_BACK, DomCode::BACKSPACE, EF_NONE, '\b');
413 ExpectUnicodeKeyNotFiltered(VKEY_3, DomCode::DIGIT3, EF_NONE, '3');
416 TEST_F(CharacterComposerTest,
417 HexadecimalCompositionPreeditWithModifierPressed) {
418 // This test case supposes X Window System uses 101 keyboard layout.
419 const int kControlShift = EF_CONTROL_DOWN | EF_SHIFT_DOWN;
420 // HIRAGANA LETTER A (U+3042)
421 ExpectUnicodeKeyFiltered(ui::VKEY_U, DomCode::KEY_U, kControlShift, 0x15);
422 EXPECT_EQ(ASCIIToUTF16("u"), character_composer_.preedit_string());
423 ExpectUnicodeKeyFiltered(ui::VKEY_3, DomCode::DIGIT3, kControlShift, '#');
424 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_.preedit_string());
425 ExpectUnicodeKeyFiltered(ui::VKEY_0, DomCode::DIGIT0, kControlShift, ')');
426 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string());
427 ExpectUnicodeKeyFiltered(ui::VKEY_4, DomCode::DIGIT4, kControlShift, '$');
428 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string());
429 ExpectUnicodeKeyFiltered(ui::VKEY_A, DomCode::KEY_A, kControlShift, 0x01);
430 EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer_.preedit_string());
431 ExpectUnicodeKeyFiltered(ui::VKEY_BACK, DomCode::BACKSPACE, kControlShift,
432 '\b');
433 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string());
434 ExpectUnicodeKeyFiltered(ui::VKEY_2, DomCode::DIGIT2, kControlShift, 0);
435 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_.preedit_string());
436 ExpectUnicodeKeyComposed(VKEY_RETURN, DomCode::ENTER, kControlShift,
437 '\r',
438 base::string16(1, 0x3042));
439 EXPECT_EQ(ASCIIToUTF16(""), character_composer_.preedit_string());
441 // Sequence with an ignored character (control + shift + 'x') and Escape.
442 ExpectUnicodeKeyFiltered(ui::VKEY_U, DomCode::KEY_U, kControlShift, 'U');
443 EXPECT_EQ(ASCIIToUTF16("u"), character_composer_.preedit_string());
444 ExpectUnicodeKeyFiltered(ui::VKEY_3, DomCode::DIGIT3, kControlShift, '#');
445 EXPECT_EQ(ASCIIToUTF16("u3"), character_composer_.preedit_string());
446 ExpectUnicodeKeyFiltered(ui::VKEY_0, DomCode::DIGIT0, kControlShift, ')');
447 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string());
448 ExpectUnicodeKeyFiltered(ui::VKEY_X, DomCode::KEY_X, kControlShift, 'X');
449 EXPECT_EQ(ASCIIToUTF16("u30"), character_composer_.preedit_string());
450 ExpectUnicodeKeyFiltered(ui::VKEY_4, DomCode::DIGIT4, kControlShift, '$');
451 EXPECT_EQ(ASCIIToUTF16("u304"), character_composer_.preedit_string());
452 ExpectUnicodeKeyFiltered(ui::VKEY_2, DomCode::DIGIT2, kControlShift, 0);
453 EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer_.preedit_string());
454 ExpectUnicodeKeyFiltered(ui::VKEY_ESCAPE, DomCode::ESCAPE, kControlShift,
455 0x1B);
456 EXPECT_EQ(ASCIIToUTF16(""), character_composer_.preedit_string());
459 TEST_F(CharacterComposerTest, InvalidHexadecimalSequence) {
460 // U+FFFFFFFF
461 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
462 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
463 for (int i = 0; i < 8; ++i)
464 ExpectUnicodeKeyFiltered(VKEY_F, DomCode::KEY_F, 0, 'f');
465 ExpectUnicodeKeyFiltered(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ');
467 // U+0000 (Actually, this is a valid unicode character, but we don't
468 // compose a string with a character '\0')
469 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
470 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
471 for (int i = 0; i < 4; ++i)
472 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, 0, '0');
473 ExpectUnicodeKeyFiltered(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ');
475 // U+10FFFF
476 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
477 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
478 ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, 0, '1');
479 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, 0, '0');
480 for (int i = 0; i < 4; ++i)
481 ExpectUnicodeKeyFiltered(VKEY_F, DomCode::KEY_F, 0, 'f');
482 ExpectUnicodeKeyFiltered(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ');
484 // U+110000
485 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
486 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
487 ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, 0, '1');
488 ExpectUnicodeKeyFiltered(VKEY_1, DomCode::DIGIT1, 0, '1');
489 for (int i = 0; i < 4; ++i)
490 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, 0, '0');
491 ExpectUnicodeKeyFiltered(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ');
494 TEST_F(CharacterComposerTest, HexadecimalSequenceAndDeadKey) {
495 // LATIN SMALL LETTER A WITH ACUTE
496 ExpectDeadKeyFiltered(kCombiningAcute);
497 ExpectUnicodeKeyComposed(VKEY_A, DomCode::KEY_A, EF_NONE, 'a',
498 base::string16(1, 0x00E1));
499 // HIRAGANA LETTER A (U+3042) with dead_acute ignored.
500 ExpectUnicodeKeyFiltered(VKEY_U, DomCode::KEY_U,
501 EF_SHIFT_DOWN | EF_CONTROL_DOWN, 0x15);
502 ExpectUnicodeKeyFiltered(VKEY_3, DomCode::DIGIT3, EF_NONE, '3');
503 ExpectUnicodeKeyFiltered(VKEY_0, DomCode::DIGIT0, EF_NONE, '0');
504 ExpectDeadKeyFiltered(kCombiningAcute);
505 ExpectUnicodeKeyFiltered(VKEY_4, DomCode::DIGIT4, EF_NONE, '4');
506 ExpectUnicodeKeyFiltered(VKEY_2, DomCode::DIGIT2, EF_NONE, '2');
507 ExpectUnicodeKeyComposed(VKEY_SPACE, DomCode::SPACE, EF_NONE, ' ',
508 base::string16(1, 0x3042));
511 } // namespace ui