- add sources.
[platform/framework/web/crosswalk.git] / src / ui / base / ime / character_composer_unittest.cc
1 // Copyright (c) 2012 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 "ui/base/ime/character_composer.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/gtk+/gdk/gdkkeysyms.h"
10 #include "ui/base/glib/glib_integers.h"
11 #include "ui/events/event_constants.h"
12
13 namespace ui {
14
15 namespace {
16
17 // Expects key is not filtered and no character is composed.
18 void ExpectKeyNotFiltered(CharacterComposer* character_composer,
19                           uint key,
20                           int flags) {
21   EXPECT_FALSE(character_composer->FilterKeyPress(key, 0, flags));
22   EXPECT_TRUE(character_composer->composed_character().empty());
23 }
24
25 // Expects key is filtered and no character is composed.
26 void ExpectKeyFiltered(CharacterComposer* character_composer,
27                        uint key,
28                        int flags) {
29   EXPECT_TRUE(character_composer->FilterKeyPress(key, 0, flags));
30   EXPECT_TRUE(character_composer->composed_character().empty());
31 }
32
33 // Expects key is filtered and no character is composed.
34 void ExpectKeyFilteredWithKeycode(CharacterComposer* character_composer,
35                                   uint key,
36                                   uint keycode,
37                                   int flags) {
38   EXPECT_TRUE(character_composer->FilterKeyPress(key, keycode, flags));
39   EXPECT_TRUE(character_composer->composed_character().empty());
40 }
41
42 // Expects |expected_character| is composed after sequence [key1, key2].
43 void ExpectCharacterComposed(CharacterComposer* character_composer,
44                              uint key1,
45                              uint key2,
46                              int flags,
47                              const string16& expected_character) {
48   ExpectKeyFiltered(character_composer, key1, flags);
49   EXPECT_TRUE(character_composer->FilterKeyPress(key2, 0, flags));
50   EXPECT_EQ(expected_character, character_composer->composed_character());
51 }
52
53 // Expects |expected_character| is composed after sequence [key1, key2, key3].
54 void ExpectCharacterComposed(CharacterComposer* character_composer,
55                              uint key1,
56                              uint key2,
57                              uint key3,
58                              int flags,
59                              const string16& expected_character) {
60   ExpectKeyFiltered(character_composer, key1, flags);
61   ExpectCharacterComposed(character_composer, key2, key3, flags,
62                           expected_character);
63 }
64
65 // Expects |expected_character| is composed after sequence [key1, key2, key3,
66 // key 4].
67 void ExpectCharacterComposed(CharacterComposer* character_composer,
68                              uint key1,
69                              uint key2,
70                              uint key3,
71                              uint key4,
72                              int flags,
73                              const string16& expected_character) {
74   ExpectKeyFiltered(character_composer, key1, flags);
75   ExpectCharacterComposed(character_composer, key2, key3, key4, flags,
76                           expected_character);
77 }
78
79 // Expects |expected_character| is composed after sequence [key1, key2, key3,
80 // key 4, key5].
81 void ExpectCharacterComposed(CharacterComposer* character_composer,
82                              uint key1,
83                              uint key2,
84                              uint key3,
85                              uint key4,
86                              uint key5,
87                              int flags,
88                              const string16& expected_character) {
89   ExpectKeyFiltered(character_composer, key1, flags);
90   ExpectCharacterComposed(character_composer, key2, key3, key4, key5, flags,
91                           expected_character);
92 }
93
94 // Expects |expected_character| is composed after sequence [key1, key2, key3,
95 // key 4, key5, key6].
96 void ExpectCharacterComposed(CharacterComposer* character_composer,
97                              uint key1,
98                              uint key2,
99                              uint key3,
100                              uint key4,
101                              uint key5,
102                              uint key6,
103                              int flags,
104                              const string16& expected_character) {
105   ExpectKeyFiltered(character_composer, key1, flags);
106   ExpectCharacterComposed(character_composer, key2, key3, key4, key5, key6,
107                           flags, expected_character);
108 }
109
110 // Expects |expected_character| is composed after sequence [{key1, keycode1}].
111 void ExpectCharacterComposedWithKeyCode(CharacterComposer* character_composer,
112                                         uint key1, uint keycode1,
113                                         int flags,
114                                         const string16& expected_character) {
115   EXPECT_TRUE(character_composer->FilterKeyPress(key1, keycode1, flags));
116   EXPECT_EQ(expected_character, character_composer->composed_character());
117 }
118
119 } // namespace
120
121 TEST(CharacterComposerTest, InitialState) {
122   CharacterComposer character_composer;
123   EXPECT_TRUE(character_composer.composed_character().empty());
124 }
125
126 TEST(CharacterComposerTest, NormalKeyIsNotFiltered) {
127   CharacterComposer character_composer;
128   ExpectKeyNotFiltered(&character_composer, GDK_KEY_B, 0);
129   ExpectKeyNotFiltered(&character_composer, GDK_KEY_Z, 0);
130   ExpectKeyNotFiltered(&character_composer, GDK_KEY_c, 0);
131   ExpectKeyNotFiltered(&character_composer, GDK_KEY_m, 0);
132   ExpectKeyNotFiltered(&character_composer, GDK_KEY_0, 0);
133   ExpectKeyNotFiltered(&character_composer, GDK_KEY_1, 0);
134   ExpectKeyNotFiltered(&character_composer, GDK_KEY_8, 0);
135 }
136
137 TEST(CharacterComposerTest, PartiallyMatchingSequence) {
138   CharacterComposer character_composer;
139
140   // Composition with sequence ['dead acute', '1'] will fail.
141   ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
142   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1, 0, 0));
143   EXPECT_TRUE(character_composer.composed_character().empty());
144
145   // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail.
146   ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
147   ExpectKeyFiltered(&character_composer, GDK_KEY_dead_circumflex, 0);
148   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1, 0, 0));
149   EXPECT_TRUE(character_composer.composed_character().empty());
150 }
151
152 TEST(CharacterComposerTest, FullyMatchingSequences) {
153   CharacterComposer character_composer;
154   // LATIN SMALL LETTER A WITH ACUTE
155   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0,
156                           string16(1, 0x00E1));
157   // LATIN CAPITAL LETTER A WITH ACUTE
158   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_A, 0,
159                           string16(1, 0x00C1));
160   // GRAVE ACCENT
161   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_grave,
162                           GDK_KEY_dead_grave, 0, string16(1, 0x0060));
163   // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
164   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute,
165                           GDK_KEY_dead_circumflex, GDK_KEY_a, 0,
166                           string16(1, 0x1EA5));
167   // LATIN CAPITAL LETTER U WITH HORN AND GRAVE
168   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_grave,
169                           GDK_KEY_dead_horn, GDK_KEY_U, 0, string16(1, 0x1EEA));
170   // LATIN CAPITAL LETTER C WITH CEDILLA
171   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_C, 0,
172                           string16(1, 0x00C7));
173   // LATIN SMALL LETTER C WITH CEDILLA
174   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_c, 0,
175                           string16(1, 0x00E7));
176 }
177
178 TEST(CharacterComposerTest, FullyMatchingSequencesAfterMatchingFailure) {
179   CharacterComposer character_composer;
180   // Composition with sequence ['dead acute', 'dead circumflex', '1'] will fail.
181   ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
182   ExpectKeyFiltered(&character_composer, GDK_KEY_dead_circumflex, 0);
183   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_1, 0, 0));
184   EXPECT_TRUE(character_composer.composed_character().empty());
185   // LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE
186   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute,
187                           GDK_KEY_dead_circumflex, GDK_KEY_a, 0,
188                           string16(1, 0x1EA5));
189 }
190
191 TEST(CharacterComposerTest, ComposedCharacterIsClearedAfterReset) {
192   CharacterComposer character_composer;
193   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0,
194                           string16(1, 0x00E1));
195   character_composer.Reset();
196   EXPECT_TRUE(character_composer.composed_character().empty());
197 }
198
199 TEST(CharacterComposerTest, CompositionStateIsClearedAfterReset) {
200   CharacterComposer character_composer;
201   // Even though sequence ['dead acute', 'a'] will compose 'a with acute',
202   // no character is composed here because of reset.
203   ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
204   character_composer.Reset();
205   EXPECT_FALSE(character_composer.FilterKeyPress(GDK_KEY_a, 0, 0));
206   EXPECT_TRUE(character_composer.composed_character().empty());
207 }
208
209 TEST(CharacterComposerTest, KeySequenceCompositionPreedit) {
210   CharacterComposer character_composer;
211   // LATIN SMALL LETTER A WITH ACUTE
212   // preedit_string() is always empty in key sequence composition mode.
213   ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
214   EXPECT_TRUE(character_composer.preedit_string().empty());
215   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_a, 0, 0));
216   EXPECT_EQ(string16(1, 0x00E1), character_composer.composed_character());
217   EXPECT_TRUE(character_composer.preedit_string().empty());
218 }
219
220 // ComposeCheckerWithCompactTable in character_composer.cc is depending on the
221 // assumption that the data in gtkimcontextsimpleseqs.h is correctly ordered.
222 TEST(CharacterComposerTest, MainTableIsCorrectlyOrdered) {
223   // This file is included here intentionally, instead of the top of the file,
224   // because including this file at the top of the file will define a
225   // global constant and contaminate the global namespace.
226 #include "third_party/gtk+/gtk/gtkimcontextsimpleseqs.h"
227   const int index_size = 26;
228   const int index_stride = 6;
229
230   // Verify that the index is correctly ordered
231   for (int i = 1; i < index_size; ++i) {
232     const int index_key_prev = gtk_compose_seqs_compact[(i - 1)*index_stride];
233     const int index_key = gtk_compose_seqs_compact[i*index_stride];
234     EXPECT_TRUE(index_key > index_key_prev);
235   }
236
237   // Verify that the sequenes are correctly ordered
238   struct {
239     int operator()(const uint16* l, const uint16* r, int length) const{
240       for (int i = 0; i < length; ++i) {
241         if (l[i] > r[i])
242           return 1;
243         if (l[i] < r[i])
244           return -1;
245       }
246       return 0;
247     }
248   } compare_sequence;
249
250   for (int i = 0; i < index_size; ++i) {
251     for (int length = 1; length < index_stride - 1; ++length) {
252       const int index_begin = gtk_compose_seqs_compact[i*index_stride + length];
253       const int index_end =
254           gtk_compose_seqs_compact[i*index_stride + length + 1];
255       const int stride = length + 1;
256       for (int index = index_begin + stride; index < index_end;
257            index += stride) {
258         const uint16* sequence = &gtk_compose_seqs_compact[index];
259         const uint16* sequence_prev = sequence - stride;
260         EXPECT_EQ(1, compare_sequence(sequence, sequence_prev, length));
261       }
262     }
263   }
264 }
265
266 TEST(CharacterComposerTest, HexadecimalComposition) {
267   CharacterComposer character_composer;
268   // HIRAGANA LETTER A (U+3042)
269   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
270                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
271   ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4,
272                           GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042));
273   // MUSICAL KEYBOARD (U+1F3B9)
274   const char16 kMusicalKeyboard[] = {0xd83c, 0xdfb9};
275   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
276                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
277   ExpectCharacterComposed(&character_composer, GDK_KEY_1, GDK_KEY_f, GDK_KEY_3,
278                           GDK_KEY_b, GDK_KEY_9, GDK_KEY_Return, 0,
279                           string16(kMusicalKeyboard,
280                                    kMusicalKeyboard +
281                                    arraysize(kMusicalKeyboard)));
282 }
283
284 TEST(CharacterComposerTest, HexadecimalCompositionPreedit) {
285   CharacterComposer character_composer;
286   // HIRAGANA LETTER A (U+3042)
287   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
288                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
289   EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string());
290   ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0);
291   EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string());
292   ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
293   EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
294   ExpectKeyFiltered(&character_composer, GDK_KEY_4, 0);
295   EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
296   ExpectKeyFiltered(&character_composer, GDK_KEY_a, 0);
297   EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer.preedit_string());
298   ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
299   EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
300   ExpectCharacterComposed(&character_composer, GDK_KEY_2, GDK_KEY_Return, 0,
301                           string16(1, 0x3042));
302   EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string());
303
304   // Sequence with an ignored character ('x') and Escape.
305   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
306                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
307   EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string());
308   ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0);
309   EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string());
310   ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
311   EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
312   ExpectKeyFiltered(&character_composer, GDK_KEY_x, 0);
313   EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
314   ExpectKeyFiltered(&character_composer, GDK_KEY_4, 0);
315   EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
316   ExpectKeyFiltered(&character_composer, GDK_KEY_2, 0);
317   EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string());
318   ExpectKeyFiltered(&character_composer, GDK_KEY_Escape, 0);
319   EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string());
320 }
321
322 TEST(CharacterComposerTest, HexadecimalCompositionWithNonHexKey) {
323   CharacterComposer character_composer;
324
325   // Sequence [Ctrl+Shift+U, x, space] does not compose a character.
326   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
327                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
328   ExpectKeyFiltered(&character_composer, GDK_KEY_x, 0);
329   ExpectKeyFiltered(&character_composer, GDK_KEY_space, 0);
330   EXPECT_TRUE(character_composer.composed_character().empty());
331
332   // HIRAGANA LETTER A (U+3042) with a sequence [3, 0, x, 4, 2].
333   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
334                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
335   ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_x,
336                           GDK_KEY_4, GDK_KEY_2, GDK_KEY_space, 0,
337                           string16(1, 0x3042));
338 }
339
340 TEST(CharacterComposerTest, HexadecimalCompositionWithAdditionalModifiers) {
341   CharacterComposer character_composer;
342
343   // Ctrl+Shift+Alt+U
344   // HIRAGANA LETTER A (U+3042)
345   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
346                     EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_ALT_DOWN);
347   ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4,
348                           GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042));
349
350   // Ctrl+Shift+u (CapsLock enabled)
351   ExpectKeyNotFiltered(&character_composer, GDK_KEY_u,
352                        EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_CAPS_LOCK_DOWN);
353 }
354
355 TEST(CharacterComposerTest, CancelHexadecimalComposition) {
356   CharacterComposer character_composer;
357   // Cancel composition with ESC.
358   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
359                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
360   ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
361   ExpectKeyFiltered(&character_composer, GDK_KEY_Escape, 0);
362
363   // Now we can start composition again since the last composition was
364   // cancelled.
365   // HIRAGANA LETTER A (U+3042)
366   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
367                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
368   ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0, GDK_KEY_4,
369                           GDK_KEY_2, GDK_KEY_space, 0, string16(1, 0x3042));
370 }
371
372 TEST(CharacterComposerTest, HexadecimalCompositionWithBackspace) {
373   CharacterComposer character_composer;
374   // HIRAGANA LETTER A (U+3042)
375   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
376                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
377   ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0);
378   ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
379   ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0);
380   ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
381   ExpectCharacterComposed(&character_composer, GDK_KEY_4, GDK_KEY_2,
382                           GDK_KEY_space, 0, string16(1, 0x3042));
383 }
384
385 TEST(CharacterComposerTest, CancelHexadecimalCompositionWithBackspace) {
386   CharacterComposer character_composer;
387
388   // Backspace just after Ctrl+Shift+U.
389   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
390                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
391   ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
392   ExpectKeyNotFiltered(&character_composer, GDK_KEY_3, 0);
393
394   // Backspace twice after Ctrl+Shift+U and 3.
395   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
396                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
397   ExpectKeyFiltered(&character_composer, GDK_KEY_3, 0);
398   ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
399   ExpectKeyFiltered(&character_composer, GDK_KEY_BackSpace, 0);
400   ExpectKeyNotFiltered(&character_composer, GDK_KEY_3, 0);
401 }
402
403 TEST(CharacterComposerTest, HexadecimalCompositionPreeditWithModifierPressed) {
404   // This test case supposes X Window System uses 101 keyboard layout.
405   CharacterComposer character_composer;
406   const int control_shift =  EF_CONTROL_DOWN | EF_SHIFT_DOWN;
407   // HIRAGANA LETTER A (U+3042)
408   ExpectKeyFilteredWithKeycode(&character_composer,
409                                GDK_KEY_U, 30, control_shift);
410   EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string());
411   ExpectKeyFilteredWithKeycode(&character_composer,
412                                GDK_KEY_numbersign, 12, control_shift);
413   EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string());
414   ExpectKeyFilteredWithKeycode(&character_composer,
415                                GDK_KEY_parenright, 19, control_shift);
416   EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
417   ExpectKeyFilteredWithKeycode(&character_composer,
418                                GDK_KEY_dollar, 13, control_shift);
419   EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
420   ExpectKeyFilteredWithKeycode(&character_composer,
421                                GDK_KEY_A, 38, control_shift);
422   EXPECT_EQ(ASCIIToUTF16("u304a"), character_composer.preedit_string());
423   ExpectKeyFilteredWithKeycode(&character_composer,
424                                GDK_KEY_BackSpace, 22, control_shift);
425   EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
426   ExpectKeyFilteredWithKeycode(&character_composer,
427                                GDK_KEY_at, 11, control_shift);
428   EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string());
429   ExpectCharacterComposedWithKeyCode(&character_composer,
430                                      GDK_KEY_Return, 36,
431                                      control_shift,
432                                      string16(1, 0x3042));
433   EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string());
434
435   // Sequence with an ignored character (control + shift + 'x') and Escape.
436   ExpectKeyFilteredWithKeycode(&character_composer,
437                                GDK_KEY_U, 30, control_shift);
438   EXPECT_EQ(ASCIIToUTF16("u"), character_composer.preedit_string());
439   ExpectKeyFilteredWithKeycode(&character_composer,
440                                GDK_KEY_numbersign, 12, control_shift);
441   EXPECT_EQ(ASCIIToUTF16("u3"), character_composer.preedit_string());
442   ExpectKeyFilteredWithKeycode(&character_composer,
443                                GDK_KEY_parenright, 19, control_shift);
444   EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
445   ExpectKeyFilteredWithKeycode(&character_composer,
446                                GDK_KEY_X, 53, control_shift);
447   EXPECT_EQ(ASCIIToUTF16("u30"), character_composer.preedit_string());
448   ExpectKeyFilteredWithKeycode(&character_composer,
449                                GDK_KEY_dollar, 13, control_shift);
450   EXPECT_EQ(ASCIIToUTF16("u304"), character_composer.preedit_string());
451   ExpectKeyFilteredWithKeycode(&character_composer,
452                                GDK_KEY_at, 11, control_shift);
453   EXPECT_EQ(ASCIIToUTF16("u3042"), character_composer.preedit_string());
454   ExpectKeyFilteredWithKeycode(&character_composer,
455                                GDK_KEY_Escape, 9, control_shift);
456   EXPECT_EQ(ASCIIToUTF16(""), character_composer.preedit_string());
457 }
458
459 TEST(CharacterComposerTest, InvalidHexadecimalSequence) {
460   CharacterComposer character_composer;
461   // U+FFFFFFFF
462   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
463                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
464   for (int i = 0; i < 8; ++i)
465     ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0);
466   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_space, 0, 0));
467   EXPECT_TRUE(character_composer.composed_character().empty());
468
469   // U+0000 (Actually, this is a valid unicode character, but we don't
470   // compose a string with a character '\0')
471   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
472                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
473   for (int i = 0; i < 4; ++i)
474     ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
475   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_space, 0, 0));
476   EXPECT_TRUE(character_composer.composed_character().empty());
477
478   // U+10FFFF
479   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
480                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
481   ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
482   ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
483   for (int i = 0; i < 4; ++i)
484     ExpectKeyFiltered(&character_composer, GDK_KEY_f, 0);
485   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_space, 0, 0));
486   EXPECT_TRUE(character_composer.composed_character().empty());
487
488   // U+110000
489   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
490                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
491   ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
492   ExpectKeyFiltered(&character_composer, GDK_KEY_1, 0);
493   for (int i = 0; i < 4; ++i)
494     ExpectKeyFiltered(&character_composer, GDK_KEY_0, 0);
495   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_space, 0, 0));
496   EXPECT_TRUE(character_composer.composed_character().empty());
497 }
498
499 TEST(CharacterComposerTest, HexadecimalSequenceAndDeadKey) {
500   CharacterComposer character_composer;
501   // LATIN SMALL LETTER A WITH ACUTE
502   ExpectCharacterComposed(&character_composer, GDK_KEY_dead_acute, GDK_KEY_a, 0,
503                           string16(1, 0x00E1));
504   // HIRAGANA LETTER A (U+3042) with dead_acute ignored.
505   ExpectKeyFiltered(&character_composer, GDK_KEY_U,
506                     EF_SHIFT_DOWN | EF_CONTROL_DOWN);
507   ExpectCharacterComposed(&character_composer, GDK_KEY_3, GDK_KEY_0,
508                           GDK_KEY_dead_acute, GDK_KEY_4,  GDK_KEY_2,
509                           GDK_KEY_space, 0, string16(1, 0x3042));
510   // LATIN CAPITAL LETTER U WITH ACUTE while 'U' is pressed with Ctrl+Shift.
511   ExpectKeyFiltered(&character_composer, GDK_KEY_dead_acute, 0);
512   EXPECT_TRUE(character_composer.FilterKeyPress(
513       GDK_KEY_U, 0, EF_SHIFT_DOWN | EF_CONTROL_DOWN));
514   EXPECT_EQ(string16(1, 0x00DA), character_composer.composed_character());
515 }
516
517 TEST(CharacterComposerTest, BlacklistedKeyeventsTest) {
518   CharacterComposer character_composer;
519   EXPECT_TRUE(character_composer.FilterKeyPress(GDK_KEY_dead_acute, 0, 0));
520   EXPECT_FALSE(character_composer.FilterKeyPress(GDK_KEY_s, 0, 0));
521   ASSERT_EQ(1U, character_composer.composed_character().size());
522   EXPECT_EQ(GDK_KEY_apostrophe, character_composer.composed_character().at(0));
523 }
524
525 }  // namespace ui