| // 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 "dictionary/user_dictionary_storage.h" |
| |
| #ifndef OS_WINDOWS |
| #include <sys/stat.h> |
| #endif |
| |
| #include <algorithm> |
| #include "base/base.h" |
| #include "base/file_stream.h" |
| #include "base/util.h" |
| #include "dictionary/user_dictionary_importer.h" |
| #include "dictionary/user_dictionary_util.h" |
| #include "testing/base/public/googletest.h" |
| #include "testing/base/public/gunit.h" |
| |
| DECLARE_string(test_tmpdir); |
| |
| namespace mozc { |
| namespace { |
| |
| int Random(int size) { |
| return static_cast<int> (1.0 * size * rand() / (RAND_MAX + 1.0)); |
| } |
| |
| string GenRandomString(int size) { |
| string result; |
| const size_t len = Random(size) + 1; |
| for (int i = 0; i < len; ++i) { |
| const uint16 l = Random(static_cast<int>('~' - ' ')) + ' '; |
| Util::UCS2ToUTF8Append(l, &result); |
| } |
| return result; |
| } |
| |
| string GetUserDictionaryFile() { |
| #ifndef OS_WINDOWS |
| chmod(FLAGS_test_tmpdir.c_str(), 0777); |
| #endif |
| return Util::JoinPath(FLAGS_test_tmpdir, "test.db"); |
| } |
| } // namespace |
| |
| TEST(UserDictionaryStorage, FileTest) { |
| Util::SetUserProfileDirectory(FLAGS_test_tmpdir); |
| Util::Unlink(GetUserDictionaryFile()); |
| UserDictionaryStorage storage(GetUserDictionaryFile()); |
| EXPECT_EQ(storage.filename(), GetUserDictionaryFile()); |
| EXPECT_FALSE(storage.Exists()); |
| } |
| |
| TEST(UserDictionaryStorage, LockTest) { |
| Util::SetUserProfileDirectory(FLAGS_test_tmpdir); |
| Util::Unlink(GetUserDictionaryFile()); |
| UserDictionaryStorage storage1(GetUserDictionaryFile()); |
| UserDictionaryStorage storage2(GetUserDictionaryFile()); |
| EXPECT_TRUE(storage1.Lock()); |
| EXPECT_FALSE(storage2.Lock()); |
| EXPECT_FALSE(storage2.Save()); |
| EXPECT_TRUE(storage1.UnLock()); |
| EXPECT_TRUE(storage2.Lock()); |
| EXPECT_TRUE(storage2.Save()); |
| } |
| |
| TEST(UserDictionaryStorage, BasicOperationsTest) { |
| Util::SetUserProfileDirectory(FLAGS_test_tmpdir); |
| Util::Unlink(GetUserDictionaryFile()); |
| |
| UserDictionaryStorage storage(GetUserDictionaryFile()); |
| EXPECT_FALSE(storage.Load()); |
| |
| const size_t kDictionariesSize = 3; |
| uint64 id[kDictionariesSize]; |
| |
| for (size_t i = 0; i < kDictionariesSize; ++i) { |
| EXPECT_TRUE(storage.CreateDictionary("test" + Util::SimpleItoa(i), &id[i])); |
| EXPECT_EQ(i + 1, storage.dictionaries_size()); |
| } |
| |
| for (size_t i = 0; i < kDictionariesSize; ++i) { |
| EXPECT_EQ(i, storage.GetUserDictionaryIndex(id[i])); |
| EXPECT_EQ(-1, storage.GetUserDictionaryIndex(id[i] + 1)); |
| } |
| |
| for (size_t i = 0; i < kDictionariesSize; ++i) { |
| EXPECT_EQ(storage.mutable_dictionaries(i), |
| storage.GetUserDictionary(id[i])); |
| EXPECT_EQ(NULL, storage.GetUserDictionary(id[i] + 1)); |
| } |
| |
| // empty |
| EXPECT_FALSE(storage.RenameDictionary(id[0], "")); |
| |
| // invalid id |
| EXPECT_FALSE(storage.RenameDictionary(0, "")); |
| |
| EXPECT_TRUE(storage.RenameDictionary(id[0], "renamed0")); |
| EXPECT_EQ("renamed0", storage.dictionaries(0).name()); |
| |
| // invalid id |
| EXPECT_FALSE(storage.DeleteDictionary(0)); |
| |
| EXPECT_TRUE(storage.DeleteDictionary(id[1])); |
| EXPECT_EQ(2, storage.dictionaries_size()); |
| } |
| |
| TEST(UserDictionaryStorage, DeleteTest) { |
| Util::SetUserProfileDirectory(FLAGS_test_tmpdir); |
| Util::Unlink(GetUserDictionaryFile()); |
| |
| UserDictionaryStorage storage(GetUserDictionaryFile()); |
| EXPECT_FALSE(storage.Load()); |
| |
| // repeat 10 times |
| for (int i = 0; i < 10; ++i) { |
| storage.Clear(); |
| vector<uint64> ids(100); |
| for (size_t i = 0; i < ids.size(); ++i) { |
| EXPECT_TRUE(storage.CreateDictionary("test", &ids[i])); |
| } |
| |
| vector<uint64> alive; |
| for (size_t i = 0; i < ids.size(); ++i) { |
| if (Random(3) == 0) { // 30% |
| EXPECT_TRUE(storage.DeleteDictionary(ids[i])); |
| continue; |
| } |
| alive.push_back(ids[i]); |
| } |
| |
| EXPECT_EQ(alive.size(), storage.dictionaries_size()); |
| |
| for (size_t i = 0; i < alive.size(); ++i) { |
| EXPECT_EQ(alive[i], storage.dictionaries(i).id()); |
| } |
| } |
| } |
| |
| TEST(UserDictionaryStorage, ExportTest) { |
| Util::SetUserProfileDirectory(FLAGS_test_tmpdir); |
| UserDictionaryStorage storage(GetUserDictionaryFile()); |
| uint64 id = 0; |
| |
| EXPECT_TRUE(storage.CreateDictionary("test", &id)); |
| |
| UserDictionaryStorage::UserDictionary *dic = |
| storage.GetUserDictionary(id); |
| |
| for (size_t i = 0; i < 1000; ++i) { |
| UserDictionaryStorage::UserDictionaryEntry *entry = dic->add_entries(); |
| const string prefix = Util::SimpleItoa(i); |
| // set empty fields randomly |
| entry->set_key(prefix + "key"); |
| entry->set_value(prefix + "value"); |
| // "名詞" |
| entry->set_pos("\xe5\x90\x8d\xe8\xa9\x9e"); |
| entry->set_comment(prefix + "comment"); |
| } |
| |
| const string export_file = Util::JoinPath(FLAGS_test_tmpdir, |
| "export.txt"); |
| |
| EXPECT_FALSE(storage.ExportDictionary(id + 1, export_file)); |
| EXPECT_TRUE(storage.ExportDictionary(id, export_file)); |
| |
| UserDictionaryStorage::UserDictionary dic2; |
| InputFileStream ifs(export_file.c_str()); |
| CHECK(ifs); |
| UserDictionaryImporter::IStreamTextLineIterator iter(&ifs); |
| |
| EXPECT_EQ(UserDictionaryImporter::IMPORT_NO_ERROR, |
| UserDictionaryImporter::ImportFromTextLineIterator( |
| UserDictionaryImporter::MOZC, |
| &iter, &dic2)); |
| |
| dic2.set_id(id); |
| dic2.set_name("test"); |
| |
| EXPECT_EQ(dic2.DebugString(), dic->DebugString()); |
| } |
| |
| TEST(UserDictionaryStorage, SerializeTest) { |
| Util::SetUserProfileDirectory(FLAGS_test_tmpdir); |
| |
| // repeat 20 times |
| for (int i = 0; i < 20; ++i) { |
| Util::Unlink(GetUserDictionaryFile()); |
| UserDictionaryStorage storage1(GetUserDictionaryFile()); |
| |
| { |
| EXPECT_FALSE(storage1.Load()); |
| const size_t dic_size = Random(50) + 1; |
| |
| for (size_t i = 0; i < dic_size; ++i) { |
| uint64 id = 0; |
| EXPECT_TRUE(storage1.CreateDictionary(GenRandomString(10), |
| &id)); |
| const size_t entry_size = Random(100) + 1; |
| for (size_t j = 0; j < entry_size; ++j) { |
| UserDictionaryStorage::UserDictionary *dic = |
| storage1.mutable_dictionaries(i); |
| UserDictionaryStorage::UserDictionaryEntry *entry = |
| dic->add_entries(); |
| entry->set_key(GenRandomString(10)); |
| entry->set_value(GenRandomString(10)); |
| entry->set_pos(GenRandomString(10)); |
| entry->set_comment(GenRandomString(10)); |
| } |
| } |
| |
| EXPECT_TRUE(storage1.Lock()); |
| EXPECT_TRUE(storage1.Save()); |
| EXPECT_TRUE(storage1.UnLock()); |
| } |
| |
| UserDictionaryStorage storage2(GetUserDictionaryFile()); |
| { |
| EXPECT_TRUE(storage2.Load()); |
| } |
| |
| EXPECT_EQ(storage1.DebugString(), storage2.DebugString()); |
| } |
| } |
| } // namespace mozc |