Codebase list mozc / debian/0.11.svn13-1 composer / table_test.cc
debian/0.11.svn13-1

Tree @debian/0.11.svn13-1 (Download .tar.gz)

table_test.cc @debian/0.11.svn13-1raw · history · blame

// 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 "composer/table.h"

#include "base/base.h"
#include "base/util.h"
#include "testing/base/public/gunit.h"
#include "session/config.pb.h"
#include "session/config_handler.h"

DECLARE_string(test_tmpdir);

// This macro is ported from base/basictypes.h.  Due to WinNT.h has
// the same macro, this macro should be undefined at the end of this
// file.
// TODO(komatsu): Move this macro to base or testing.
#ifndef ARRAYSIZE
#define UNDEFINE_ARRAYSIZE
#define ARRAYSIZE(a) \
  ((sizeof(a) / sizeof(*(a))) / \
    static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
#endif  // ARRAYSIZE

static void InitTable(mozc::composer::Table* table) {
  // "あ"
  table->AddRule("a",  "\xe3\x81\x82", "");
  // "い"
  table->AddRule("i",  "\xe3\x81\x84", "");
  // "か"
  table->AddRule("ka", "\xe3\x81\x8b", "");
  // "き"
  table->AddRule("ki", "\xe3\x81\x8d", "");
  // "く"
  table->AddRule("ku", "\xe3\x81\x8f", "");
  // "け"
  table->AddRule("ke", "\xe3\x81\x91", "");
  // "こ"
  table->AddRule("ko", "\xe3\x81\x93", "");
  // "っ"
  table->AddRule("kk", "\xe3\x81\xa3", "k");
  // "な"
  table->AddRule("na", "\xe3\x81\xaa", "");
  // "に"
  table->AddRule("ni", "\xe3\x81\xab", "");
  // "ん"
  table->AddRule("n",  "\xe3\x82\x93", "");
  // "ん"
  table->AddRule("nn", "\xe3\x82\x93", "");
}

string GetResult(const mozc::composer::Table &table, const string &key) {
  const mozc::composer::Entry *entry = table.LookUp(key);
  if (entry == NULL) {
    return "<NULL>";
  }
  return entry->result();
}

string GetInput(const mozc::composer::Table &table, const string &key) {
  const mozc::composer::Entry *entry = table.LookUp(key);
  if (entry == NULL) {
    return "<NULL>";
  }
  return entry->input();
}

TEST(TableTest, LookUp) {
  static const struct TestCase {
    const char* input;
    const bool expected_result;
    const char* expected_output;
    const char* expected_pending;
  } test_cases[] = {
    // "あ"
    { "a", true, "\xe3\x81\x82", "" },
    { "k", false, "", "" },
    // "か"
    { "ka", true, "\xe3\x81\x8b", "" },
    // "き"
    { "ki", true, "\xe3\x81\x8d", "" },
    // "く"
    { "ku", true, "\xe3\x81\x8f", "" },
    // "っ"
    { "kk", true, "\xe3\x81\xa3", "k" },
    { "aka", false, "", "" },
    // "な"
    { "na", true, "\xe3\x81\xaa", "" },
    // "ん"
    { "n", true, "\xe3\x82\x93", "" },
    // "ん"
    { "nn", true, "\xe3\x82\x93", "" },
  };
  static const int size = ARRAYSIZE(test_cases);

  mozc::composer::Table table;
  InitTable(&table);

  for (int i = 0; i < size; ++i) {
    const TestCase& test = test_cases[i];
    string output;
    string pending;
    const mozc::composer::Entry* entry;
    entry = table.LookUp(test.input);

    EXPECT_EQ(test.expected_result, (entry != NULL));
    if (entry == NULL) {
      continue;
    }
    EXPECT_EQ(test.expected_output, entry->result());
    EXPECT_EQ(test.expected_pending, entry->pending());
  }
}

TEST(TableTest, Puncutations) {
  static const struct TestCase {
    mozc::config::Config::PunctuationMethod method;
    const char *input;
    const char *expected;
  } test_cases[] = {
    // "、"
    { mozc::config::Config::KUTEN_TOUTEN, ",",  "\xe3\x80\x81" },
    // "。"
    { mozc::config::Config::KUTEN_TOUTEN, ".",  "\xe3\x80\x82" },
    // ","
    { mozc::config::Config::COMMA_PERIOD, ",",  "\xef\xbc\x8c" },
    // "."
    { mozc::config::Config::COMMA_PERIOD, ".",  "\xef\xbc\x8e" },
    // "、"
    { mozc::config::Config::KUTEN_PERIOD, ",",  "\xe3\x80\x81" },
    // "."
    { mozc::config::Config::KUTEN_PERIOD, ".",  "\xef\xbc\x8e" },
    // ","
    { mozc::config::Config::COMMA_TOUTEN, ",",  "\xef\xbc\x8c" },
    // "。"
    { mozc::config::Config::COMMA_TOUTEN, ".",  "\xe3\x80\x82" },
  };

  const string config_file = mozc::Util::JoinPath(FLAGS_test_tmpdir,
                                                  "mozc_config_test_tmp");
  mozc::Util::Unlink(config_file);
  mozc::config::ConfigHandler::SetConfigFileName(config_file);
  mozc::config::ConfigHandler::Reload();

  for (int i = 0; i < ARRAYSIZE(test_cases); ++i) {
    mozc::config::Config config;
    config.set_punctuation_method(test_cases[i].method);
    EXPECT_TRUE(mozc::config::ConfigHandler::SetConfig(config));
    mozc::composer::Table table;
    table.Initialize();
    const mozc::composer::Entry *entry = table.LookUp(test_cases[i].input);
    EXPECT_TRUE(entry != NULL);
    EXPECT_EQ(test_cases[i].expected, entry->result());
  }
}

TEST(TableTest, Symbols) {
  static const struct TestCase {
    mozc::config::Config::SymbolMethod method;
    const char *input;
    const char *expected;
  } test_cases[] = {
    // "「"
    { mozc::config::Config::CORNER_BRACKET_MIDDLE_DOT, "[",  "\xe3\x80\x8c" },
    // "」"
    { mozc::config::Config::CORNER_BRACKET_MIDDLE_DOT, "]",  "\xe3\x80\x8d" },
    // "・"
    { mozc::config::Config::CORNER_BRACKET_MIDDLE_DOT, "/",  "\xe3\x83\xbb" },
    { mozc::config::Config::SQUARE_BRACKET_SLASH, "[",  "["      },
    { mozc::config::Config::SQUARE_BRACKET_SLASH, "]",  "]"      },
    // "/"
    { mozc::config::Config::SQUARE_BRACKET_SLASH, "/",  "\xef\xbc\x8f"      },
    // "「"
    { mozc::config::Config::CORNER_BRACKET_SLASH, "[",  "\xe3\x80\x8c"      },
    // "」"
    { mozc::config::Config::CORNER_BRACKET_SLASH, "]",  "\xe3\x80\x8d"      },
    // "/"
    { mozc::config::Config::CORNER_BRACKET_SLASH, "/",  "\xef\xbc\x8f"      },
    { mozc::config::Config::SQUARE_BRACKET_MIDDLE_DOT, "[",  "[" },
    { mozc::config::Config::SQUARE_BRACKET_MIDDLE_DOT, "]",  "]" },
    // "・"
    { mozc::config::Config::SQUARE_BRACKET_MIDDLE_DOT, "/",  "\xe3\x83\xbb" },
  };

  const string config_file = mozc::Util::JoinPath(FLAGS_test_tmpdir,
                                                  "mozc_config_test_tmp");
  mozc::Util::Unlink(config_file);
  mozc::config::ConfigHandler::SetConfigFileName(config_file);
  mozc::config::ConfigHandler::Reload();

  for (int i = 0; i < ARRAYSIZE(test_cases); ++i) {
    mozc::config::Config config;
    config.set_symbol_method(test_cases[i].method);
    EXPECT_TRUE(mozc::config::ConfigHandler::SetConfig(config));
    mozc::composer::Table table;
    table.Initialize();
    const mozc::composer::Entry *entry = table.LookUp(test_cases[i].input);
    EXPECT_TRUE(entry != NULL);
    EXPECT_EQ(test_cases[i].expected, entry->result());
  }
}

TEST(TableTest, KanaSuppressed) {
  mozc::config::Config config;
  mozc::config::ConfigHandler::GetConfig(&config);

  config.set_preedit_method(mozc::config::Config::KANA);
  mozc::config::ConfigHandler::SetConfig(config);

  mozc::composer::Table table;
  table.Initialize();

  const mozc::composer::Entry *entry = table.LookUp("a");
  EXPECT_TRUE(entry != NULL);
  // "あ"
  EXPECT_EQ("\xE3\x81\x82", entry->result());
  EXPECT_TRUE(entry->pending().empty());
}

TEST(TableTest, KanaCombination) {
  mozc::composer::Table table;
  ASSERT_TRUE(table.Initialize());
  // "か゛"
  const mozc::composer::Entry *entry = table.LookUp("\xE3\x81\x8B\xE3\x82\x9B");
  EXPECT_TRUE(entry != NULL);
  // "が"
  EXPECT_EQ("\xE3\x81\x8C", entry->result());
  EXPECT_TRUE(entry->pending().empty());
}

TEST(TableTest, InvalidEntryTest) {
  {
    mozc::composer::Table table;
    table.AddRule("a", "aa", "");
    table.AddRule("b", "aa", "a");  // looping
    EXPECT_TRUE(table.LookUp("a") != NULL);
    EXPECT_TRUE(table.LookUp("b") == NULL);
  }

  {
    mozc::composer::Table table;
    table.AddRule("a", "aa", "c");
    table.AddRule("c", "aa", "b");
    table.AddRule("d", "aa", "a");  // looping
    EXPECT_TRUE(table.LookUp("a") != NULL);
    EXPECT_TRUE(table.LookUp("c") != NULL);
    EXPECT_TRUE(table.LookUp("d") == NULL);
  }

  {
    mozc::composer::Table table;
    table.AddRule("a", "aa", "a");
    EXPECT_TRUE(table.LookUp("a") == NULL);
  }
}

TEST(TableTest, CustomPunctuationsAndSymbols) {
  // Test against Issue2465801.
  string custom_roman_table;
  custom_roman_table.append("mozc\tMOZC\n");
  custom_roman_table.append(",\tCOMMA\n");
  custom_roman_table.append(".\tPERIOD\n");
  custom_roman_table.append("/\tSLASH\n");
  custom_roman_table.append("[\tOPEN\n");
  custom_roman_table.append("]\tCLOSE\n");

  mozc::config::Config config;
  config.set_custom_roman_table(custom_roman_table);
  EXPECT_TRUE(mozc::config::ConfigHandler::SetConfig(config));

  mozc::composer::Table table;
  table.Initialize();

  const mozc::composer::Entry *entry = NULL;
  entry = table.LookUp("mozc");
  ASSERT_TRUE(entry != NULL);
  EXPECT_EQ("MOZC", entry->result());

  entry = table.LookUp(",");
  ASSERT_TRUE(entry != NULL);
  EXPECT_EQ("COMMA", entry->result());

  entry = table.LookUp(".");
  ASSERT_TRUE(entry != NULL);
  EXPECT_EQ("PERIOD", entry->result());

  entry = table.LookUp("/");
  ASSERT_TRUE(entry != NULL);
  EXPECT_EQ("SLASH", entry->result());

  entry = table.LookUp("[");
  ASSERT_TRUE(entry != NULL);
  EXPECT_EQ("OPEN", entry->result());

  entry = table.LookUp("]");
  ASSERT_TRUE(entry != NULL);
  EXPECT_EQ("CLOSE", entry->result());
}

TEST(TableTest, CaseSensitive) {
  mozc::composer::Table table;
  table.AddRule("a", "[a]", "");
  table.AddRule("A", "[A]", "");
  table.AddRule("ba", "[ba]", "");
  table.AddRule("BA", "[BA]", "");
  table.AddRule("Ba", "[Ba]", "");
  // The rule of "bA" is intentionally dropped.
  // table.AddRule("bA",  "[bA]", "");
  table.AddRule("za", "[za]", "");

  // case insensitive (default)
  EXPECT_FALSE(table.case_sensitive());
  EXPECT_EQ("[a]", GetResult(table, "a"));
  EXPECT_EQ("[a]", GetResult(table, "A"));
  EXPECT_EQ("[ba]", GetResult(table, "ba"));
  EXPECT_EQ("[ba]", GetResult(table, "BA"));
  EXPECT_EQ("[ba]", GetResult(table, "Ba"));
  EXPECT_EQ("[ba]", GetResult(table, "bA"));

  EXPECT_EQ("a", GetInput(table, "a"));
  EXPECT_EQ("a", GetInput(table, "A"));
  EXPECT_EQ("ba", GetInput(table, "ba"));
  EXPECT_EQ("ba", GetInput(table, "BA"));
  EXPECT_EQ("ba", GetInput(table, "Ba"));
  EXPECT_EQ("ba", GetInput(table, "bA"));

  // Test for HasSubRules
  EXPECT_TRUE(table.HasSubRules("Z"));

  {  // Test for LookUpPrefix
    const mozc::composer::Entry *entry = NULL;
    size_t key_length = 0;
    bool fixed = false;
    entry = table.LookUpPrefix("bA", &key_length, &fixed);
    EXPECT_TRUE(entry != NULL);
    EXPECT_EQ("[ba]", entry->result());
    EXPECT_EQ(2, key_length);
    EXPECT_TRUE(fixed);
  }

  // case sensitive
  table.set_case_sensitive(true);
  EXPECT_TRUE(table.case_sensitive());
  EXPECT_EQ("[a]", GetResult(table, "a"));
  EXPECT_EQ("[A]", GetResult(table, "A"));
  EXPECT_EQ("[ba]", GetResult(table, "ba"));
  EXPECT_EQ("[BA]", GetResult(table, "BA"));
  EXPECT_EQ("[Ba]", GetResult(table, "Ba"));
  EXPECT_EQ("<NULL>", GetResult(table, "bA"));

  EXPECT_EQ("a", GetInput(table, "a"));
  EXPECT_EQ("A", GetInput(table, "A"));
  EXPECT_EQ("ba", GetInput(table, "ba"));
  EXPECT_EQ("BA", GetInput(table, "BA"));
  EXPECT_EQ("Ba", GetInput(table, "Ba"));
  EXPECT_EQ("<NULL>", GetInput(table, "bA"));

  // Test for HasSubRules
  EXPECT_FALSE(table.HasSubRules("Z"));

  {  // Test for LookUpPrefix
    const mozc::composer::Entry *entry = NULL;
    size_t key_length = 0;
    bool fixed = false;
    entry = table.LookUpPrefix("bA", &key_length, &fixed);
    EXPECT_TRUE(entry == NULL);
    EXPECT_EQ(1, key_length);
    EXPECT_TRUE(fixed);
  }
}

#ifdef UNDEFINE_ARRAYSIZE
#undef ARRAYSIZE
#endif  // UNDEFINE_ARRAYSIZE