Home | History | Annotate | Download | only in ime
      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/events/event_constants.h"
     11 #include "ui/base/glib/glib_integers.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
    526