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