| // 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 "dictionary/system/value_dictionary.h" |
| |
| #include <vector> |
| |
| #include "base/file_util.h" |
| #include "base/stl_util.h" |
| #include "base/system_util.h" |
| #include "base/trie.h" |
| #include "data_manager/user_pos_manager.h" |
| #include "dictionary/dictionary_interface.h" |
| #include "dictionary/dictionary_test_util.h" |
| #include "dictionary/dictionary_token.h" |
| #include "dictionary/pos_matcher.h" |
| #include "dictionary/system/system_dictionary_builder.h" |
| #include "testing/base/public/googletest.h" |
| #include "testing/base/public/gunit.h" |
| |
| DECLARE_string(test_tmpdir); |
| |
| namespace mozc { |
| namespace dictionary { |
| |
| class ValueDictionaryTest : public testing::Test { |
| protected: |
| ValueDictionaryTest() : |
| dict_name_(FLAGS_test_tmpdir + "/value_dict_test.dic") {} |
| |
| virtual void SetUp() { |
| STLDeleteElements(&tokens_); |
| SystemUtil::SetUserProfileDirectory(FLAGS_test_tmpdir); |
| FileUtil::Unlink(dict_name_); |
| pos_matcher_ = UserPosManager::GetUserPosManager()->GetPOSMatcher(); |
| } |
| |
| virtual void TearDown() { |
| STLDeleteElements(&tokens_); |
| FileUtil::Unlink(dict_name_); |
| } |
| |
| void AddToken(const string &key, const string &value) { |
| Token *token = new Token; |
| token->key = key; |
| token->value = value; |
| token->cost = 0; |
| token->lid = 0; |
| token->rid = 0; |
| tokens_.push_back(token); |
| } |
| |
| void BuildDictionary() { |
| dictionary::SystemDictionaryBuilder builder; |
| builder.BuildFromTokens(tokens_); |
| builder.WriteToFile(dict_name_); |
| } |
| |
| void InitToken(const string &value, Token *token) const { |
| token->key = token->value = value; |
| token->cost = 10000; |
| token->lid = token->rid = pos_matcher_->GetSuggestOnlyWordId(); |
| token->attributes = Token::NONE; |
| } |
| |
| const string dict_name_; |
| const POSMatcher *pos_matcher_; |
| |
| private: |
| vector<Token *> tokens_; |
| }; |
| |
| TEST_F(ValueDictionaryTest, HasValue) { |
| // "うぃー" |
| AddToken("\xE3\x81\x86\xE3\x81\x83\xE3\x83\xBC", "we"); |
| // "うぉー" |
| AddToken("\xE3\x81\x86\xE3\x81\x89\xE3\x83\xBC", "war"); |
| // "わーど" |
| AddToken("\xE3\x82\x8F\xE3\x83\xBC\xE3\x81\xA9", "word"); |
| // "わーるど" |
| AddToken("\xE3\x82\x8F\xE3\x83\xBC\xE3\x82\x8B\xE3\x81\xA9", "world"); |
| BuildDictionary(); |
| scoped_ptr<ValueDictionary> dictionary( |
| ValueDictionary::CreateValueDictionaryFromFile(*pos_matcher_, |
| dict_name_)); |
| |
| // ValueDictionary is supposed to use the same data with SystemDictionary |
| // and SystemDictionary::HasValue should return the same result with |
| // ValueDictionary::HasValue. So we can skip the actual logic of HasValue |
| // and return just false. |
| EXPECT_FALSE(dictionary->HasValue("we")); |
| EXPECT_FALSE(dictionary->HasValue("war")); |
| EXPECT_FALSE(dictionary->HasValue("word")); |
| EXPECT_FALSE(dictionary->HasValue("world")); |
| |
| EXPECT_FALSE(dictionary->HasValue("hoge")); |
| EXPECT_FALSE(dictionary->HasValue("piyo")); |
| } |
| |
| TEST_F(ValueDictionaryTest, LookupPredictive) { |
| // "ぐーぐる" |
| AddToken("\xE3\x81\x90\xE3\x83\xBC\xE3\x81\x90\xE3\x82\x8B", "google"); |
| // "うぃー" |
| AddToken("\xE3\x81\x86\xE3\x81\x83\xE3\x83\xBC", "we"); |
| // "うぉー" |
| AddToken("\xE3\x81\x86\xE3\x81\x89\xE3\x83\xBC", "war"); |
| // "わーど" |
| AddToken("\xE3\x82\x8F\xE3\x83\xBC\xE3\x81\xA9", "word"); |
| // "わーるど" |
| AddToken("\xE3\x82\x8F\xE3\x83\xBC\xE3\x82\x8B\xE3\x81\xA9", "world"); |
| BuildDictionary(); |
| scoped_ptr<ValueDictionary> dictionary( |
| ValueDictionary::CreateValueDictionaryFromFile(*pos_matcher_, |
| dict_name_)); |
| |
| // Reading fields are irrelevant to value dictionary. Prepare actual tokens |
| // that are to be looked up. |
| Token token_we, token_war, token_word, token_world; |
| InitToken("we", &token_we); |
| InitToken("war", &token_war); |
| InitToken("word", &token_word); |
| InitToken("world", &token_world); |
| |
| { |
| CollectTokenCallback callback; |
| dictionary->LookupPredictive("", false, &callback); |
| EXPECT_TRUE(callback.tokens().empty()); |
| } |
| { |
| CollectTokenCallback callback; |
| dictionary->LookupPredictive("w", false, &callback); |
| vector<Token *> expected; |
| expected.push_back(&token_we); |
| expected.push_back(&token_war); |
| expected.push_back(&token_word); |
| expected.push_back(&token_world); |
| EXPECT_TOKENS_EQ_UNORDERED(expected, callback.tokens()); |
| } |
| { |
| CollectTokenCallback callback; |
| dictionary->LookupPredictive("wo", false, &callback); |
| vector<Token *> expected; |
| expected.push_back(&token_word); |
| expected.push_back(&token_world); |
| EXPECT_TOKENS_EQ_UNORDERED(expected, callback.tokens()); |
| } |
| { |
| CollectTokenCallback callback; |
| dictionary->LookupPredictive("ho", false, &callback); |
| EXPECT_TRUE(callback.tokens().empty()); |
| } |
| } |
| |
| TEST_F(ValueDictionaryTest, LookupExact) { |
| // "うぃー" |
| AddToken("\xE3\x81\x86\xE3\x81\x83\xE3\x83\xBC", "we"); |
| // "うぉー" |
| AddToken("\xE3\x81\x86\xE3\x81\x89\xE3\x83\xBC", "war"); |
| // "わーど" |
| AddToken("\xE3\x82\x8F\xE3\x83\xBC\xE3\x81\xA9", "word"); |
| BuildDictionary(); |
| |
| scoped_ptr<ValueDictionary> dictionary( |
| ValueDictionary::CreateValueDictionaryFromFile(*pos_matcher_, |
| dict_name_)); |
| CollectTokenCallback callback; |
| dictionary->LookupExact("war", &callback); |
| ASSERT_EQ(1, callback.tokens().size()); |
| EXPECT_EQ("war", callback.tokens()[0].value); |
| } |
| |
| } // namespace dictionary |
| } // namespace mozc |