// 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.

// Unit tests for UserDictionary.

#include "dictionary/user_dictionary.h"

#include <algorithm>
#include <cstring>
#include <sstream>
#include <string>
#include <vector>

#include "base/file_util.h"
#include "base/logging.h"
#include "base/number_util.h"
#include "base/port.h"
#include "base/singleton.h"
#include "base/system_util.h"
#include "base/trie.h"
#include "base/util.h"
#include "config/config.pb.h"
#include "config/config_handler.h"
#include "data_manager/testing/mock_user_pos_manager.h"
#include "dictionary/dictionary_test_util.h"
#include "dictionary/dictionary_token.h"
#include "dictionary/pos_matcher.h"
#include "dictionary/suppression_dictionary.h"
#include "dictionary/user_dictionary_storage.h"
#include "dictionary/user_pos.h"
#include "dictionary/user_pos_interface.h"
#include "testing/base/public/googletest.h"
#include "testing/base/public/gunit.h"
#include "usage_stats/usage_stats.h"
#include "usage_stats/usage_stats_testing_util.h"

DECLARE_string(test_tmpdir);

using mozc::dictionary::CollectTokenCallback;

namespace mozc {
namespace {

const char kUserDictionary0[] =
    "start\tstart\tverb\n"
    "star\tstar\tnoun\n"
    "starting\tstarting\tnoun\n"
    "stamp\tstamp\tnoun\n"
    "stand\tstand\tverb\n"
    "smile\tsmile\tverb\n"
    "smog\tsmog\tnoun\n"
    // invalid characters "水雲" in reading
    "\xE6\xB0\xB4\xE9\x9B\xB2\tvalue\tnoun\n"

    // Empty key
    "\tvalue\tnoun\n"
    // Empty value
    "start\t\tnoun\n"
    // Invalid POS
    "star\tvalue\tpos\n"
    // Empty POS
    "star\tvalue\t\n"
    // Duplicate entry
    "start\tstart\tverb\n"
    // The following are for tests for LookupComment
    // No comment
    "comment_key1\tcomment_value1\tnoun\n"
    // Has comment
    "comment_key2\tcomment_value2\tnoun\tcomment\n"
    // Different POS
    "comment_key3\tcomment_value3\tnoun\tcomment1\n"
    "comment_key3\tcomment_value3\tverb\tcomment2\n"
    // White spaces comment
    "comment_key4\tcomment_value4\tverb\t     \n";

const char kUserDictionary1[] = "end\tend\tverb\n";

void PushBackToken(const string &key,
                   const string &value,
                   uint16 id,
                   vector<UserPOS::Token> *tokens) {
  tokens->resize(tokens->size() + 1);
  UserPOS::Token *t = &tokens->back();
  t->key = key;
  t->value = value;
  t->id = id;
  t->cost = 0;
}

// This class is a mock class for writing unit tests of a class that
// depends on POS. It accepts only two values for part-of-speech:
// "noun" as words without inflection and "verb" as words with
// inflection.
class UserPOSMock : public UserPOSInterface {
 public:
  UserPOSMock() {}
  virtual ~UserPOSMock() {}

  // This method returns true if the given pos is "noun" or "verb".
  virtual bool IsValidPOS(const string &pos) const {
    return true;
  }

  static const char *kNoun;
  static const char *kVerb;

  // Given a verb, this method expands it to three different forms,
  // i.e. base form (the word itself), "-ed" form and "-ing" form. For
  // example, if the given word is "play", the method returns "play",
  // "played" and "playing". When a noun is passed, it returns only
  // base form. The method set lid and rid of the word as following:
  //
  //  POS              | lid | rid
  // ------------------+-----+-----
  //  noun             | 100 | 100
  //  verb (base form) | 200 | 200
  //  verb (-ed form)  | 210 | 210
  //  verb (-ing form) | 220 | 220
  virtual bool GetTokens(const string &key,
                         const string &value,
                         const string &pos,
                         vector<UserPOS::Token> *tokens) const {
    if (key.empty() ||
        value.empty() ||
        pos.empty() ||
        tokens == NULL) {
      return false;
    }

    tokens->clear();
    if (pos == kNoun) {
      PushBackToken(key, value, 100, tokens);
      return true;
    } else if (pos == kVerb) {
      PushBackToken(key, value, 200, tokens);
      PushBackToken(key + "ed", value + "ed", 210, tokens);
      PushBackToken(key + "ing", value + "ing", 220, tokens);
      return true;
    } else {
      return false;
    }
  }

