| // Copyright 2010, Google Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #include "composer/internal/char_chunk.h" |
| #include "composer/internal/composition.h" |
| #include "composer/internal/transliterators_ja.h" |
| #include "composer/table.h" |
| #include "testing/base/public/gunit.h" |
| |
| namespace mozc { |
| namespace composer { |
| |
| // This macro is ported from base/basictypes.h. Due to WinNT.h has |
| // the same macro, this macro should be undefined at the end of this |
| // file. |
| // TODO(komatsu): Move this macro to base or testing. |
| #ifndef ARRAYSIZE |
| #define UNDEFINE_ARRAYSIZE |
| #define ARRAYSIZE(a) \ |
| ((sizeof(a) / sizeof(*(a))) / \ |
| static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) |
| #endif // ARRAYSIZE |
| |
| namespace { |
| string GetString(const Composition &composition) { |
| string output; |
| composition.GetString(&output); |
| return output; |
| } |
| } // anonymous namespace |
| |
| class CompositionTest : public testing::Test { |
| protected: |
| virtual void SetUp() { |
| raw_t12r_ = Transliterators::GetRawStringSelector(); |
| conv_t12r_ = Transliterators::GetConversionStringSelector(); |
| } |
| |
| const TransliteratorInterface *raw_t12r_; |
| const TransliteratorInterface *conv_t12r_; |
| }; |
| |
| static int InitComposition(Composition* comp) { |
| static const struct TestCharChunk { |
| const char* conversion; |
| const char* pending; |
| const char* raw; |
| } test_chunks[] = { |
| // "あ ky き った っty" (9 chars) |
| // a ky ki tta tty |
| // "あ" |
| { "\xe3\x81\x82", "", "a" }, |
| { "", "ky", "ky" }, |
| // "き" |
| { "\xe3\x81\x8d", "", "ki" }, |
| // "った" |
| { "\xe3\x81\xa3\xe3\x81\x9f", "", "tta" }, |
| // "っ" |
| { "\xe3\x81\xa3", "ty", "tty" }, |
| }; |
| static const int test_chunks_size = ARRAYSIZE(test_chunks); |
| CharChunkList::iterator it; |
| comp->MaybeSplitChunkAt(0, &it); |
| for (int i = 0; i < test_chunks_size; ++i) { |
| const TestCharChunk& data = test_chunks[i]; |
| CharChunk* chunk = comp->InsertChunk(&it); |
| chunk->set_conversion(data.conversion); |
| chunk->set_pending(data.pending); |
| chunk->set_raw(data.raw); |
| } |
| return test_chunks_size; |
| } |
| |
| static CharChunk *AppendChunk(const char *conversion, |
| const char *pending, |
| const char *raw, |
| Composition *comp) { |
| CharChunkList::iterator it; |
| comp->MaybeSplitChunkAt(comp->GetLength(), &it); |
| |
| CharChunk* chunk = comp->InsertChunk(&it); |
| chunk->set_conversion(conversion); |
| chunk->set_pending(pending); |
| chunk->set_raw(raw); |
| return chunk; |
| } |
| |
| TEST_F(CompositionTest, GetChunkLength) { |
| static const struct TestCase { |
| const char* conversion; |
| const char* pending; |
| const char* raw; |
| const int expected_conv_length; |
| const int expected_raw_length; |
| } test_cases[] = { |
| // "あ" |
| { "\xe3\x81\x82", "", "a", 1, 1 }, |
| { "", "ky", "ky", 2, 2 }, |
| // "き" |
| { "\xe3\x81\x8d", "", "ki", 1, 2 }, |
| // "った" |
| { "\xe3\x81\xa3\xe3\x81\x9f", "", "tta", 2, 3 }, |
| // "っ" |
| { "\xe3\x81\xa3", "ty", "tty", 3, 3 }, |
| }; |
| Composition comp; |
| CharChunk *chunk = AppendChunk("", "", "", &comp); |
| |
| for (int i = 0; i < ARRAYSIZE(test_cases); ++i) { |
| const TestCase& test = test_cases[i]; |
| chunk->set_conversion(test.conversion); |
| chunk->set_pending(test.pending); |
| chunk->set_raw(test.raw); |
| |
| const int conv_length = chunk->GetLength(conv_t12r_); |
| EXPECT_EQ(test.expected_conv_length, conv_length); |
| |
| const int raw_length = chunk->GetLength(raw_t12r_); |
| EXPECT_EQ(test.expected_raw_length, raw_length); |
| } |
| } |
| |
| namespace { |
| bool TestGetChunkAt(Composition *comp, |
| const TransliteratorInterface *transliterator, |
| const size_t index, |
| const size_t expected_index, |
| const size_t expected_inner_position) { |
| CharChunkList::iterator it; |
| CharChunkList::const_iterator expected_it; |
| size_t inner_position; |
| |
| expected_it = comp->GetCharChunkList().begin(); |
| for (int j = 0; j < expected_index; ++j, ++expected_it); |
| |
| comp->GetChunkAt(index, transliterator, &it, &inner_position); |
| if (it == comp->GetCharChunkList().end()) { |
| EXPECT_TRUE(expected_it == it); |
| EXPECT_EQ(expected_inner_position, inner_position); |
| } else { |
| string result, expected_result; |
| EXPECT_EQ((*expected_it)->conversion(), (*it)->conversion()); |
| EXPECT_EQ((*expected_it)->pending(), (*it)->pending()); |
| EXPECT_EQ((*expected_it)->raw(), (*it)->raw()); |
| EXPECT_EQ(expected_inner_position, inner_position); |
| } |
| return true; |
| } |
| } // anonymous namespace |
| |
| TEST_F(CompositionTest, GetChunkAt) { |
| Composition comp; |
| InitComposition(&comp); |
| const TransliteratorInterface *transliterator; |
| |
| transliterator = Transliterators::GetConversionStringSelector(); |
| TestGetChunkAt(&comp, transliterator, 0, 0, 0); |
| TestGetChunkAt(&comp, transliterator, 1, 0, 1); |
| TestGetChunkAt(&comp, transliterator, 2, 1, 1); |
| TestGetChunkAt(&comp, transliterator, 3, 1, 2); |
| TestGetChunkAt(&comp, transliterator, 4, 2, 1); |
| TestGetChunkAt(&comp, transliterator, 5, 3, 1); |
| TestGetChunkAt(&comp, transliterator, 6, 3, 2); |
| TestGetChunkAt(&comp, transliterator, 7, 4, 1); |
| TestGetChunkAt(&comp, transliterator, 8, 4, 2); |
| TestGetChunkAt(&comp, transliterator, 9, 4, 3); |
| TestGetChunkAt(&comp, transliterator, 10, 4, 3); // end |
| TestGetChunkAt(&comp, transliterator, 11, 4, 3); // end |
| |
| transliterator = Transliterators::GetRawStringSelector(); |
| TestGetChunkAt(&comp, transliterator, 0, 0, 0); |
| TestGetChunkAt(&comp, transliterator, 1, 0, 1); |
| TestGetChunkAt(&comp, transliterator, 2, 1, 1); |
| TestGetChunkAt(&comp, transliterator, 3, 1, 2); |
| TestGetChunkAt(&comp, transliterator, 4, 2, 1); |
| TestGetChunkAt(&comp, transliterator, 5, 2, 2); |
| TestGetChunkAt(&comp, transliterator, 6, 3, 1); |
| TestGetChunkAt(&comp, transliterator, 7, 3, 2); |
| TestGetChunkAt(&comp, transliterator, 8, 3, 3); |
| TestGetChunkAt(&comp, transliterator, 9, 4, 1); |
| TestGetChunkAt(&comp, transliterator, 10, 4, 2); |
| TestGetChunkAt(&comp, transliterator, 11, 4, 3); |
| TestGetChunkAt(&comp, transliterator, 12, 4, 3); // end |
| TestGetChunkAt(&comp, transliterator, 13, 4, 3); // end |
| } |
| |
| TEST_F(CompositionTest, GetString) { |
| Composition comp; |
| InitComposition(&comp); |
| string composition; |
| |
| const size_t dummy_position = 0; |
| |
| // Test RAW mode |
| comp.SetDisplayMode(dummy_position, |
| Transliterators::GetRawStringSelector()); |
| comp.GetString(&composition); |
| EXPECT_EQ("akykittatty", composition); |
| |
| // Test CONVERSION mode |
| comp.SetDisplayMode(dummy_position, |
| Transliterators::GetConversionStringSelector()); |
| comp.GetString(&composition); |
| // "あkyきったっty" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f\xe3\x81" |
| "\xa3\x74\x79", composition); |
| } |
| |
| TEST_F(CompositionTest, GetStringWithDisplayMode) { |
| Composition comp; |
| // "も" |
| AppendChunk("\xe3\x82\x82", "", "mo", &comp); |
| // "ず" |
| AppendChunk("\xe3\x81\x9a", "", "z", &comp); |
| // "く" |
| AppendChunk("\xe3\x81\x8f", "", "c", &comp); |
| |
| string composition; |
| comp.GetStringWithTransliterator( |
| Transliterators::GetConversionStringSelector(), &composition); |
| // "もずく" |
| EXPECT_EQ("\xe3\x82\x82\xe3\x81\x9a\xe3\x81\x8f", composition); |
| |
| comp.GetStringWithTransliterator( |
| Transliterators::GetRawStringSelector(), &composition); |
| EXPECT_EQ("mozc", composition); |
| } |
| |
| TEST_F(CompositionTest, SplitRawChunk) { |
| static const struct TestCase { |
| const char* conversion; |
| const char* pending; |
| const char* raw; |
| const int position; |
| const char* expected_left_conversion; |
| const char* expected_left_pending; |
| const char* expected_left_raw; |
| const char* expected_right_conversion; |
| const char* expected_right_pending; |
| const char* expected_right_raw; |
| } test_cases[] = { |
| // "あ", "あ" |
| { "\xe3\x81\x82", "", "a", 0, "", "", "", "\xe3\x81\x82", "", "a" }, |
| { "", "ky", "ky", 1, "", "k", "k", "", "y", "y" }, |
| // "き" |
| { "\xe3\x81\x8d", "", "ki", 1, "k", "", "k", "i", "", "i" }, |
| // "った" |
| { "\xe3\x81\xa3\xe3\x81\x9f", "", "tta", 1, "t", "", "t", "ta", "", "ta" }, |
| // "った" |
| { "\xe3\x81\xa3\xe3\x81\x9f", "", "tta", 2, "tt", "", "tt", "a", "", "a" }, |
| // "っ", "っ" |
| { "\xe3\x81\xa3", "ty", "tty", 1, "\xe3\x81\xa3", "", "t", "", "ty", "ty" }, |
| // "っ", "っ" |
| { "\xe3\x81\xa3", "ty", "tty", 2, "\xe3\x81\xa3", "t", "tt", "", "y", "y" }, |
| // "っ", "っ" |
| { "\xe3\x81\xa3", "ty", "tty", 3, "", "", "", "\xe3\x81\xa3", "ty", "tty" }, |
| }; |
| for (int i = 0; i < ARRAYSIZE(test_cases); ++i) { |
| const TestCase& test = test_cases[i]; |
| CharChunk right_orig_chunk; |
| CharChunk left_new_chunk; |
| right_orig_chunk.set_conversion(test.conversion); |
| right_orig_chunk.set_pending(test.pending); |
| right_orig_chunk.set_raw(test.raw); |
| right_orig_chunk.SplitChunk(raw_t12r_, test.position, &left_new_chunk); |
| |
| EXPECT_EQ(test.expected_left_conversion, left_new_chunk.conversion()); |
| EXPECT_EQ(test.expected_left_pending, left_new_chunk.pending()); |
| EXPECT_EQ(test.expected_left_raw, left_new_chunk.raw()); |
| |
| EXPECT_EQ(test.expected_right_conversion, right_orig_chunk.conversion()); |
| EXPECT_EQ(test.expected_right_pending, right_orig_chunk.pending()); |
| EXPECT_EQ(test.expected_right_raw, right_orig_chunk.raw()); |
| } |
| } |
| |
| TEST_F(CompositionTest, SplitConversionChunk) { |
| static const struct TestCase { |
| const char* conversion; |
| const char* pending; |
| const char* raw; |
| const int position; |
| const char* expected_left_conversion; |
| const char* expected_left_pending; |
| const char* expected_left_raw; |
| const char* expected_right_conversion; |
| const char* expected_right_pending; |
| const char* expected_right_raw; |
| } test_cases[] = { |
| // "あ", "あ" |
| { "\xe3\x81\x82", "", "a", 0, "", "", "", "\xe3\x81\x82", "", "a" }, |
| { "", "ky", "ky", 1, "", "k", "k", "", "y", "y" }, |
| // "きょ", "き", "き", "ょ", "ょ" |
| { "\xe3\x81\x8d\xe3\x82\x87", "", "kyo", 1, "\xe3\x81\x8d", "", |
| "\xe3\x81\x8d", "\xe3\x82\x87", "", "\xe3\x82\x87" }, |
| // "っ", "っ" |
| { "\xe3\x81\xa3", "t", "tt", 1, "\xe3\x81\xa3", "", "t", "", "t", "t" }, |
| // "った", "っ", "っ", "た", "た" |
| { "\xe3\x81\xa3\xe3\x81\x9f", "", "tta", 1, "\xe3\x81\xa3", "", |
| "\xe3\x81\xa3", "\xe3\x81\x9f", "", "\xe3\x81\x9f" }, |
| // "っ", "っ" |
| { "\xe3\x81\xa3", "ty", "tty", 1, "\xe3\x81\xa3", "", "t", "", "ty", "ty" }, |
| // "っ", "っ" |
| { "\xe3\x81\xa3", "ty", "tty", 2, "\xe3\x81\xa3", "t", "tt", "", "y", "y" }, |
| // "っ", "っ" |
| { "\xe3\x81\xa3", "ty", "tty", 3, "", "", "", "\xe3\x81\xa3", "ty", "tty" }, |
| }; |
| for (int i = 0; i < ARRAYSIZE(test_cases); ++i) { |
| const TestCase& test = test_cases[i]; |
| CharChunk right_orig_chunk; |
| CharChunk left_new_chunk; |
| right_orig_chunk.set_conversion(test.conversion); |
| right_orig_chunk.set_pending(test.pending); |
| right_orig_chunk.set_raw(test.raw); |
| right_orig_chunk.SplitChunk(conv_t12r_, test.position, &left_new_chunk); |
| |
| EXPECT_EQ(test.expected_left_conversion, left_new_chunk.conversion()); |
| EXPECT_EQ(test.expected_left_pending, left_new_chunk.pending()); |
| EXPECT_EQ(test.expected_left_raw, left_new_chunk.raw()); |
| |
| EXPECT_EQ(test.expected_right_conversion, right_orig_chunk.conversion()); |
| EXPECT_EQ(test.expected_right_pending, right_orig_chunk.pending()); |
| EXPECT_EQ(test.expected_right_raw, right_orig_chunk.raw()); |
| } |
| } |
| |
| TEST_F(CompositionTest, MaybeSplitChunkAt) { |
| static const struct TestCase { |
| const int position; |
| const bool expected_raw_result; |
| const bool expected_conv_result; |
| const int expected_raw_chunks_size; |
| const int expected_conv_chunks_size; |
| } test_cases[] = { |
| // "あ ky き った っty" (9 chars) |
| // a ky ki tta tty (11 chars) |
| { 0, false, false, 5, 5 }, |
| { 1, false, false, 5, 5 }, |
| { 2, true, true, 6, 6 }, |
| { 3, false, false, 5, 5 }, |
| { 4, true, false, 6, 5 }, |
| { 5, false, true, 5, 6 }, |
| { 6, true, false, 6, 5 }, |
| { 7, true, true, 6, 6 }, |
| { 8, false, true, 5, 6 }, |
| { 9, true, false, 6, 5 }, |
| { 10, true, false, 6, 5 }, |
| { 11, false, false, 5, 5 }, |
| { 12, false, false, 5, 5 }, |
| }; |
| const size_t dummy_position = 0; |
| for (int i = 0; i < ARRAYSIZE(test_cases); ++i) { |
| const TestCase& test = test_cases[i]; |
| |
| // Test RAW mode |
| Composition raw_comp; |
| InitComposition(&raw_comp); |
| raw_comp.SetDisplayMode(dummy_position, raw_t12r_); |
| CharChunkList::iterator raw_it; |
| |
| raw_comp.MaybeSplitChunkAt(test.position, &raw_it); |
| const size_t raw_chunks_size = raw_comp.GetCharChunkList().size(); |
| EXPECT_EQ(test.expected_raw_chunks_size, raw_chunks_size); |
| |
| // Test CONVERSION mode |
| Composition conv_comp; |
| InitComposition(&conv_comp); |
| conv_comp.SetDisplayMode(dummy_position, conv_t12r_); |
| CharChunkList::iterator conv_it; |
| |
| conv_comp.MaybeSplitChunkAt(test.position, &conv_it); |
| const size_t conv_chunks_size = conv_comp.GetCharChunkList().size(); |
| EXPECT_EQ(test.expected_conv_chunks_size, conv_chunks_size); |
| } |
| } |
| |
| namespace { |
| string GetDeletedString(const TransliteratorInterface* t12r, |
| const int position) { |
| Composition comp; |
| InitComposition(&comp); |
| comp.SetDisplayMode(0, t12r); |
| comp.DeleteAt(position); |
| string composition; |
| comp.GetString(&composition); |
| return composition; |
| } |
| } // anonymous namespace |
| |
| TEST_F(CompositionTest, DeleteAt) { |
| const TransliteratorInterface* conv_t12r = |
| Transliterators::GetConversionStringSelector(); |
| const TransliteratorInterface* raw_t12r = |
| Transliterators::GetRawStringSelector(); |
| |
| // "あkyきったっty" is the original string |
| |
| // "kyきったっty" |
| EXPECT_EQ("\x6b\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f\xe3\x81\xa3\x74\x79", |
| GetDeletedString(conv_t12r, 0)); |
| // "あyきったっty" |
| EXPECT_EQ("\xe3\x81\x82\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f\xe3\x81\xa3" |
| "\x74\x79", |
| GetDeletedString(conv_t12r, 1)); |
| // "あkきったっty" |
| EXPECT_EQ("\xe3\x81\x82\x6b\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f\xe3\x81\xa3" |
| "\x74\x79", |
| GetDeletedString(conv_t12r, 2)); |
| // "あkyったっty" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\xa3\xe3\x81\x9f\xe3\x81\xa3\x74\x79", |
| GetDeletedString(conv_t12r, 3)); |
| // "あkyきたっty" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\x9f\xe3\x81\xa3\x74\x79", |
| GetDeletedString(conv_t12r, 4)); |
| // "あkyきっっty" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\xa3\x74\x79", |
| GetDeletedString(conv_t12r, 5)); |
| // "あkyきったty" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f\x74\x79", |
| GetDeletedString(conv_t12r, 6)); |
| // "あkyきったっy" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f\xe3\x81" |
| "\xa3\x79", |
| GetDeletedString(conv_t12r, 7)); |
| // "あkyきったっt" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f\xe3\x81" |
| "\xa3\x74", |
| GetDeletedString(conv_t12r, 8)); |
| // "あkyきったっty" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f" |
| "\xe3\x81\xa3\x74\x79", |
| GetDeletedString(conv_t12r, 9)); // end |
| // "あkyきったっty" |
| EXPECT_EQ("\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\xa3\xe3\x81\x9f" |
| "\xe3\x81\xa3\x74\x79", |
| GetDeletedString(conv_t12r, -1)); |
| |
| // "akykittatty" is the original string |
| EXPECT_EQ("kykittatty", GetDeletedString(raw_t12r, 0)); |
| EXPECT_EQ("aykittatty", GetDeletedString(raw_t12r, 1)); |
| EXPECT_EQ("akkittatty", GetDeletedString(raw_t12r, 2)); |
| EXPECT_EQ("akyittatty", GetDeletedString(raw_t12r, 3)); |
| EXPECT_EQ("akykttatty", GetDeletedString(raw_t12r, 4)); |
| EXPECT_EQ("akykitatty", GetDeletedString(raw_t12r, 5)); |
| EXPECT_EQ("akykitatty", GetDeletedString(raw_t12r, 6)); |
| EXPECT_EQ("akykitttty", GetDeletedString(raw_t12r, 7)); |
| EXPECT_EQ("akykittaty", GetDeletedString(raw_t12r, 8)); |
| EXPECT_EQ("akykittaty", GetDeletedString(raw_t12r, 9)); |
| EXPECT_EQ("akykittatt", GetDeletedString(raw_t12r, 10)); |
| EXPECT_EQ("akykittatty", GetDeletedString(raw_t12r, 11)); // end |
| EXPECT_EQ("akykittatty", GetDeletedString(raw_t12r, -1)); |
| } |
| |
| namespace { |
| |
| void InitTable(Table* table) { |
| // "い" |
| table->AddRule("i", "\xe3\x81\x84", ""); |
| // "き" |
| table->AddRule("ki", "\xe3\x81\x8d", ""); |
| // "きぃ" |
| table->AddRule("kyi", "\xe3\x81\x8d\xe3\x81\x83", ""); |
| // "ち" |
| table->AddRule("ti", "\xe3\x81\xa1", ""); |
| // "ちぁ" |
| table->AddRule("tya", "\xe3\x81\xa1\xe3\x81\x81", ""); |
| // "ちぃ" |
| table->AddRule("tyi", "\xe3\x81\xa1\xe3\x81\x83", ""); |
| // "や" |
| table->AddRule("ya", "\xe3\x82\x84", ""); |
| // "っ" |
| table->AddRule("yy", "\xe3\x81\xa3", "y"); |
| } |
| |
| string GetInsertedString(const TransliteratorInterface* t12r, |
| const size_t position, |
| const string &input) { |
| Composition comp; |
| InitComposition(&comp); |
| |
| Table table; |
| InitTable(&table); |
| comp.SetTable(&table); |
| comp.SetDisplayMode(0, t12r); |
| comp.InsertAt(position, input); |
| |
| string composition; |
| comp.GetString(&composition); |
| return composition; |
| } |
| } // anonymous namespace |
| |
| TEST_F(CompositionTest, InsertAt) { |
| const TransliteratorInterface* conv_t12r = |
| Transliterators::GetConversionStringSelector(); |
| const TransliteratorInterface* raw_t12r = |
| Transliterators::GetRawStringSelector(); |
| |
| // "あkyきったっty" is the original string |
| |
| // "いあkyきったっty" |
| EXPECT_EQ("\xe3\x81\x84\xe3\x81\x82\x6b\x79\xe3\x81\x8d\xe3\x81\xa3" |
| "\xe3\x81\x9f\xe3\x81\xa3\x74\x79", |
| GetInsertedString(conv_t12r, 0, "i")); |
| |
| // "あいkyきったっty" |
| EXPECT_EQ("\xE3\x81\x82\xE3\x81\x84\x6B\x79\xE3\x81\x8D\xE3\x81\xA3" |
| "\xE3\x81\x9F\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 1, "i")); |
| |
| // "あきyきったっty" |
| EXPECT_EQ("\xE3\x81\x82\xE3\x81\x8D\x79\xE3\x81\x8D\xE3\x81\xA3" |
| "\xE3\x81\x9F\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 2, "i")); |
| |
| // "あきぃきったっty" |
| EXPECT_EQ("\xE3\x81\x82\xE3\x81\x8D\xE3\x81\x83\xE3\x81\x8D\xE3\x81\xA3" |
| "\xE3\x81\x9F\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 3, "i")); |
| |
| // "あkyきいったっty" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\xE3\x81\x8D\xE3\x81\x84\xE3\x81\xA3" |
| "\xE3\x81\x9F\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 4, "i")); |
| |
| // "あkyきっいたっty" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\xE3\x81\x8D\xE3\x81\xA3\xE3\x81\x84" |
| "\xE3\x81\x9F\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 5, "i")); |
| |
| // "あkyきったっちぃ" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\xE3\x81\x8D\xE3\x81\xA3\xE3\x81\x9F" |
| "\xE3\x81\xA3\xE3\x81\xA1\xE3\x81\x83", |
| GetInsertedString(conv_t12r, 9, "i")); |
| |
| // "yあkyきったっty" |
| EXPECT_EQ("\x79\xE3\x81\x82\x6B\x79\xE3\x81\x8D\xE3\x81\xA3\xE3\x81\x9F" |
| "\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 0, "y")); |
| |
| // "あykyきったっty" |
| EXPECT_EQ("\xE3\x81\x82\x79\x6B\x79\xE3\x81\x8D\xE3\x81\xA3\xE3\x81\x9F" |
| "\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 1, "y")); |
| |
| // "あkyyきったっty" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\x79\xE3\x81\x8D\xE3\x81\xA3\xE3\x81\x9F" |
| "\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 2, "y")); |
| |
| // "あkyyきったっty" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\x79\xE3\x81\x8D\xE3\x81\xA3\xE3\x81\x9F" |
| "\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 3, "y")); |
| |
| // "あkyきyったっty" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\xE3\x81\x8D\x79\xE3\x81\xA3\xE3\x81\x9F" |
| "\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 4, "y")); |
| |
| // "あkyきっyたっty" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\xE3\x81\x8D\xE3\x81\xA3\x79\xE3\x81\x9F" |
| "\xE3\x81\xA3\x74\x79", |
| GetInsertedString(conv_t12r, 5, "y")); |
| |
| // "あkyきったっちぃ" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\xE3\x81\x8D\xE3\x81\xA3\xE3\x81\x9F" |
| "\xE3\x81\xA3\xE3\x81\xA1\xE3\x81\x83", |
| GetInsertedString(conv_t12r, 9, "i")); // end |
| |
| // "あkyきったっtyy" |
| EXPECT_EQ("\xE3\x81\x82\x6B\x79\xE3\x81\x8D\xE3\x81\xA3\xE3\x81\x9F" |
| "\xE3\x81\xA3\x74\x79\x79", |
| GetInsertedString(conv_t12r, 9, "y")); // end |
| |
| |
| // "akykittatty" is the original string |
| EXPECT_EQ("iakykittatty", GetInsertedString(raw_t12r, 0, "i")); |
| |
| EXPECT_EQ("aikykittatty", GetInsertedString(raw_t12r, 1, "i")); |
| |
| EXPECT_EQ("akiykittatty", GetInsertedString(raw_t12r, 2, "i")); |
| |
| EXPECT_EQ("akyikittatty", GetInsertedString(raw_t12r, 3, "i")); |
| |
| EXPECT_EQ("akykiittatty", GetInsertedString(raw_t12r, 4, "i")); |
| |
| EXPECT_EQ("akykiittatty", GetInsertedString(raw_t12r, 5, "i")); |
| |
| EXPECT_EQ("akykittattyi", GetInsertedString(raw_t12r, 11, "i")); // end |
| } |
| |
| TEST_F(CompositionTest, ConvertPosition) { |
| // Test against http://b/1550597 |
| Composition comp; |
| |
| // Invalid positions. |
| EXPECT_EQ(0, comp.ConvertPosition(static_cast<size_t>(-1), |
| conv_t12r_, raw_t12r_)); |
| EXPECT_EQ(0, comp.ConvertPosition(0, conv_t12r_, raw_t12r_)); |
| EXPECT_EQ(0, comp.ConvertPosition(1, conv_t12r_, raw_t12r_)); |
| EXPECT_EQ(0, comp.ConvertPosition(0, raw_t12r_, conv_t12r_)); |
| EXPECT_EQ(0, comp.ConvertPosition(static_cast<size_t>(-1), |
| raw_t12r_, conv_t12r_)); |
| EXPECT_EQ(0, comp.ConvertPosition(1, raw_t12r_, conv_t12r_)); |
| |
| // "ね" |
| AppendChunk("\xe3\x81\xad", "", "ne", &comp); |
| // "っと" |
| AppendChunk("\xe3\x81\xa3\xe3\x81\xa8", "", "tto", &comp); |
| |
| // "|ねっと" -> "|netto" |
| EXPECT_EQ(0, comp.ConvertPosition(0, conv_t12r_, raw_t12r_)); |
| // "ね|っと" -> "ne|tto" |
| EXPECT_EQ(2, comp.ConvertPosition(1, conv_t12r_, raw_t12r_)); |
| // "ねっ|と" -> "net|to" |
| EXPECT_EQ(3, comp.ConvertPosition(2, conv_t12r_, raw_t12r_)); |
| // "ねっと|" -> "netto|" |
| EXPECT_EQ(5, comp.ConvertPosition(3, conv_t12r_, raw_t12r_)); |
| |
| // Invalid positions. |
| EXPECT_EQ(5, comp.ConvertPosition(static_cast<size_t>(-1), |
| conv_t12r_, raw_t12r_)); |
| EXPECT_EQ(5, comp.ConvertPosition(4, conv_t12r_, raw_t12r_)); |
| |
| // "|netto" -> "|ねっと" |
| EXPECT_EQ(0, comp.ConvertPosition(0, raw_t12r_, conv_t12r_)); |
| // "n|etto" -> "ね|っと" |
| EXPECT_EQ(1, comp.ConvertPosition(1, raw_t12r_, conv_t12r_)); |
| // "ne|tto" -> "ね|っと" |
| EXPECT_EQ(1, comp.ConvertPosition(2, raw_t12r_, conv_t12r_)); |
| // "net|to" -> "ねっ|と" |
| EXPECT_EQ(2, comp.ConvertPosition(3, raw_t12r_, conv_t12r_)); |
| // "nett|o" -> "ねっと|" |
| EXPECT_EQ(3, comp.ConvertPosition(4, raw_t12r_, conv_t12r_)); |
| // "netto|" -> "ねっと|" |
| EXPECT_EQ(3, comp.ConvertPosition(5, raw_t12r_, conv_t12r_)); |
| // Invalid positions. |
| EXPECT_EQ(3, comp.ConvertPosition(static_cast<size_t>(-1), |
| raw_t12r_, conv_t12r_)); |
| EXPECT_EQ(3, comp.ConvertPosition(6, raw_t12r_, conv_t12r_)); |
| |
| CharChunkList::iterator chunk_it; |
| size_t inner_position; |
| comp.GetChunkAt(5, raw_t12r_, &chunk_it, &inner_position); |
| |
| EXPECT_EQ("tto", (*chunk_it)->raw()); |
| EXPECT_EQ(3, inner_position); |
| } |
| |
| TEST_F(CompositionTest, SetDisplayMode) { |
| Composition comp; |
| // "も" |
| AppendChunk("\xe3\x82\x82", "", "mo", &comp); |
| // "ず" |
| AppendChunk("\xe3\x81\x9a", "", "zu", &comp); |
| // "く" |
| AppendChunk("\xe3\x81\x8f", "", "ku", &comp); |
| |
| CharChunkList::iterator chunk_it; |
| size_t inner_position; |
| comp.GetChunkAt(0, conv_t12r_, &chunk_it, &inner_position); |
| EXPECT_EQ("mo", (*chunk_it)->raw()); |
| EXPECT_EQ(0, inner_position); |
| comp.GetChunkAt(1, conv_t12r_, &chunk_it, &inner_position); |
| EXPECT_EQ("mo", (*chunk_it)->raw()); |
| EXPECT_EQ(1, inner_position); |
| comp.GetChunkAt(2, conv_t12r_, &chunk_it, &inner_position); |
| EXPECT_EQ("zu", (*chunk_it)->raw()); |
| EXPECT_EQ(1, inner_position); |
| comp.GetChunkAt(3, conv_t12r_, &chunk_it, &inner_position); |
| EXPECT_EQ("ku", (*chunk_it)->raw()); |
| EXPECT_EQ(1, inner_position); |
| |
| EXPECT_EQ(6, comp.SetDisplayMode(1, raw_t12r_)); |
| EXPECT_EQ(3, comp.SetDisplayMode(2, conv_t12r_)); |
| EXPECT_EQ(6, comp.SetDisplayMode(2, raw_t12r_)); |
| } |
| |
| TEST_F(CompositionTest, GetStringWithTrimMode) { |
| Composition comp; |
| Table table; |
| // "か" |
| table.AddRule("ka", "\xe3\x81\x8b", ""); |
| // "ん" |
| table.AddRule("n", "\xe3\x82\x93", ""); |
| // This makes the above rule ambiguous. |
| // "な" |
| table.AddRule("na", "\xe3\x81\xaa", ""); |
| comp.SetTable(&table); |
| |
| string output_empty; |
| comp.GetStringWithTrimMode(TRIM, &output_empty); |
| EXPECT_TRUE(output_empty.empty()); |
| |
| size_t pos = 0; |
| pos = comp.InsertAt(pos, "k"); |
| pos = comp.InsertAt(pos, "a"); |
| pos = comp.InsertAt(pos, "n"); |
| |
| string output_trim; |
| comp.GetStringWithTrimMode(TRIM, &output_trim); |
| // "か" |
| EXPECT_EQ("\xe3\x81\x8b", output_trim); |
| |
| string output_asis; |
| comp.GetStringWithTrimMode(ASIS, &output_asis); |
| // "かn" |
| EXPECT_EQ("\xe3\x81\x8b\x6e", output_asis); |
| |
| string output_fix; |
| comp.GetStringWithTrimMode(FIX, &output_asis); |
| // "かん" |
| EXPECT_EQ("\xe3\x81\x8b\xe3\x82\x93", output_asis); |
| } |
| |
| TEST_F(CompositionTest, InsertKeyAndPreeditAt) { |
| Composition comp; |
| Table table; |
| // "す゛", "ず" |
| table.AddRule("\xe3\x81\x99\xe3\x82\x9b", "\xe3\x81\x9a", ""); |
| // "く゛", "ぐ" |
| table.AddRule("\xe3\x81\x8f\xe3\x82\x9b", "\xe3\x81\x90", ""); |
| comp.SetTable(&table); |
| |
| size_t pos = 0; |
| // "も" |
| pos = comp.InsertKeyAndPreeditAt(pos, "m", "\xe3\x82\x82"); |
| // "す" |
| pos = comp.InsertKeyAndPreeditAt(pos, "r", "\xe3\x81\x99"); |
| // "゛" |
| pos = comp.InsertKeyAndPreeditAt(pos, "@", "\xe3\x82\x9b"); |
| // "く" |
| pos = comp.InsertKeyAndPreeditAt(pos, "h", "\xe3\x81\x8f"); |
| pos = comp.InsertKeyAndPreeditAt(pos, "!", "!"); |
| |
| string comp_str; |
| comp.GetString(&comp_str); |
| // "もずく!" |
| EXPECT_EQ("\xe3\x82\x82\xe3\x81\x9a\xe3\x81\x8f\x21", comp_str); |
| |
| string comp_ascii_str; |
| comp.GetStringWithTransliterator(raw_t12r_, &comp_ascii_str); |
| EXPECT_EQ("mr@h!", comp_ascii_str); |
| } |
| |
| TEST_F(CompositionTest, InsertKey_ForN) { |
| Composition comp; |
| Table table; |
| table.AddRule("a", "[A]", ""); |
| table.AddRule("n", "[N]", ""); |
| table.AddRule("nn", "[N]", ""); |
| table.AddRule("na", "[NA]", ""); |
| table.AddRule("nya", "[NYA]", ""); |
| table.AddRule("ya", "[YA]", ""); |
| table.AddRule("ka", "[KA]", ""); |
| comp.SetTable(&table); |
| |
| size_t pos = 0; |
| pos = comp.InsertAt(pos, "n"); |
| pos = comp.InsertAt(pos, "y"); |
| pos = comp.InsertAt(pos, "n"); |
| pos = comp.InsertAt(pos, "y"); |
| pos = comp.InsertAt(pos, "a"); |
| |
| string comp_str; |
| comp.GetString(&comp_str); |
| EXPECT_EQ("ny[NYA]", comp_str); |
| } |
| |
| TEST_F(CompositionTest, GetStringWithDisplayMode_ForKana) { |
| Composition comp; |
| Table table; |
| // Empty table is OK. |
| comp.SetTable(&table); |
| |
| size_t pos = 0; |
| // "も" |
| pos = comp.InsertKeyAndPreeditAt(pos, "m", "\xe3\x82\x82"); |
| |
| string comp_str; |
| comp.GetStringWithTransliterator(raw_t12r_, &comp_str); |
| EXPECT_EQ("m", comp_str); |
| } |
| |
| TEST_F(CompositionTest, InputMode) { |
| const TransliteratorInterface *kFullKatakanaT12r = |
| TransliteratorsJa::GetFullKatakanaTransliterator(); |
| const TransliteratorInterface *kHalfAsciiT12r = |
| TransliteratorsJa::GetHalfAsciiTransliterator(); |
| const TransliteratorInterface *kHiraganaT12r = |
| TransliteratorsJa::GetHiraganaTransliterator(); |
| const TransliteratorInterface *kDefaultT12r = |
| Transliterators::GetConversionStringSelector(); |
| |
| Composition comp; |
| Table table; |
| // "あ" |
| table.AddRule("a", "\xE3\x81\x82", ""); |
| // "か" |
| table.AddRule("ka", "\xE3\x81\x8B", ""); |
| comp.SetTable(&table); |
| |
| size_t pos = 0; |
| pos = comp.InsertAt(pos, "k"); |
| |
| string result; |
| comp.GetString(&result); |
| // "k" |
| EXPECT_EQ("k", result); |
| |
| comp.SetInputMode(kFullKatakanaT12r); |
| pos = comp.InsertAt(pos, "a"); |
| comp.GetString(&result); |
| // If a vowel and a consonant were typed with different |
| // transliterators, these characters should not be combined. |
| // "kア" |
| EXPECT_EQ("\x6B\xE3\x82\xA2", result); |
| |
| comp.SetInputMode(kHalfAsciiT12r); |
| pos = comp.InsertAt(pos, "k"); |
| comp.GetString(&result); |
| // "kアk" |
| EXPECT_EQ("\x6B\xE3\x82\xA2\x6B", result); |
| |
| comp.SetInputMode(kHiraganaT12r); |
| pos = comp.InsertAt(pos, "a"); |
| comp.GetString(&result); |
| // "kアkあ" |
| EXPECT_EQ("\x6B\xE3\x82\xA2\x6B\xE3\x81\x82", result); |
| |
| // "|kアkあ" |
| EXPECT_EQ(kDefaultT12r, comp.GetTransliterator(0)); |
| // "k|アkあ" |
| EXPECT_EQ(kDefaultT12r, comp.GetTransliterator(1)); |
| // "kア|kあ" |
| EXPECT_EQ(kFullKatakanaT12r, comp.GetTransliterator(2)); |
| // "kアk|あ" |
| EXPECT_EQ(kHalfAsciiT12r, comp.GetTransliterator(3)); |
| // "kアkあ|" |
| EXPECT_EQ(kHiraganaT12r, comp.GetTransliterator(4)); |
| // "kアkあ...|" |
| EXPECT_EQ(kHiraganaT12r, comp.GetTransliterator(5)); |
| EXPECT_EQ(kHiraganaT12r, comp.GetTransliterator(10)); |
| } |
| |
| TEST_F(CompositionTest, Transliterator) { |
| Composition comp; |
| Table table; |
| // "あ" |
| table.AddRule("a", "\xE3\x81\x82", ""); |
| comp.SetTable(&table); |
| |
| // Insert "a" which is converted to "あ". |
| size_t pos = 0; |
| pos = comp.InsertAt(pos, "a"); |
| EXPECT_EQ(1, pos); |
| string result; |
| comp.GetString(&result); |
| // "あ" |
| EXPECT_EQ("\xE3\x81\x82", result); |
| |
| // Set transliterator for Half Ascii. |
| comp.SetTransliterator(0, pos, |
| TransliteratorsJa::GetHalfAsciiTransliterator()); |
| comp.GetString(&result); |
| EXPECT_EQ("a", result); |
| |
| // Insert "a" again. |
| pos = comp.InsertAt(pos, "a"); |
| EXPECT_EQ(2, pos); |
| result.clear(); |
| comp.GetString(&result); |
| // "aあ" |
| EXPECT_EQ("a\xE3\x81\x82", result); |
| |
| // Set transliterator for Full Katakana. |
| comp.SetTransliterator(0, pos, |
| TransliteratorsJa::GetFullKatakanaTransliterator()); |
| comp.GetString(&result); |
| // "アア" |
| EXPECT_EQ("\xE3\x82\xA2\xE3\x82\xA2", result); |
| } |
| |
| TEST_F(CompositionTest, HalfAsciiTransliterator) { |
| Composition comp; |
| Table table; |
| // "ー" |
| table.AddRule("-", "\xE3\x83\xBC", ""); |
| comp.SetTable(&table); |
| comp.SetInputMode(TransliteratorsJa::GetHalfAsciiTransliterator()); |
| |
| size_t pos = 0; |
| pos = comp.InsertKeyAndPreeditAt(pos, "-", "-"); |
| EXPECT_EQ(1, pos); |
| EXPECT_EQ("-", GetString(comp)); |
| |
| pos = comp.InsertKeyAndPreeditAt(pos, "-", "-"); |
| EXPECT_EQ(2, pos); |
| EXPECT_EQ("--", GetString(comp)); |
| } |
| |
| TEST_F(CompositionTest, Issue2190364) { |
| // This is a unittest against http://b/2190364 |
| Composition comp; |
| Table table; |
| comp.SetTable(&table); |
| |
| size_t pos = 0; |
| |
| comp.SetInputMode(TransliteratorsJa::GetFullAsciiTransliterator()); |
| // "ち" |
| pos = comp.InsertKeyAndPreeditAt(pos, "a", "\xE3\x81\xA1"); |
| // "a" |
| EXPECT_EQ("\xEF\xBD\x81", GetString(comp)); |
| |
| pos = comp.InsertAt(pos, " "); |
| // "a " |
| EXPECT_EQ("\xEF\xBD\x81\xE3\x80\x80", GetString(comp)); |
| } |
| |
| |
| TEST_F(CompositionTest, Issue1817410) { |
| // This is a unittest against http://b/2190364 |
| Composition comp; |
| const TransliteratorInterface *kNullT12r = NULL; |
| const TransliteratorInterface *kHalfAsciiT12r = |
| TransliteratorsJa::GetHalfAsciiTransliterator(); |
| Table table; |
| // "っ" |
| table.AddRule("ss", "\xE3\x81\xA3", "s"); |
| comp.SetTable(&table); |
| |
| size_t pos = 0; |
| pos = comp.InsertAt(pos, "s"); |
| pos = comp.InsertAt(pos, "s"); |
| |
| string preedit; |
| comp.GetString(&preedit); |
| // "っs" |
| EXPECT_EQ("\xE3\x81\xA3\x73", preedit); |
| |
| EXPECT_EQ(0, comp.ConvertPosition(0, kNullT12r, kHalfAsciiT12r)); |
| EXPECT_EQ(1, comp.ConvertPosition(1, kNullT12r, kHalfAsciiT12r)); |
| EXPECT_EQ(2, comp.ConvertPosition(2, kNullT12r, kHalfAsciiT12r)); |
| |
| { // "s|s" |
| CharChunkList::iterator chunk_it; |
| size_t inner_position; |
| comp.GetChunkAt(1, kNullT12r, &chunk_it, &inner_position); |
| EXPECT_EQ(1, inner_position); |
| EXPECT_EQ(2, (*chunk_it)->GetLength(kNullT12r)); |
| |
| EXPECT_EQ(0, comp.GetPosition(kHalfAsciiT12r, chunk_it)); |
| EXPECT_EQ(2, (*chunk_it)->GetLength(kHalfAsciiT12r)); |
| } |
| |
| { // "ss|" |
| CharChunkList::iterator chunk_it; |
| size_t inner_position; |
| comp.GetChunkAt(2, kNullT12r, &chunk_it, &inner_position); |
| EXPECT_EQ(2, inner_position); |
| EXPECT_EQ(2, (*chunk_it)->GetLength(kNullT12r)); |
| |
| EXPECT_EQ(0, comp.GetPosition(kHalfAsciiT12r, chunk_it)); |
| EXPECT_EQ(2, (*chunk_it)->GetLength(kHalfAsciiT12r)); |
| } |
| } |
| |
| TEST_F(CompositionTest, Issue2209634) { |
| // This is a unittest against http://b/2209634 |
| // "q@" becomes "qた@". |
| Composition comp; |
| Table table; |
| // "た" |
| table.AddRule("q", "", "\xE3\x81\x9F"); |
| // "た@", "だ" |
| table.AddRule("\xE3\x81\x9F\x40", "\xE3\x81\xA0", ""); |
| comp.SetTable(&table); |
| |
| comp.SetInputMode(TransliteratorsJa::GetHalfAsciiTransliterator()); |
| |
| size_t pos = 0; |
| pos = comp.InsertAt(pos, "q"); |
| pos = comp.InsertAt(pos, "@"); |
| |
| string preedit; |
| comp.GetString(&preedit); |
| EXPECT_EQ("q@", preedit); |
| } |
| |
| TEST_F(CompositionTest, Issue2330530) { |
| // This is a unittest against http://b/2330530 |
| // "Win" + Numpad7 becomes "Win77" instead of "Win7". |
| Composition comp; |
| Table table; |
| // "うぃ" |
| table.AddRule("wi", "\xe3\x81\x86\xe3\x81\x83", ""); |
| // "い" |
| table.AddRule("i", "\xe3\x81\x84", ""); |
| // "ん" |
| table.AddRule("n", "\xe3\x82\x93", ""); |
| // "な" |
| table.AddRule("na", "\xe3\x81\xaa", ""); |
| comp.SetTable(&table); |
| |
| comp.SetInputMode(TransliteratorsJa::GetHalfAsciiTransliterator()); |
| |
| size_t pos = 0; |
| pos = comp.InsertAt(pos, "W"); |
| pos = comp.InsertAt(pos, "i"); |
| pos = comp.InsertAt(pos, "n"); |
| |
| string preedit; |
| comp.GetString(&preedit); |
| EXPECT_EQ("Win", preedit); |
| |
| pos = comp.InsertKeyAndPreeditAt(pos, "7", "7"); |
| comp.GetString(&preedit); |
| EXPECT_EQ("Win7", preedit); |
| } |
| |
| #ifdef UNDEFINE_ARRAYSIZE |
| #undef ARRAYSIZE |
| #endif // UNDEFINE_ARRAYSIZE |
| |
| } // namespace composer |
| } // namespace mozc |