| // 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 <string> |
| |
| #include "base/file_util.h" |
| #include "base/scoped_ptr.h" |
| #include "base/system_util.h" |
| #include "composer/composer.h" |
| #include "composer/table.h" |
| #include "config/config.pb.h" |
| #include "config/config_handler.h" |
| #include "converter/conversion_request.h" |
| #include "converter/converter_interface.h" |
| #include "converter/segments.h" |
| #include "engine/engine_factory.h" |
| #include "engine/engine_interface.h" |
| #include "session/commands.pb.h" |
| #include "testing/base/public/gunit.h" |
| |
| #ifdef OS_ANDROID |
| #include "base/mmap.h" |
| #include "base/singleton.h" |
| #include "data_manager/android/android_data_manager.h" |
| #endif |
| |
| DECLARE_string(test_srcdir); |
| DECLARE_string(test_tmpdir); |
| |
| namespace mozc { |
| |
| using mozc::commands::Request; |
| using mozc::composer::Composer; |
| using mozc::composer::Table; |
| using mozc::config::Config; |
| using mozc::config::ConfigHandler; |
| |
| namespace { |
| #ifdef OS_ANDROID |
| // In actual libmozc.so usage, the dictionary data will be given via JNI call |
| // because only Java side code knows where the data is. |
| // On native code unittest, we cannot do it, so instead we mmap the files |
| // and use it. |
| // Note that this technique works here because the no other test code doesn't |
| // link to this binary. |
| // TODO(hidehiko): Get rid of this hack by refactoring Engine/DataManager |
| // related code. |
| class AndroidInitializer { |
| private: |
| AndroidInitializer() { |
| string dictionary_data_path = FileUtil::JoinPath( |
| FLAGS_test_srcdir, "embedded_data/dictionary_data"); |
| CHECK(dictionary_mmap_.Open(dictionary_data_path.c_str(), "r")); |
| mozc::android::AndroidDataManager::SetDictionaryData( |
| dictionary_mmap_.begin(), dictionary_mmap_.size()); |
| |
| string connection_data_path = FileUtil::JoinPath( |
| FLAGS_test_srcdir, "embedded_data/connection_data"); |
| CHECK(connection_mmap_.Open(connection_data_path.c_str(), "r")); |
| mozc::android::AndroidDataManager::SetConnectionData( |
| connection_mmap_.begin(), connection_mmap_.size()); |
| LOG(ERROR) << "mmap data initialized."; |
| } |
| |
| friend class Singleton<AndroidInitializer>; |
| |
| Mmap dictionary_mmap_; |
| Mmap connection_mmap_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AndroidInitializer); |
| }; |
| #endif // OS_ANDROID |
| } // namespace |
| |
| class ConverterRegressionTest : public ::testing::Test { |
| protected: |
| ConverterRegressionTest() { |
| } |
| virtual ~ConverterRegressionTest() { |
| } |
| |
| virtual void SetUp() { |
| #ifdef OS_ANDROID |
| Singleton<AndroidInitializer>::get(); |
| #endif |
| |
| user_profile_directory_backup_ = SystemUtil::GetUserProfileDirectory(); |
| config_backup_.CopyFrom(ConfigHandler::GetConfig()); |
| |
| // set default user profile directory |
| SystemUtil::SetUserProfileDirectory(FLAGS_test_tmpdir); |
| Config config; |
| ConfigHandler::GetDefaultConfig(&config); |
| ConfigHandler::SetConfig(config); |
| } |
| |
| virtual void TearDown() { |
| ConfigHandler::SetConfig(config_backup_); |
| SystemUtil::SetUserProfileDirectory(user_profile_directory_backup_); |
| } |
| |
| private: |
| string user_profile_directory_backup_; |
| Config config_backup_; |
| }; |
| |
| TEST_F(ConverterRegressionTest, QueryOfDeathTest) { |
| scoped_ptr<EngineInterface> engine(EngineFactory::Create()); |
| ConverterInterface *converter = engine->GetConverter(); |
| |
| CHECK(converter); |
| { |
| Segments segments; |
| // "りゅきゅけmぽ" |
| EXPECT_TRUE(converter->StartConversion( |
| &segments, |
| "\xE3\x82\x8A\xE3\x82\x85" |
| "\xE3\x81\x8D\xE3\x82\x85" |
| "\xE3\x81\x91" |
| "m" |
| "\xE3\x81\xBD")); |
| } |
| { |
| Segments segments; |
| EXPECT_TRUE(converter->StartConversion(&segments, "5.1,||t:1")); |
| } |
| { |
| Segments segments; |
| // Converter returns false, but not crash. |
| EXPECT_FALSE(converter->StartConversion(&segments, "")); |
| } |
| { |
| Segments segments; |
| ConversionRequest conv_request; |
| // Create an empty composer. |
| const Table table; |
| const commands::Request request; |
| composer::Composer composer(&table, &request); |
| conv_request.set_composer(&composer); |
| // Converter returns false, but not crash. |
| EXPECT_FALSE(converter->StartConversionForRequest(conv_request, |
| &segments)); |
| } |
| } |
| |
| TEST_F(ConverterRegressionTest, Regression3323108) { |
| scoped_ptr<EngineInterface> engine(EngineFactory::Create()); |
| ConverterInterface *converter = engine->GetConverter(); |
| Segments segments; |
| |
| // "ここではきものをぬぐ" |
| EXPECT_TRUE(converter->StartConversion( |
| &segments, |
| "\xE3\x81\x93\xE3\x81\x93\xE3\x81\xA7" |
| "\xE3\x81\xAF\xE3\x81\x8D\xE3\x82\x82" |
| "\xE3\x81\xAE\xE3\x82\x92\xE3\x81\xAC" |
| "\xE3\x81\x90")); |
| EXPECT_EQ(3, segments.conversion_segments_size()); |
| const ConversionRequest default_request; |
| EXPECT_TRUE(converter->ResizeSegment(&segments, default_request, 1, 2)); |
| EXPECT_EQ(2, segments.conversion_segments_size()); |
| |
| // "きものをぬぐ" |
| EXPECT_EQ("\xE3\x81\x8D\xE3\x82\x82" |
| "\xE3\x81\xAE\xE3\x82\x92" |
| "\xE3\x81\xAC\xE3\x81\x90", |
| segments.conversion_segment(1).key()); |
| } |
| |
| } // namespace mozc |