  virtual void GetPOSList(vector<string> *pos_list) const {}

  virtual bool GetPOSIDs(const string &pos, uint16 *id) const {
    return false;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(UserPOSMock);
};
// "名詞"
const char *UserPOSMock::kNoun = "\xE5\x90\x8D\xE8\xA9\x9E";
// "動詞ワ行五段"
const char *UserPOSMock::kVerb =
    "\xE5\x8B\x95\xE8\xA9\x9E\xE3\x83\xAF\xE8\xA1\x8C\xE4\xBA\x94\xE6\xAE\xB5";

string GenRandomAlphabet(int size) {
  string result;
  const size_t len = Util::Random(size) + 1;
  for (int i = 0; i < len; ++i) {
    const char32 l = Util::Random(static_cast<int>('z' - 'a')) + 'a';
    Util::UCS4ToUTF8Append(l, &result);
  }
  return result;
}

class UserDictionaryTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    SystemUtil::SetUserProfileDirectory(FLAGS_test_tmpdir);
    suppression_dictionary_.reset(new SuppressionDictionary);

    mozc::usage_stats::UsageStats::ClearAllStatsForTest();
  }

  virtual void TearDown() {
    mozc::usage_stats::UsageStats::ClearAllStatsForTest();
  }

  // Workaround for the constructor of UserDictionary being protected.
  // Creates a user dictionary with mock pos data.
  UserDictionary *CreateDictionaryWithMockPos() {
    const testing::MockUserPosManager user_pos_manager;
    return new UserDictionary(
        new UserPOSMock(),
        user_pos_manager.GetPOSMatcher(),
        suppression_dictionary_.get());
  }

  // Creates a user dictionary with actual pos data.
  UserDictionary *CreateDictionary() {
    const testing::MockUserPosManager user_pos_manager;
    return new UserDictionary(new UserPOS(user_pos_manager.GetUserPOSData()),
                              user_pos_manager.GetPOSMatcher(),
                              Singleton<SuppressionDictionary>::get());
  }

  struct Entry {
    string key;
    string value;
    uint16 lid;
    uint16 rid;
  };

  class EntryCollector : public DictionaryInterface::Callback {
   public:
    virtual ResultType OnToken(StringPiece,  // key
                               StringPiece,  // actual_key
                               const Token &token) {
      // Collect only user dictionary entries.
      if (token.attributes & Token::USER_DICTIONARY) {
        entries_.push_back(Entry());
        entries_.back().key = token.key;
        entries_.back().value = token.value;
        entries_.back().lid = token.lid;
        entries_.back().rid = token.rid;
      }
      return TRAVERSE_CONTINUE;
    }

    const vector<Entry> &entries() const { return entries_; }

   private:
    vector<Entry> entries_;
  };

  static void TestLookupPredictiveHelper(const Entry *expected,
                                         size_t expected_size,
                                         StringPiece key,
                                         const UserDictionary &dic) {
    EntryCollector collector;
    dic.LookupPredictive(key, false, &collector);

    if (expected == NULL || expected_size == 0) {
      EXPECT_TRUE(collector.entries().empty());
    } else {
      ASSERT_FALSE(collector.entries().empty());
      CompareEntries(expected, expected_size, collector.entries());
    }
  }

  static void TestLookupPrefixHelper(const Entry *expected,
                                     size_t expected_size,
                                     const char *key,
                                     size_t key_size,
                                     const UserDictionary &dic) {
    EntryCollector collector;
    dic.LookupPrefix(StringPiece(key, key_size), false, &collector);

    if (expected == NULL || expected_size == 0) {
      EXPECT_TRUE(collector.entries().empty());
    } else {
      ASSERT_FALSE(collector.entries().empty());
      CompareEntries(expected, expected_size, collector.entries());
    }
  }

  static void TestLookupExactHelper(const Entry *expected,
                                    size_t expected_size,
                                    const char *key,
                                    size_t key_size,
                                    const UserDictionary &dic) {
    EntryCollector collector;
    dic.LookupExact(StringPiece(key, key_size), &collector);

    if (expected == NULL || expected_size == 0) {
      EXPECT_TRUE(collector.entries().empty());
    } else {
      ASSERT_FALSE(collector.entries().empty());
      CompareEntries(expected, expected_size, collector.entries());
    }
  }

