Files
msime-windows/engine/tests/src/test_segmentation_contract.cpp
T
fanlusky a7779d2b05 refactor(engine): 将 engine 从 submodule 内嵌为仓内一等组件
`vendor/MetasequoiaImeEngine` submodule 改为 `engine/` 目录,导入的是
product-lock.json 原本钉住的提交 c810d201,逐文件核对过 blob,因此这是一次
搬迁而不是引擎升级。引擎自己的嵌套 submodule(googlepinyinime-rev、utfcpp、
miniaudio)按各自 gitlink 一并展开,来源与提交见 engine/UPSTREAM.md。

Windows 专门化裁掉了不属于本产品的部分:whisper.cpp 与本地推理 provider、
macOS 示例宿主、整个 dictionary/ 建库流水线、上游 CI 与 release-please 配置。
词库仍按 product-lock.json 在构建时取发布产物。

引擎不再进 product-lock.json:没有 gitlink 就没有可比对的东西,锁里写一个上游
commit 等于宣称这棵树仍等于上游,而第一个 Windows 专门化改动落地时这句话就假了。
verify-contracts / verify-checkout 随之移除,verify-published 保留。

CI 与工具链:引擎源码并入根 scripts/format.sh(删掉引擎自己的那份,避免两套排除
列表分叉);引擎 voice.yml 里的 silero_vad.onnx 摘要校验移到本仓 lock job;
engine-bump-triage 工作流与其测试删除;gitsubmodule 的 dependabot 频率由 daily
改为 monthly。

README、README.en、AGENTS.md、CONTRIBUTING、docs/product-release.md 及各子目录
文档同步说明新的位置与边界。
2026-09-12 03:40:48 +08:00

71 lines
3.3 KiB
C++

#include "quanpin/quanpin_dictionary.h"
#include <algorithm>
#include <filesystem>
#include <sqlite3.h>
#include <stdexcept>
#include <iostream>
namespace
{
std::filesystem::path CreatePinyinCacheDatabase()
{
const auto path = std::filesystem::temp_directory_path() / "msime-segmentation-contract-test.db";
std::filesystem::remove(path);
sqlite3 *db = nullptr;
if (sqlite3_open(path.string().c_str(), &db) != SQLITE_OK)
{
throw std::runtime_error("Failed to create temporary pinyin database.");
}
const char *sql =
"PRAGMA journal_mode=WAL;"
"CREATE TABLE tbl_1_n(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_1_a(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_1_x(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_2_a(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_2_x(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_3_a(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_3_x(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_4_x(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_5_x(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"CREATE TABLE tbl_6_x(key TEXT,jp TEXT,value TEXT,weight INTEGER);"
"INSERT INTO tbl_3_a VALUES('ao''shi''ke','ask','奥湿克',1);"
"INSERT INTO tbl_1_x VALUES('xian','x','__primary_xian_1__',1000);"
"INSERT INTO tbl_1_x VALUES('xian','x','__primary_xian_2__',900);"
"INSERT INTO tbl_1_x VALUES('xian','x','__primary_xian_3__',800);"
"INSERT INTO tbl_2_x VALUES('xi''an','xa','__alternative_xi_an__',1);"
"INSERT INTO tbl_4_x VALUES('xi''an''xian''xian','xaxx','__three_syllable_alternative__',100);"
"INSERT INTO tbl_5_x VALUES('xi''an''xian''xian''xian','xaxxx','__four_syllable_alternative__',100);"
"INSERT INTO tbl_6_x VALUES('xi''an''xian''xian''xian''xian','xaxxxx','__five_syllable_alternative__',100);";
const int result = sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
sqlite3_close(db);
if (result != SQLITE_OK)
{
std::filesystem::remove(path);
throw std::runtime_error("Failed to initialize temporary pinyin database.");
}
return path;
}
} // namespace
int main()
{
const auto path = CreatePinyinCacheDatabase();
int result = 0;
{
QuanpinDictionary dictionary(path.string());
const auto four = dictionary.query("xianxianxianxian", "xian'xian'xian'xian");
const auto five = dictionary.query("xianxianxianxianxian", "xian'xian'xian'xian'xian");
const auto manual = dictionary.query("xian'xian'xian'xian", "xian'xian'xian'xian");
auto has = [](const auto &candidates, const char *word) {
return std::any_of(candidates.begin(), candidates.end(),
[word](const auto &item) { return item.word == word; });
};
if (!has(four, "__four_syllable_alternative__") || has(five, "__five_syllable_alternative__") ||
has(manual, "__four_syllable_alternative__"))
{
std::cerr << "Four-syllable ambiguity, five-syllable bound or explicit boundary contract failed\n";
result = 1;
}
}
std::filesystem::remove(path);
return result;
}