| // Copyright 2010-2015, 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 "session/internal/candidate_list.h" |
| |
| #include <string> |
| |
| #include "base/scoped_ptr.h" |
| #include "testing/base/public/gunit.h" |
| |
| namespace mozc { |
| namespace session { |
| |
| class CandidateListTest : public testing::Test { |
| protected: |
| virtual void SetUp() { |
| main_list_.reset(new CandidateList(true)); |
| sub_list_2_.reset(new CandidateList(true)); |
| sub_sub_list_2_1_.reset(new CandidateList(false)); |
| |
| main_list_->AddCandidate(0, "0"); // main0 |
| main_list_->AddCandidate(1, "1"); // main1 |
| sub_list_1_ = main_list_->AllocateSubCandidateList(false); // main2 |
| main_list_->AddCandidate(2, "2"); // main3 |
| main_list_->AddCandidate(3, "3"); // main4 |
| main_list_->AddCandidate(4, "4"); // main5 |
| main_list_->AddCandidate(5, "5"); // main6 |
| main_list_->AddSubCandidateList(sub_list_2_.get()); // main7 |
| main_list_->AddCandidate(6, "6"); // main8 |
| main_list_->AddCandidate(7, "7"); // main9 |
| main_list_->AddCandidate(8, "8"); // main10 |
| main_list_->AddCandidate(9, "9"); // main11 |
| main_list_->AddCandidate(10, "10"); // main12 |
| |
| sub_list_1_->AddCandidate(-1, "-1"); // sub10 |
| sub_list_1_->AddCandidate(-2, "-2"); // sub11 |
| sub_list_1_->AddCandidate(-3, "-3"); // sub12 |
| sub_list_1_->AddCandidate(-4, "-4"); // sub13 |
| sub_list_1_->AddCandidate(-5, "-5"); // sub14 |
| |
| sub_list_2_->AddSubCandidateList(sub_sub_list_2_1_.get()); // sub20 |
| sub_list_2_->AddCandidate(21, "21"); // sub21 |
| sub_list_2_->AddCandidate(22, "22"); // sub22 |
| sub_list_2_->AddCandidate(23, "23"); // sub23 |
| sub_list_2_->AddCandidate(24, "24"); // sub24 |
| sub_list_2_->AddCandidate(25, "25"); // sub25 |
| |
| sub_sub_list_2_1_->AddCandidate(210, "210"); // subsub210 |
| sub_sub_list_2_1_->AddCandidate(211, "211"); // subsub211 |
| sub_sub_list_2_1_->AddCandidate(212, "212"); // subsub212 |
| } |
| |
| scoped_ptr<CandidateList> main_list_; |
| // sub_list_1_ will be initialized on the fly. |
| CandidateList *sub_list_1_; |
| scoped_ptr<CandidateList> sub_list_2_; |
| scoped_ptr<CandidateList> sub_sub_list_2_1_; |
| }; |
| |
| TEST_F(CandidateListTest, MoveToId) { |
| // main0 |
| EXPECT_TRUE(main_list_->MoveToId(0)); |
| EXPECT_EQ(0, main_list_->focused_id()); |
| EXPECT_EQ(0, main_list_->focused_index()); |
| |
| // main1 |
| EXPECT_TRUE(main_list_->MoveToId(1)); |
| EXPECT_EQ(1, main_list_->focused_id()); |
| EXPECT_EQ(1, main_list_->focused_index()); |
| |
| // (main2, sub13) |
| EXPECT_TRUE(main_list_->MoveToId(-4)); |
| EXPECT_EQ(-4, main_list_->focused_id()); |
| EXPECT_EQ(2, main_list_->focused_index()); |
| EXPECT_EQ(3, sub_list_1_->focused_index()); |
| |
| // (main7, sub20, subsub210) |
| EXPECT_TRUE(main_list_->MoveToId(210)); |
| EXPECT_EQ(210, main_list_->focused_id()); |
| EXPECT_EQ(7, main_list_->focused_index()); |
| EXPECT_EQ(0, sub_list_2_->focused_index()); |
| EXPECT_EQ(0, sub_sub_list_2_1_->focused_index()); |
| |
| // Invalid IDs |
| EXPECT_FALSE(main_list_->MoveToId(13)); |
| EXPECT_FALSE(main_list_->MoveToId(-6)); |
| EXPECT_FALSE(main_list_->MoveToId(9999)); |
| } |
| |
| |
| TEST_F(CandidateListTest, MoveNext) { |
| // main0 -> main1 |
| EXPECT_TRUE(main_list_->MoveToId(0)); |
| EXPECT_TRUE(main_list_->MoveNext()); |
| EXPECT_EQ(1, main_list_->focused_id()); |
| EXPECT_EQ(1, main_list_->focused_index()); |
| |
| // main1 -> (main2, sub10) |
| EXPECT_TRUE(main_list_->MoveNext()); |
| EXPECT_EQ(-1, main_list_->focused_id()); |
| EXPECT_EQ(2, main_list_->focused_index()); |
| EXPECT_EQ(0, sub_list_1_->focused_index()); |
| |
| // (main2, sub10) -> (main2, sub11) |
| EXPECT_TRUE(main_list_->MoveNext()); |
| EXPECT_EQ(-2, main_list_->focused_id()); |
| EXPECT_EQ(2, main_list_->focused_index()); |
| EXPECT_EQ(1, sub_list_1_->focused_index()); |
| |
| // (main2, sub14) -> main3: no rotation |
| EXPECT_TRUE(main_list_->MoveToId(-5)); |
| EXPECT_TRUE(main_list_->MoveNext()); |
| EXPECT_EQ(2, main_list_->focused_id()); |
| EXPECT_EQ(3, main_list_->focused_index()); |
| |
| // (main7, sub25) -> (main7, sub20, subsub210): rotation |
| EXPECT_TRUE(main_list_->MoveToId(25)); |
| EXPECT_TRUE(main_list_->MoveNext()); |
| EXPECT_EQ(210, main_list_->focused_id()); |
| EXPECT_EQ(7, main_list_->focused_index()); |
| EXPECT_EQ(0, sub_list_2_->focused_index()); |
| EXPECT_EQ(0, sub_sub_list_2_1_->focused_index()); |
| |
| // (main7, sub20, subsub210) -> (main7, sub20, subsub211) |
| EXPECT_TRUE(main_list_->MoveNext()); |
| EXPECT_EQ(211, main_list_->focused_id()); |
| EXPECT_EQ(7, main_list_->focused_index()); |
| EXPECT_EQ(0, sub_list_2_->focused_index()); |
| EXPECT_EQ(1, sub_sub_list_2_1_->focused_index()); |
| } |
| |
| TEST_F(CandidateListTest, MovePrev) { |
| // main1 -> main0 |
| EXPECT_TRUE(main_list_->MoveToId(1)); |
| EXPECT_TRUE(main_list_->MovePrev()); |
| EXPECT_EQ(0, main_list_->focused_id()); |
| EXPECT_EQ(0, main_list_->focused_index()); |
| |
| // (main2, sub10) -> main1: no rotation |
| EXPECT_TRUE(main_list_->MoveToId(-1)); |
| EXPECT_TRUE(main_list_->MovePrev()); |
| EXPECT_EQ(1, main_list_->focused_id()); |
| |
| // (main7, sub20, subsub210) -> (main7, sub25) |
| EXPECT_TRUE(main_list_->MoveToId(210)); |
| EXPECT_TRUE(main_list_->MovePrev()); |
| EXPECT_EQ(25, main_list_->focused_id()); |
| } |
| |
| TEST_F(CandidateListTest, MoveNextPage) { |
| // main3 -> main9 |
| EXPECT_TRUE(main_list_->MoveToId(2)); |
| EXPECT_TRUE(main_list_->MoveNextPage()); |
| EXPECT_EQ(7, main_list_->focused_id()); |
| |
| // main9 -> main0 |
| EXPECT_TRUE(main_list_->MoveNextPage()); |
| EXPECT_EQ(0, main_list_->focused_id()); |
| |
| // (main2, sub10) -> main9: no ratation |
| EXPECT_TRUE(main_list_->MoveToId(-1)); |
| EXPECT_TRUE(main_list_->MoveNextPage()); |
| EXPECT_EQ(7, main_list_->focused_id()); |
| |
| // (main7, sub20, subsub210) -> (main7, sub20, subsub210) |
| EXPECT_TRUE(main_list_->MoveToId(210)); |
| EXPECT_TRUE(main_list_->MoveNextPage()); |
| EXPECT_EQ(210, main_list_->focused_id()); |
| } |
| |
| TEST_F(CandidateListTest, MovePrevPage) { |
| // main3 -> main9 |
| EXPECT_TRUE(main_list_->MoveToId(2)); |
| EXPECT_TRUE(main_list_->MovePrevPage()); |
| EXPECT_EQ(7, main_list_->focused_id()); |
| |
| // main9 -> main0 |
| EXPECT_TRUE(main_list_->MovePrevPage()); |
| EXPECT_EQ(0, main_list_->focused_id()); |
| |
| // (main2, sub10) -> main9: no ratation |
| EXPECT_TRUE(main_list_->MoveToId(-1)); |
| EXPECT_TRUE(main_list_->MovePrevPage()); |
| EXPECT_EQ(7, main_list_->focused_id()); |
| |
| // (main7, sub20, subsub210) -> (main7, sub20, subsub210) |
| EXPECT_TRUE(main_list_->MoveToId(210)); |
| EXPECT_TRUE(main_list_->MovePrevPage()); |
| EXPECT_EQ(210, main_list_->focused_id()); |
| } |
| |
| TEST_F(CandidateListTest, MoveToPageIndex) { |
| EXPECT_TRUE(main_list_->MoveToId(0)); |
| |
| // main1 |
| EXPECT_TRUE(main_list_->MoveToPageIndex(1)); |
| EXPECT_EQ(1, main_list_->focused_id()); |
| |
| // (main2, sub10) |
| EXPECT_TRUE(main_list_->MoveToPageIndex(2)); |
| EXPECT_EQ(-1, main_list_->focused_id()); |
| |
| // main12 |
| EXPECT_TRUE(main_list_->MoveToId(10)); |
| |
| // invalid index |
| EXPECT_FALSE(main_list_->MoveToPageIndex(7)); |
| } |
| |
| TEST_F(CandidateListTest, Clear) { |
| EXPECT_TRUE(main_list_->MoveToId(0)); |
| |
| main_list_->Clear(); |
| EXPECT_FALSE(main_list_->MoveToId(0)); |
| EXPECT_EQ(0, main_list_->size()); |
| |
| main_list_->AddCandidate(500, "500"); |
| main_list_->AddCandidate(501, "501"); |
| |
| EXPECT_TRUE(main_list_->MoveNext()); |
| EXPECT_EQ(501, main_list_->focused_id()); |
| EXPECT_EQ(1, main_list_->focused_index()); |
| } |
| |
| TEST_F(CandidateListTest, Duplication) { |
| CandidateList main_list(true); |
| CandidateList sub_list(true); |
| |
| main_list.AddCandidate(0, "0"); |
| main_list.AddCandidate(1, "1"); |
| main_list.AddCandidate(2, "2"); |
| main_list.AddCandidate(3, "0"); // dup |
| main_list.AddCandidate(4, "0"); // dup |
| main_list.AddCandidate(5, "1"); // dup |
| main_list.AddSubCandidateList(&sub_list); |
| sub_list.AddCandidate(6, "0"); // not dup |
| sub_list.AddCandidate(7, "7"); |
| sub_list.AddCandidate(8, "7"); // dup |
| |
| EXPECT_EQ(4, main_list.size()); |
| EXPECT_EQ(2, sub_list.size()); |
| |
| main_list.MoveToId(3); |
| EXPECT_EQ(0, main_list.focused_id()); |
| |
| main_list.MoveToId(4); |
| EXPECT_EQ(0, main_list.focused_id()); |
| |
| main_list.MoveToId(5); |
| EXPECT_EQ(1, main_list.focused_id()); |
| |
| main_list.MoveToId(6); |
| EXPECT_EQ(6, main_list.focused_id()); |
| |
| main_list.MoveToId(8); |
| EXPECT_EQ(7, main_list.focused_id()); |
| } |
| |
| TEST_F(CandidateListTest, FocusedId) { |
| CandidateList empty_list(true); |
| EXPECT_EQ(0, empty_list.focused_id()); |
| } |
| |
| TEST_F(CandidateListTest, set_page_size) { |
| EXPECT_EQ(9, main_list_->page_size()); |
| // Move to the 10th item. |
| EXPECT_TRUE(main_list_->MoveToId(7)); |
| |
| // Make sure the default values. |
| EXPECT_EQ(7, main_list_->focused_id()); |
| EXPECT_EQ(9, main_list_->focused_index()); |
| size_t begin, end; |
| main_list_->GetPageRange(main_list_->focused_index(), &begin, &end); |
| EXPECT_EQ(9, begin); |
| EXPECT_EQ(12, end); // The last index. |
| |
| // Change the page size. |
| main_list_->set_page_size(11); |
| // The id and index should not be changed. |
| EXPECT_EQ(7, main_list_->focused_id()); |
| EXPECT_EQ(9, main_list_->focused_index()); |
| |
| // The begin and end should be changed. |
| main_list_->GetPageRange(main_list_->focused_index(), &begin, &end); |
| EXPECT_EQ(0, begin); |
| EXPECT_EQ(10, end); |
| } |
| |
| TEST_F(CandidateListTest, Attributes) { |
| CandidateList main_list(true); |
| |
| main_list.AddCandidateWithAttributes(0, "hiragana", HIRAGANA); |
| main_list.AddCandidateWithAttributes(1, "f_katakana", FULL_WIDTH | KATAKANA); |
| main_list.AddCandidateWithAttributes(2, "h_ascii", |
| (HALF_WIDTH | ASCII | LOWER)); |
| main_list.AddCandidateWithAttributes(3, "H_ASCII", |
| (HALF_WIDTH | ASCII | UPPER)); |
| // dup entry |
| main_list.AddCandidateWithAttributes(4, "h_ascii", |
| (HALF_WIDTH | ASCII | LOWER)); |
| main_list.AddCandidateWithAttributes(5, "H_Ascii", (HALF_WIDTH | ASCII)); |
| main_list.AddCandidateWithAttributes(6, "f_ascii", |
| (FULL_WIDTH | ASCII | LOWER)); |
| |
| EXPECT_EQ(6, main_list.size()); |
| |
| EXPECT_FALSE(main_list.MoveNextAttributes(HALF_WIDTH | KATAKANA)); |
| |
| // h_ascii |
| EXPECT_TRUE(main_list.MoveNextAttributes(HALF_WIDTH | ASCII)); |
| EXPECT_EQ(2, main_list.focused_id()); |
| EXPECT_EQ((HALF_WIDTH | ASCII | LOWER), |
| main_list.focused_candidate().attributes()); |
| |
| // H_ASCII |
| EXPECT_TRUE(main_list.MoveNextAttributes(HALF_WIDTH | ASCII)); |
| EXPECT_EQ(3, main_list.focused_id()); |
| EXPECT_EQ((HALF_WIDTH | ASCII | UPPER), |
| main_list.focused_candidate().attributes()); |
| |
| // ID:4 (h_ascii) should be skipped because it's a dup. |
| |
| // H_Ascii |
| EXPECT_TRUE(main_list.MoveNextAttributes(HALF_WIDTH | ASCII)); |
| EXPECT_EQ(5, main_list.focused_id()); |
| EXPECT_EQ((HALF_WIDTH | ASCII), main_list.focused_candidate().attributes()); |
| |
| // h_ascii / Looped |
| EXPECT_TRUE(main_list.MoveNextAttributes(HALF_WIDTH | ASCII)); |
| EXPECT_EQ(2, main_list.focused_id()); |
| } |
| |
| TEST_F(CandidateListTest, Attributes2) { |
| CandidateList main_list(true); |
| |
| main_list.AddCandidate(0, "dvd"); |
| main_list.AddCandidate(1, "DVD"); |
| main_list.AddCandidateWithAttributes(2, "f_dvd", HIRAGANA); |
| // id#3 is dup |
| main_list.AddCandidateWithAttributes(3, "f_dvd", FULL_WIDTH | KATAKANA); |
| main_list.AddCandidateWithAttributes(4, "h_dvd", |
| (HALF_WIDTH | ASCII)); |
| // id#5 is dup |
| main_list.AddCandidateWithAttributes(5, "h_dvd", |
| (HALF_WIDTH | ASCII | LOWER)); |
| main_list.AddCandidateWithAttributes(6, "h_DVD", |
| (HALF_WIDTH | ASCII | UPPER)); |
| main_list.AddCandidateWithAttributes(7, "h_Dvd", |
| (HALF_WIDTH | ASCII | CAPITALIZED)); |
| // id#8 is dup |
| main_list.AddCandidateWithAttributes(8, "f_dvd", |
| (FULL_WIDTH | ASCII)); |
| // id#9 is dup |
| main_list.AddCandidateWithAttributes(9, "f_dvd", |
| (FULL_WIDTH | ASCII | LOWER)); |
| main_list.AddCandidateWithAttributes(10, "f_DVD", |
| (FULL_WIDTH | ASCII | UPPER)); |
| main_list.AddCandidateWithAttributes(11, "f_Dvd", |
| (FULL_WIDTH | ASCII | CAPITALIZED)); |
| // id#12 is dup |
| main_list.AddCandidateWithAttributes(12, "h_dvd", HALF_WIDTH | KATAKANA); |
| |
| EXPECT_EQ(8, main_list.size()); |
| |
| EXPECT_TRUE(main_list.MoveNextAttributes(FULL_WIDTH | ASCII)); |
| |
| EXPECT_EQ(2, main_list.focused_id()); |
| EXPECT_EQ((HIRAGANA | KATAKANA | FULL_WIDTH | ASCII | LOWER), |
| main_list.focused_candidate().attributes()); |
| |
| EXPECT_TRUE(main_list.MoveNextAttributes(FULL_WIDTH | ASCII)); |
| EXPECT_EQ(10, main_list.focused_id()); |
| EXPECT_EQ((FULL_WIDTH | ASCII | UPPER), |
| main_list.focused_candidate().attributes()); |
| |
| EXPECT_TRUE(main_list.MoveNextAttributes(FULL_WIDTH | ASCII)); |
| EXPECT_EQ(11, main_list.focused_id()); |
| EXPECT_EQ((FULL_WIDTH | ASCII | CAPITALIZED), |
| main_list.focused_candidate().attributes()); |
| |
| EXPECT_TRUE(main_list.MoveNextAttributes(FULL_WIDTH | ASCII)); |
| EXPECT_EQ(2, main_list.focused_id()); |
| } |
| |
| TEST_F(CandidateListTest, AttributesWithSubList) { |
| CandidateList main_list(true); |
| main_list.AddCandidate(0, "kanji"); |
| |
| CandidateList *sub_list = main_list.AllocateSubCandidateList(false); |
| sub_list->AddCandidateWithAttributes(1, "hiragana", HIRAGANA); |
| sub_list->AddCandidateWithAttributes(2, "f_katakana", FULL_WIDTH | KATAKANA); |
| sub_list->AddCandidateWithAttributes(3, "h_ascii", |
| (HALF_WIDTH | ASCII | LOWER)); |
| sub_list->AddCandidateWithAttributes(4, "H_ASCII", |
| (HALF_WIDTH | ASCII | UPPER)); |
| sub_list->AddCandidateWithAttributes(5, "H_Ascii", |
| (HALF_WIDTH | ASCII | CAPITALIZED)); |
| EXPECT_EQ(2, main_list.size()); |
| EXPECT_EQ(5, sub_list->size()); |
| |
| // h_ascii |
| EXPECT_TRUE(main_list.MoveNextAttributes(HALF_WIDTH | ASCII)); |
| EXPECT_EQ(3, main_list.focused_id()); |
| EXPECT_EQ((HALF_WIDTH | ASCII | LOWER), |
| sub_list->focused_candidate().attributes()); |
| |
| // H_ASCII |
| EXPECT_TRUE(main_list.MoveNextAttributes(HALF_WIDTH | ASCII)); |
| EXPECT_EQ(4, main_list.focused_id()); |
| EXPECT_EQ((HALF_WIDTH | ASCII | UPPER), |
| sub_list->focused_candidate().attributes()); |
| |
| // H_Ascii |
| EXPECT_TRUE(main_list.MoveNextAttributes(HALF_WIDTH | ASCII)); |
| EXPECT_EQ(5, main_list.focused_id()); |
| EXPECT_EQ((HALF_WIDTH | ASCII | CAPITALIZED), |
| sub_list->focused_candidate().attributes()); |
| |
| // h_ascii / Looped |
| EXPECT_TRUE(main_list.MoveNextAttributes(HALF_WIDTH | ASCII)); |
| EXPECT_EQ(3, main_list.focused_id()); |
| EXPECT_EQ((HALF_WIDTH | ASCII | LOWER), |
| sub_list->focused_candidate().attributes()); |
| } |
| |
| TEST_F(CandidateListTest, GetDeepestFocusedCandidate) { |
| EXPECT_TRUE(main_list_->MoveToPageIndex(2)); |
| EXPECT_EQ(0, main_list_->focused_candidate().id()); |
| EXPECT_TRUE(main_list_->focused_candidate().IsSubcandidateList()); |
| |
| const Candidate &deepest_candidate = main_list_->GetDeepestFocusedCandidate(); |
| EXPECT_EQ(-1, deepest_candidate.id()); |
| EXPECT_FALSE(deepest_candidate.IsSubcandidateList()); |
| } |
| |
| TEST_F(CandidateListTest, NextAvailableId) { |
| EXPECT_EQ(213, main_list_->next_available_id()); |
| EXPECT_EQ(0, sub_list_1_->next_available_id()); |
| EXPECT_EQ(213, sub_list_2_->next_available_id()); |
| EXPECT_EQ(213, sub_sub_list_2_1_->next_available_id()); |
| |
| // Append duplicate candidate. |
| // next_available_id should be incremented. |
| sub_sub_list_2_1_->AddCandidate(213, "212"); |
| EXPECT_EQ(214, main_list_->next_available_id()); |
| EXPECT_EQ(214, sub_sub_list_2_1_->next_available_id()); |
| } |
| |
| } // namespace session |
| } // namespace mozc |