  static string EncodeEntry(const Entry &entry) {
    return entry.key + "\t" +
           entry.value + "\t" +
           NumberUtil::SimpleItoa(entry.lid) + "\t" +
           NumberUtil::SimpleItoa(entry.rid) + "\n";
  }

  static string EncodeEntries(const Entry *array, size_t size) {
    vector<string> encoded_items;
    for (size_t i = 0; i < size; ++i) {
      encoded_items.push_back(EncodeEntry(array[i]));
    }
    sort(encoded_items.begin(), encoded_items.end());
    string result;
    Util::JoinStrings(encoded_items, "", &result);
    return result;
  }

  static void CompareEntries(const Entry *expected, size_t expected_size,
                             const vector<Entry> &actual) {
    const string expected_encoded = EncodeEntries(expected, expected_size);
    const string actual_encoded = EncodeEntries(&actual[0], actual.size());
    EXPECT_EQ(expected_encoded, actual_encoded);
  }

  static void LoadFromString(const string &contents,
                             UserDictionaryStorage *storage) {
    istringstream is(contents);
    CHECK(is.good());

    storage->Clear();
    UserDictionaryStorage::UserDictionary *dic
        = storage->add_dictionaries();
    CHECK(dic);

    string line;
    while (!getline(is, line).fail()) {
      if (line.empty() || line[0] == '#') {
        continue;
      }
      vector<string> fields;
      Util::SplitStringAllowEmpty(line, "\t", &fields);
      EXPECT_GE(fields.size(), 3) << line;
      UserDictionaryStorage::UserDictionaryEntry *entry =
          dic->add_entries();
      CHECK(entry);
      entry->set_key(fields[0]);
      entry->set_value(fields[1]);
      if (fields[2] == "verb") {
        entry->set_pos(user_dictionary::UserDictionary::WA_GROUP1_VERB);
      } else if (fields[2] == "noun") {
        entry->set_pos(user_dictionary::UserDictionary::NOUN);
      }
      if (fields.size() >= 4 && !fields[3].empty()) {
        entry->set_comment(fields[3]);
      }
    }
  }

  // Helper function to lookup comment string from |dic|.
  static string LookupComment(const UserDictionary& dic,
                              StringPiece key, StringPiece value) {
    string comment;
    dic.LookupComment(key, value, &comment);
    return comment;
  }

  scoped_ptr<SuppressionDictionary> suppression_dictionary_;

