247 lines
8.8 KiB
C++
247 lines
8.8 KiB
C++
#include "tests/includes/test_framework.h"
|
|
#include "src/session/engine_input_session.h"
|
|
#include "MetasequoiaImeEngine/shuangpin/shuangpin_dictionary.h"
|
|
#include <algorithm>
|
|
|
|
namespace
|
|
{
|
|
void InputLetters(EngineInputSession &session, const std::string &keys)
|
|
{
|
|
for (const char ch : keys)
|
|
{
|
|
const bool is_upper = ch >= 'A' && ch <= 'Z';
|
|
const char upper = is_upper ? ch : static_cast<char>(ch - ('a' - 'A'));
|
|
session.handle_key(static_cast<UINT>(upper), 0, static_cast<WCHAR>(ch));
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE(EngineShuangpinSessionContinuesCompositionWithoutHelpcode)
|
|
{
|
|
EngineInputSession session(SchemeType::Shuangpin);
|
|
InputLetters(session, "xitele");
|
|
|
|
const auto transition = session.advance_composition_after_selection("xi", "西");
|
|
REQUIRE(transition.continues_composition);
|
|
REQUIRE_EQ(session.get_pinyin_sequence(), std::string("tele"));
|
|
}
|
|
|
|
TEST_CASE(EngineShuangpinSessionContinuesCompositionWithSingleHelpcode)
|
|
{
|
|
EngineInputSession session(SchemeType::Shuangpin);
|
|
InputLetters(session, "xitelea");
|
|
|
|
const auto transition = session.advance_composition_after_selection("xi", "西");
|
|
REQUIRE(transition.continues_composition);
|
|
REQUIRE_EQ(session.get_pinyin_sequence(), std::string("tele"));
|
|
}
|
|
|
|
TEST_CASE(EngineShuangpinSessionContinuesCompositionWithDoubleHelpcode)
|
|
{
|
|
EngineInputSession session(SchemeType::Shuangpin);
|
|
InputLetters(session, "xiteleaA");
|
|
|
|
const auto transition = session.advance_composition_after_selection("xi", "西");
|
|
REQUIRE(transition.continues_composition);
|
|
REQUIRE_EQ(session.get_pinyin_sequence(), std::string("tele"));
|
|
}
|
|
|
|
TEST_CASE(EngineShuangpinSessionCloudQueryMatchesLegacyTiming)
|
|
{
|
|
EngineInputSession session(SchemeType::Shuangpin);
|
|
|
|
InputLetters(session, "xi");
|
|
auto state = session.get_cloud_query_state();
|
|
REQUIRE(state.should_query);
|
|
|
|
session.reset_state();
|
|
InputLetters(session, "xia");
|
|
state = session.get_cloud_query_state();
|
|
REQUIRE(!state.should_query);
|
|
|
|
session.reset_state();
|
|
InputLetters(session, "xiA");
|
|
state = session.get_cloud_query_state();
|
|
REQUIRE(!state.should_query);
|
|
REQUIRE_EQ(state.cache_key, std::string("xi"));
|
|
|
|
session.reset_state();
|
|
InputLetters(session, "xI");
|
|
state = session.get_cloud_query_state();
|
|
REQUIRE(!state.should_query);
|
|
}
|
|
|
|
TEST_CASE(EngineShuangpinSessionCloudQueryDoesNotTriggerWhenHelpcodesApply)
|
|
{
|
|
EngineInputSession session(SchemeType::Shuangpin);
|
|
|
|
InputLetters(session, "xitelea");
|
|
auto state = session.get_cloud_query_state();
|
|
REQUIRE(!state.should_query);
|
|
REQUIRE_EQ(state.cache_key, std::string("xitele"));
|
|
|
|
session.reset_state();
|
|
InputLetters(session, "xiteleaA");
|
|
state = session.get_cloud_query_state();
|
|
REQUIRE(!state.should_query);
|
|
REQUIRE_EQ(state.cache_key, std::string("xitele"));
|
|
}
|
|
|
|
TEST_CASE(EngineShuangpinSessionCloudCommitUsesRawShuangpinSequence)
|
|
{
|
|
EngineInputSession session(SchemeType::Shuangpin);
|
|
|
|
InputLetters(session, "vh");
|
|
const auto state = session.get_cloud_query_state();
|
|
|
|
REQUIRE(state.should_query);
|
|
REQUIRE_EQ(state.query_text, std::string("zhang"));
|
|
REQUIRE_EQ(state.cache_key, std::string("vh"));
|
|
REQUIRE_EQ(state.committed_pinyin, std::string("vh"));
|
|
}
|
|
|
|
TEST_CASE(EngineQuanpinSessionCloudQueryDoesNotTriggerWhenHelpcodesApply)
|
|
{
|
|
EngineInputSession session(SchemeType::Quanpin);
|
|
|
|
InputLetters(session, "xiteleA");
|
|
auto state = session.get_cloud_query_state();
|
|
REQUIRE(!state.should_query);
|
|
REQUIRE_EQ(state.cache_key, std::string("xitele"));
|
|
|
|
session.reset_state();
|
|
InputLetters(session, "xiteleAA");
|
|
state = session.get_cloud_query_state();
|
|
REQUIRE(!state.should_query);
|
|
REQUIRE_EQ(state.cache_key, std::string("xitele"));
|
|
|
|
session.reset_state();
|
|
InputLetters(session, "xitelR");
|
|
state = session.get_cloud_query_state();
|
|
REQUIRE(state.should_query);
|
|
}
|
|
|
|
TEST_CASE(EngineQuanpinSessionContinuesCompositionForCreatingWord)
|
|
{
|
|
EngineInputSession session(SchemeType::Quanpin);
|
|
InputLetters(session, "xitele");
|
|
|
|
const auto transition = session.advance_composition_after_selection("xi", "西");
|
|
REQUIRE(transition.continues_composition);
|
|
REQUIRE_EQ(session.get_pinyin_sequence(), std::string("tele"));
|
|
REQUIRE_EQ(session.get_pinyin_segmentation_with_cases(), std::string("te'le"));
|
|
}
|
|
|
|
TEST_CASE(EngineQuanpinSessionCompletesCreatingWordProgress)
|
|
{
|
|
EngineInputSession session(SchemeType::Quanpin);
|
|
InputLetters(session, "xitele");
|
|
|
|
const auto first_transition = session.advance_composition_after_selection("xi", "西");
|
|
const auto first_progress = session.update_creating_word_progress("", "", "西", first_transition);
|
|
REQUIRE(!first_progress.completed);
|
|
REQUIRE_EQ(first_progress.pinyin, std::string("xitele"));
|
|
REQUIRE_EQ(first_progress.word, std::string("西"));
|
|
REQUIRE_EQ(first_progress.preedit, std::string("西te'le"));
|
|
|
|
const auto second_transition = session.advance_composition_after_selection("te'le", "特乐");
|
|
REQUIRE(!second_transition.continues_composition);
|
|
const auto second_progress =
|
|
session.update_creating_word_progress(first_progress.pinyin, first_progress.word, "特乐", second_transition);
|
|
REQUIRE(second_progress.completed);
|
|
REQUIRE_EQ(second_progress.pinyin, std::string("xitele"));
|
|
REQUIRE_EQ(second_progress.word, std::string("西特乐"));
|
|
}
|
|
|
|
TEST_CASE(EngineQuanpinSessionContinuesCompositionAfterMultiSyllableSelection)
|
|
{
|
|
EngineInputSession session(SchemeType::Quanpin);
|
|
InputLetters(session, "zhengxianghuafen");
|
|
|
|
const auto transition = session.advance_composition_after_selection("zheng'xiang", "正向");
|
|
REQUIRE(transition.continues_composition);
|
|
REQUIRE_EQ(session.get_pinyin_sequence(), std::string("huafen"));
|
|
REQUIRE_EQ(session.get_pinyin_segmentation_with_cases(), std::string("hua'fen"));
|
|
|
|
const auto progress = session.update_creating_word_progress("", "", "正向", transition);
|
|
REQUIRE_EQ(progress.pinyin, std::string("zhengxianghuafen"));
|
|
REQUIRE_EQ(progress.word, std::string("正向"));
|
|
REQUIRE_EQ(progress.preedit, std::string("正向hua'fen"));
|
|
}
|
|
|
|
TEST_CASE(EngineQuanpinSessionContinuesCompositionWithoutRetainingHelpcodes)
|
|
{
|
|
EngineInputSession session(SchemeType::Quanpin);
|
|
InputLetters(session, "nishuoneNV");
|
|
|
|
const auto transition = session.advance_composition_after_selection("ni'shuo", "你说");
|
|
REQUIRE(transition.continues_composition);
|
|
REQUIRE_EQ(session.get_pinyin_sequence(), std::string("ne"));
|
|
REQUIRE_EQ(session.get_pinyin_sequence_with_cases(), std::string("ne"));
|
|
REQUIRE_EQ(session.get_pinyin_segmentation_with_cases(), std::string("ne"));
|
|
|
|
const auto progress = session.update_creating_word_progress("", "", "你说", transition);
|
|
REQUIRE_EQ(progress.pinyin, std::string("nishuone"));
|
|
REQUIRE_EQ(progress.word, std::string("你说"));
|
|
REQUIRE_EQ(progress.preedit, std::string("你说ne"));
|
|
}
|
|
|
|
TEST_CASE(EngineShuangpinSessionDynamicCloudCandidateParticipatesInHelpcodesQuery)
|
|
{
|
|
EngineInputSession session(SchemeType::Shuangpin);
|
|
InputLetters(session, "xitele");
|
|
|
|
const auto state = session.get_cloud_query_state();
|
|
REQUIRE(state.should_query);
|
|
|
|
session.cache_dynamic_candidate(state.cache_key, "云词");
|
|
InputLetters(session, "a");
|
|
|
|
const auto &candidates = session.get_candidates();
|
|
const auto found = std::find_if(candidates.begin(), candidates.end(), [](const IInputSession::WordItem &item) {
|
|
return item.word == "云词";
|
|
});
|
|
REQUIRE(found != candidates.end());
|
|
REQUIRE(found->source == CandidateSource::CloudSuggestion);
|
|
}
|
|
|
|
TEST_CASE(EngineQuanpinSessionDynamicCloudCandidateParticipatesInHelpcodesQuery)
|
|
{
|
|
EngineInputSession session(SchemeType::Quanpin);
|
|
InputLetters(session, "xitele");
|
|
|
|
const auto state = session.get_cloud_query_state();
|
|
REQUIRE(state.should_query);
|
|
|
|
session.cache_dynamic_candidate(state.cache_key, "云词");
|
|
InputLetters(session, "A");
|
|
|
|
const auto &candidates = session.get_candidates();
|
|
const auto found = std::find_if(candidates.begin(), candidates.end(), [](const IInputSession::WordItem &item) {
|
|
return item.word == "云词";
|
|
});
|
|
REQUIRE(found != candidates.end());
|
|
REQUIRE(found->source == CandidateSource::CloudSuggestion);
|
|
}
|
|
|
|
TEST_CASE(EngineShuangpinSessionUsesZiranmaProfileEndToEnd)
|
|
{
|
|
EngineInputSession session(SchemeType::Shuangpin, GetZiranmaShuangpinProfile());
|
|
|
|
InputLetters(session, "xd");
|
|
const auto state = session.get_cloud_query_state();
|
|
|
|
REQUIRE(state.should_query);
|
|
REQUIRE_EQ(state.query_text, std::string("xiang"));
|
|
REQUIRE_EQ(session.get_quanpin(), std::string("xiang"));
|
|
}
|
|
|
|
TEST_CASE(LegacyShuangpinDictionaryUsesZiranmaProfile)
|
|
{
|
|
ShuangpinDictionary dictionary(GetZiranmaShuangpinProfile());
|
|
dictionary.handleVkCode('X', 0, L'x');
|
|
dictionary.handleVkCode('D', 0, L'd');
|
|
|
|
REQUIRE_EQ(dictionary.get_quanpin(), std::string("xiang"));
|
|
}
|