 private:
  mozc::usage_stats::scoped_usage_stats_enabler usage_stats_enabler_;
};

TEST_F(UserDictionaryTest, TestLookupPredictive) {
  scoped_ptr<UserDictionary> dic(CreateDictionaryWithMockPos());
  // Wait for async reload called from the constructor.
  dic->WaitForReloader();

  {
    UserDictionaryStorage storage("");
    UserDictionaryTest::LoadFromString(kUserDictionary0, &storage);
    dic->Load(storage);
  }

  // A normal lookup operation.
  const Entry kExpected0[] = {
    { "start", "start", 200, 200 },
    { "started", "started", 210, 210 },
    { "starting", "starting", 100, 100 },
    { "starting", "starting", 220, 220 },
  };
  TestLookupPredictiveHelper(kExpected0, arraysize(kExpected0),
                             "start", *dic.get());

  // Another normal lookup operation.
  const Entry kExpected1[] = {
    { "stamp", "stamp", 100, 100 },
    { "stand", "stand", 200, 200 },
    { "standed", "standed", 210, 210 },
    { "standing", "standing", 220, 220 },
    { "star", "star", 100, 100 },
    { "start", "start", 200, 200 },
    { "started", "started", 210, 210 },
    { "starting", "starting", 100, 100 },
    { "starting", "starting", 220, 220 },
  };
  TestLookupPredictiveHelper(kExpected1, arraysize(kExpected1),
                             "st", *dic.get());

  // Invalid input values should be just ignored.
  TestLookupPredictiveHelper(NULL, 0, "", *dic.get());
  TestLookupPredictiveHelper(NULL, 0,
                             "\xE6\xB0\xB4\xE9\x9B\xB2",  // "水雲"
                             *dic.get());

  // Make a change to the dictionary file and load it again.
  {
    UserDictionaryStorage storage("");
    LoadFromString(kUserDictionary1, &storage);
    dic->Load(storage);
  }

  // A normal lookup again.
  const Entry kExpected2[] = {
    { "end", "end", 200, 200 },
    { "ended", "ended", 210, 210 },
    { "ending", "ending", 220, 220 },
  };
  TestLookupPredictiveHelper(kExpected2, arraysize(kExpected2),
                             "end", *dic.get());

  // Entries in the dictionary before reloading cannot be looked up.
  TestLookupPredictiveHelper(NULL, 0, "start", *dic.get());
  TestLookupPredictiveHelper(NULL, 0, "st", *dic.get());
}

TEST_F(UserDictionaryTest, TestLookupPrefix) {
  scoped_ptr<UserDictionary> dic(CreateDictionaryWithMockPos());
  // Wait for async reload called from the constructor.
  dic->WaitForReloader();

  {
    UserDictionaryStorage storage("");
    LoadFromString(kUserDictionary0, &storage);
    dic->Load(storage);
  }

  // A normal lookup operation.
  const Entry kExpected0[] = {
    { "star", "star", 100, 100 },
    { "start", "start", 200, 200 },
    { "started", "started", 210, 210 },
  };
  TestLookupPrefixHelper(kExpected0, arraysize(kExpected0),
                         "started", 7, *dic.get());

  // Another normal lookup operation.
  const Entry kExpected1[] = {
    { "star", "star", 100, 100 },
    { "start", "start", 200, 200 },
    { "starting", "starting", 100, 100 },
    { "starting", "starting", 220, 220 },
  };
  TestLookupPrefixHelper(kExpected1, arraysize(kExpected1),
                         "starting", 8, *dic.get());

  // Invalid input values should be just ignored.
  TestLookupPrefixHelper(NULL, 0, "", 0, *dic.get());
  TestLookupPrefixHelper(
      NULL, 0, "\xE6\xB0\xB4\xE9\x9B\xB2",  // "水雲"
      strlen("\xE6\xB0\xB4\xE9\x9B\xB2"), *dic.get());

  // Make a change to the dictionary file and load it again.
  {
    UserDictionaryStorage storage("");
    LoadFromString(kUserDictionary1, &storage);
    dic->Load(storage);
  }

  // A normal lookup.
  const Entry kExpected2[] = {
    { "end", "end", 200, 200 },
    { "ending", "ending", 220, 220 },
  };
  TestLookupPrefixHelper(kExpected2, arraysize(kExpected2),
                                     "ending", 6, *dic.get());

  // Lookup for entries which are gone should returns empty result.
  TestLookupPrefixHelper(NULL, 0, "started", 7, *dic.get());
  TestLookupPrefixHelper(NULL, 0, "starting", 8, *dic.get());
}

TEST_F(UserDictionaryTest, TestLookupExact) {
  scoped_ptr<UserDictionary> dic(CreateDictionaryWithMockPos());
  // Wait for async reload called from the constructor.
  dic->WaitForReloader();

  {
    UserDictionaryStorage storage("");
    LoadFromString(kUserDictionary0, &storage);
    dic->Load(storage);
  }

  // A normal lookup operation.
  const Entry kExpected0[] = {
    { "start", "start", 200, 200 },
  };
  TestLookupExactHelper(kExpected0, arraysize(kExpected0),
                        "start", 5, *dic.get());

  // Another normal lookup operation.
  const Entry kExpected1[] = {
    { "starting", "starting", 100, 100 },
    { "starting", "starting", 220, 220 },
  };
  TestLookupExactHelper(kExpected1, arraysize(kExpected1),
                        "starting", 8, *dic.get());

  // Invalid input values should be just ignored.
  TestLookupPrefixHelper(NULL, 0, "", 0, *dic.get());
  TestLookupPrefixHelper(NULL, 0, "\xE6\xB0\xB4\xE9\x9B\xB2",  // "水雲"
                         strlen("\xE6\xB0\xB4\xE9\x9B\xB2"), *dic.get());
}

TEST_F(UserDictionaryTest, TestLookupExactWithSuggestionOnlyWords) {
  scoped_ptr<UserDictionary> user_dic(CreateDictionary());
  user_dic->WaitForReloader();

  // Create dictionary
  const string filename = FileUtil::JoinPath(FLAGS_test_tmpdir,
                                             "suggestion_only_test.db");
  FileUtil::Unlink(filename);
  UserDictionaryStorage storage(filename);
  {
    uint64 id = 0;
    EXPECT_TRUE(storage.CreateDictionary("test", &id));
    UserDictionaryStorage::UserDictionary *dic =
        storage.mutable_dictionaries(0);

    // "名詞"
    UserDictionaryStorage::UserDictionaryEntry *entry =
        dic->add_entries();
    entry->set_key("key");
    entry->set_value("noun");
    entry->set_pos(user_dictionary::UserDictionary::NOUN);

    // "サジェストのみ"
    entry = dic->add_entries();
    entry->set_key("key");
    entry->set_value("suggest_only");
    entry->set_pos(user_dictionary::UserDictionary::SUGGESTION_ONLY);

    user_dic->Load(storage);
  }

  // "suggestion_only" should not be looked up.
  const testing::MockUserPosManager user_pos_manager;
  const uint16 kNounId = user_pos_manager.GetPOSMatcher()->GetGeneralNounId();
  const Entry kExpected1[] = {{"key", "noun", kNounId, kNounId}};
  TestLookupExactHelper(kExpected1, arraysize(kExpected1),
                        "key", 3, *user_dic.get());
}

TEST_F(UserDictionaryTest, IncognitoModeTest) {
  config::Config config;
  config::ConfigHandler::GetConfig(&config);
  config.set_incognito_mode(true);
  config::ConfigHandler::SetConfig(config);

  scoped_ptr<UserDictionary> dic(CreateDictionaryWithMockPos());
  // Wait for async reload called from the constructor.
  dic->WaitForReloader();

  {
    UserDictionaryStorage storage("");
    UserDictionaryTest::LoadFromString(kUserDictionary0, &storage);
    dic->Load(storage);
  }

  TestLookupPrefixHelper(NULL, 0, "start", 4, *dic);
  TestLookupPredictiveHelper(NULL, 0, "s", *dic);

  config.set_incognito_mode(false);
  config::ConfigHandler::SetConfig(config);

  {
    EntryCollector collector;
    dic->LookupPrefix("start", false, &collector);
    EXPECT_FALSE(collector.entries().empty());
  }
  {
    EntryCollector collector;
    dic->LookupPredictive("s", false, &collector);
    EXPECT_FALSE(collector.entries().empty());
  }
}

TEST_F(UserDictionaryTest, AsyncLoadTest) {
  const string filename = FileUtil::JoinPath(FLAGS_test_tmpdir,
                                             "async_load_test.db");
  FileUtil::Unlink(filename);

  // Create dictionary
  vector<string> keys;
  {
    UserDictionaryStorage storage(filename);

    EXPECT_FALSE(storage.Load());
    EXPECT_TRUE(storage.Lock());

    uint64 id = 0;
    EXPECT_TRUE(storage.CreateDictionary("test", &id));
    UserDictionaryStorage::UserDictionary *dic =
        storage.mutable_dictionaries(0);
    for (size_t j = 0; j < 10000; ++j) {
      UserDictionaryStorage::UserDictionaryEntry *entry =
          dic->add_entries();
      entry->set_key(GenRandomAlphabet(10));
      entry->set_value(GenRandomAlphabet(10));
      entry->set_pos(user_dictionary::UserDictionary::NOUN);
      entry->set_comment(GenRandomAlphabet(10));
      keys.push_back(entry->key());
    }
    EXPECT_TRUE(storage.Save());
    EXPECT_TRUE(storage.UnLock());
  }

  {
    scoped_ptr<UserDictionary> dic(CreateDictionary());
    // Wait for async reload called from the constructor.
    dic->WaitForReloader();
    dic->SetUserDictionaryName(filename);

    for (int i = 0; i < 32; ++i) {
      random_shuffle(keys.begin(), keys.end());
      dic->Reload();
      for (int i = 0; i < 1000; ++i) {
        CollectTokenCallback callback;
        dic->LookupPrefix(keys[i], false, &callback);
      }
    }
    dic->WaitForReloader();
  }
  FileUtil::Unlink(filename);
}

TEST_F(UserDictionaryTest, AddToAutoRegisteredDictionary) {
  const string filename = FileUtil::JoinPath(FLAGS_test_tmpdir,
                                             "add_to_auto_registered.db");
  FileUtil::Unlink(filename);

  // Create dictionary
  {
    UserDictionaryStorage storage(filename);
    EXPECT_FALSE(storage.Load());
    EXPECT_TRUE(storage.Lock());
    EXPECT_TRUE(storage.Save());
    EXPECT_TRUE(storage.UnLock());
  }

  // Add entries.
  {
    scoped_ptr<UserDictionary> dic(CreateDictionaryWithMockPos());
    dic->WaitForReloader();
    dic->SetUserDictionaryName(filename);
    for (int i = 0; i < 100; ++i) {
      EXPECT_TRUE(dic->AddToAutoRegisteredDictionary(
                      "key" + NumberUtil::SimpleItoa(i),
                      "value" + NumberUtil::SimpleItoa(i),
                      user_dictionary::UserDictionary::NOUN));
      dic->WaitForReloader();
    }
  }

  // Verify the contents.
  {
    UserDictionaryStorage storage(filename);
    EXPECT_TRUE(storage.Load());
    int index = 0;
    EXPECT_EQ(1, storage.dictionaries_size());
    EXPECT_EQ(100, storage.dictionaries(index).entries_size());
    for (int i = 0; i < 100; ++i) {
      EXPECT_EQ("key" + NumberUtil::SimpleItoa(i),
                storage.dictionaries(index).entries(i).key());
      EXPECT_EQ("value" + NumberUtil::SimpleItoa(i),
                storage.dictionaries(index).entries(i).value());
      EXPECT_EQ(user_dictionary::UserDictionary::NOUN,
                storage.dictionaries(index).entries(i).pos());
    }
  }

  FileUtil::Unlink(filename);

  // Create dictionary
  {
    UserDictionaryStorage storage(filename);
    EXPECT_FALSE(storage.Load());
    EXPECT_TRUE(storage.Lock());
    EXPECT_TRUE(storage.Save());
    EXPECT_TRUE(storage.UnLock());
  }

  // Add same entries.
  {
    scoped_ptr<UserDictionary> dic(CreateDictionaryWithMockPos());
    dic->WaitForReloader();
    dic->SetUserDictionaryName(filename);
    EXPECT_TRUE(dic->AddToAutoRegisteredDictionary(
        "key", "value", user_dictionary::UserDictionary::NOUN));
    dic->WaitForReloader();
    // Duplicated one is not registered.
    EXPECT_FALSE(dic->AddToAutoRegisteredDictionary(
        "key", "value", user_dictionary::UserDictionary::NOUN));
    dic->WaitForReloader();
  }

  // Verify the contents.
  {
    UserDictionaryStorage storage(filename);
    EXPECT_TRUE(storage.Load());
    EXPECT_EQ(1, storage.dictionaries_size());
    EXPECT_EQ(1, storage.dictionaries(0).entries_size());
    EXPECT_EQ("key", storage.dictionaries(0).entries(0).key());
    EXPECT_EQ("value", storage.dictionaries(0).entries(0).value());
    EXPECT_EQ(user_dictionary::UserDictionary::NOUN,
              storage.dictionaries(0).entries(0).pos());
  }
}

TEST_F(UserDictionaryTest, TestSuppressionDictionary) {
  scoped_ptr<UserDictionary> user_dic(CreateDictionaryWithMockPos());
  user_dic->WaitForReloader();

  const string filename = FileUtil::JoinPath(FLAGS_test_tmpdir,
                                             "suppression_test.db");
  FileUtil::Unlink(filename);

  UserDictionaryStorage storage(filename);

  // Create dictionary
  {
    uint64 id = 0;
    EXPECT_TRUE(storage.CreateDictionary("test", &id));
    UserDictionaryStorage::UserDictionary *dic =
        storage.mutable_dictionaries(0);
    for (size_t j = 0; j < 10000; ++j) {
      UserDictionaryStorage::UserDictionaryEntry *entry =
          dic->add_entries();
      entry->set_key("no_suppress_key" +
                     NumberUtil::SimpleItoa(static_cast<uint32>(j)));
      entry->set_value("no_suppress_value" +
                       NumberUtil::SimpleItoa(static_cast<uint32>(j)));
      entry->set_pos(user_dictionary::UserDictionary::NOUN);
    }

    for (size_t j = 0; j < 10; ++j) {
      UserDictionaryStorage::UserDictionaryEntry *entry =
          dic->add_entries();
      entry->set_key(
          "suppress_key" + NumberUtil::SimpleItoa(static_cast<uint32>(j)));
      entry->set_value(
          "suppress_value" + NumberUtil::SimpleItoa(static_cast<uint32>(j)));
      // entry->set_pos("抑制単語");
      entry->set_pos(user_dictionary::UserDictionary::SUPPRESSION_WORD);
    }

    suppression_dictionary_->Lock();
    EXPECT_TRUE(suppression_dictionary_->IsLocked());
    user_dic->Load(storage);
    EXPECT_FALSE(suppression_dictionary_->IsLocked());

    for (size_t j = 0; j < 10; ++j) {
      EXPECT_TRUE(suppression_dictionary_->SuppressEntry(
          "suppress_key" + NumberUtil::SimpleItoa(static_cast<uint32>(j)),
          "suppress_value" + NumberUtil::SimpleItoa(static_cast<uint32>(j))));
    }
  }

  // Remove suppression entry
  {
    storage.Clear();
    uint64 id = 0;
    EXPECT_TRUE(storage.CreateDictionary("test", &id));
    UserDictionaryStorage::UserDictionary *dic =
        storage.mutable_dictionaries(0);
    for (size_t j = 0; j < 10000; ++j) {
      UserDictionaryStorage::UserDictionaryEntry *entry =
          dic->add_entries();
      entry->set_key(
          "no_suppress_key" + NumberUtil::SimpleItoa(static_cast<uint32>(j)));
      entry->set_value(
          "no_suppress_value" + NumberUtil::SimpleItoa(static_cast<uint32>(j)));
      entry->set_pos(user_dictionary::UserDictionary::NOUN);
    }

    suppression_dictionary_->Lock();
    user_dic->Load(storage);
    EXPECT_FALSE(suppression_dictionary_->IsLocked());

    for (size_t j = 0; j < 10; ++j) {
      EXPECT_FALSE(suppression_dictionary_->SuppressEntry(
          "suppress_key" + NumberUtil::SimpleItoa(static_cast<uint32>(j)),
          "suppress_value" + NumberUtil::SimpleItoa(static_cast<uint32>(j))));
    }
  }
  FileUtil::Unlink(filename);
}

TEST_F(UserDictionaryTest, TestSuggestionOnlyWord) {
  scoped_ptr<UserDictionary> user_dic(CreateDictionary());
  user_dic->WaitForReloader();

  const string filename = FileUtil::JoinPath(FLAGS_test_tmpdir,
                                             "suggestion_only_test.db");
  FileUtil::Unlink(filename);

  UserDictionaryStorage storage(filename);

  // Create dictionary
  {
    uint64 id = 0;
    EXPECT_TRUE(storage.CreateDictionary("test", &id));
    UserDictionaryStorage::UserDictionary *dic =
        storage.mutable_dictionaries(0);

    for (size_t j = 0; j < 10; ++j) {
      UserDictionaryStorage::UserDictionaryEntry *entry =
          dic->add_entries();
      entry->set_key("key" + NumberUtil::SimpleItoa(static_cast<uint32>(j)));
      entry->set_value("default");
      // "名詞"
      entry->set_pos(user_dictionary::UserDictionary::NOUN);
    }

    for (size_t j = 0; j < 10; ++j) {
      UserDictionaryStorage::UserDictionaryEntry *entry =
          dic->add_entries();
      entry->set_key("key" + NumberUtil::SimpleItoa(static_cast<uint32>(j)));
      entry->set_value("suggest_only");
      // "サジェストのみ"
      entry->set_pos(user_dictionary::UserDictionary::SUGGESTION_ONLY);
    }

    user_dic->Load(storage);
  }

  {
    const char kKey[] = "key0123";
    CollectTokenCallback callback;
    user_dic->LookupPrefix(kKey, false, &callback);
    const vector<Token> &tokens = callback.tokens();
    for (size_t i = 0; i < tokens.size(); ++i) {
      EXPECT_EQ("default", tokens[i].value);
    }
  }
  {
    const char kKey[] = "key";
    CollectTokenCallback callback;
    user_dic->LookupPredictive(kKey, false, &callback);
    const vector<Token> &tokens = callback.tokens();
    for (size_t i = 0; i < tokens.size(); ++i) {
      EXPECT_TRUE(tokens[i].value == "suggest_only" ||
                  tokens[i].value == "default");
    }
  }

  FileUtil::Unlink(filename);
}

TEST_F(UserDictionaryTest, TestUsageStats) {
  scoped_ptr<UserDictionary> dic(CreateDictionaryWithMockPos());
  // Wait for async reload called from the constructor.
  dic->WaitForReloader();
  UserDictionaryStorage storage("");

  {
    UserDictionaryStorage::UserDictionary *dic1 = storage.add_dictionaries();
    CHECK(dic1);
    UserDictionaryStorage::UserDictionaryEntry *entry;
    entry = dic1->add_entries();
    CHECK(entry);
    entry->set_key("key1");
    entry->set_value("value1");
    entry->set_pos(user_dictionary::UserDictionary::NOUN);
    entry = dic1->add_entries();
    CHECK(entry);
    entry->set_key("key2");
    entry->set_value("value2");
    entry->set_pos(user_dictionary::UserDictionary::NOUN);
  }
  {
    UserDictionaryStorage::UserDictionary *dic2 = storage.add_dictionaries();
    CHECK(dic2);
    UserDictionaryStorage::UserDictionaryEntry *entry;
    entry = dic2->add_entries();
    CHECK(entry);
    entry->set_key("key3");
    entry->set_value("value3");
    entry->set_pos(user_dictionary::UserDictionary::NOUN);
    entry = dic2->add_entries();
    CHECK(entry);
    entry->set_key("key4");
    entry->set_value("value4");
    entry->set_pos(user_dictionary::UserDictionary::NOUN);
    entry = dic2->add_entries();
    CHECK(entry);
    entry->set_key("key5");
    entry->set_value("value5");
    entry->set_pos(user_dictionary::UserDictionary::NOUN);
  }
  dic->Load(storage);

  EXPECT_INTEGER_STATS("UserRegisteredWord", 5);
}

TEST_F(UserDictionaryTest, LookupComment) {
  scoped_ptr<UserDictionary> dic(CreateDictionaryWithMockPos());
  // Wait for async reload called from the constructor.
  dic->WaitForReloader();

  {
    UserDictionaryStorage storage("");
    UserDictionaryTest::LoadFromString(kUserDictionary0, &storage);
    dic->Load(storage);
  }

  // Entry is in user dictionary but has no comment.
  string comment;
  comment = "prev comment";
  EXPECT_FALSE(dic->LookupComment("comment_key1", "comment_value2", &comment));
  EXPECT_EQ("prev comment", comment);

  // Usual case: single key-value pair with comment.
  EXPECT_TRUE(dic->LookupComment("comment_key2", "comment_value2", &comment));
  EXPECT_EQ("comment", comment);

  // There exist two entries having the same key, value and POS.  Since POS is
  // irrelevant to comment lookup, the first nonempty comment should be found.
  EXPECT_TRUE(dic->LookupComment("comment_key3", "comment_value3", &comment));
  EXPECT_EQ("comment1", comment);

  // White-space only comments should be cleared.
  EXPECT_FALSE(dic->LookupComment("comment_key4", "comment_value4", &comment));
  // The previous comment should remain.
  EXPECT_EQ("comment1", comment);

  // Comment should be found iff key and value match.
  EXPECT_TRUE(LookupComment(*dic, "comment_key", "mismatching_value").empty());
  EXPECT_TRUE(LookupComment(*dic, "comment_key1", "mismatching_value").empty());
  EXPECT_TRUE(LookupComment(*dic, "comment_key2", "mismatching_value").empty());
  EXPECT_TRUE(LookupComment(*dic, "comment_key3", "mismatching_value").empty());
  EXPECT_TRUE(LookupComment(*dic, "comment_key4", "mismatching_value").empty());
  EXPECT_TRUE(LookupComment(*dic, "mismatching_key", "comment_value").empty());
  EXPECT_TRUE(LookupComment(*dic, "mismatching_key", "comment_value1").empty());
  EXPECT_TRUE(LookupComment(*dic, "mismatching_key", "comment_value2").empty());
  EXPECT_TRUE(LookupComment(*dic, "mismatching_key", "comment_value3").empty());
  EXPECT_TRUE(LookupComment(*dic, "mismatching_key", "comment_value4").empty());
}

}  // namespace
}  // namespace mozc
