Files
msime-windows/server/tests
Evan Hu 680fdfa648 fix(skin): 丢弃第三方皮肤 CSS 里的远程引用,不再原样注入候选窗
皮肤是用户往 %LOCALAPPDATA%\metasequoiaime\skins 里丢的文件夹,是彻头彻尾的第三方内容,而它的 CSS 会被内联进候选窗文档。此前 IsRewritableSkinCssUrl() 对含 :// 的 URL 直接返回 false,而 false 分支把原始 url("…") 原封不动写回样式表——也就是说 `background-image: url(https://attacker/beacon.png)` 会在每一次候选窗渲染时向外发一个请求,泄露「此人此刻正在打字」以及 IP。这直接推翻了 PRIVACY.md 的 "Local conversion never contacts the network",而那句话是这个项目最强的信任资产。

问题出在这个判断只有两态:不可重写就等于放行。实际上有三类:

- Embed——皮肤包内的相对路径,读文件内联;
- Keep——本身就是惰性的 data: 负载和文档内 #fragment 引用,照原样保留;
- Drop——任何会让候选窗向皮肤包之外取数据的写法。丢掉 URL 后声明不完整,CSS 会整条丢弃,这正是想要的结果。

Drop 覆盖 http/https/ftp 等带 scheme 的、协议相对的 //host/x(不写 scheme 但照样出网)、路径穿越,以及会逃出皮肤包的绝对路径。

url() 不是唯一入口:`@import "https://…"` 根本不含 url() token,扫描器永远看不到它。补 StripRemoteImports() 做前置处理,只删远程 @import,本地的保留。

skin.preview 来自皮肤自己的 skin.toml,此前直接进 EmbedSkinCssUrl。现在同样过一遍分类,不因为它是通过 manifest 字段到达就被信任。

判断逻辑抽到 server/src/webview2/skin_css_policy.{h,cpp},不依赖任何 Windows API,配 6 个用例覆盖三类判定与两种 @import 写法。本机以 -Wall -Wextra 编译运行全部通过。
2026-09-06 18:05:09 +09:00
..
2026-06-20 22:11:00 +08:00
2025-04-20 17:44:33 +08:00
2025-04-21 18:32:45 +08:00

Tests

This project now includes a lightweight regression test target wired into the main CMake build.

What It Covers

Current tests focus on high-value IME behaviors that are easy to accidentally break during refactors:

  • shuangpin scheme request construction
  • quanpin scheme request construction
  • case-preserving shuangpin segmentation
  • full-helpcode detection
  • engine + shuangpin continuation behavior
  • cloud suggestion trigger timing for shuangpin

The goal is not to fully simulate the whole IME UI pipeline yet. The goal is to protect the core input rules and session behavior.

Build and run

Run these commands from the MSIME-Windows repository root after preparing vcpkg and Boost with python server/scripts/prepare_env.py:

python scripts/product_lock.py fetch-dictionaries --staging-root .
if ($LASTEXITCODE -ne 0) { throw 'Dictionary verification failed' }
$env:LOCALAPPDATA = Join-Path $PWD 'build/test-data/user-local'
$env:METASEQUOIA_IME_DATA_DIR = Join-Path $env:LOCALAPPDATA 'metasequoiaime'
New-Item -ItemType Directory -Force $env:METASEQUOIA_IME_DATA_DIR | Out-Null
Copy-Item MetasequoiaImeDict/out/* $env:METASEQUOIA_IME_DATA_DIR -Force
Copy-Item vendor/MetasequoiaImeEngine/helpcode/helpcodes $env:METASEQUOIA_IME_DATA_DIR -Recurse -Force
Copy-Item server/assets/tables/* $env:METASEQUOIA_IME_DATA_DIR -Force
Copy-Item server/assets/config/config.toml $env:METASEQUOIA_IME_DATA_DIR -Force
.\server\tests\scripts\llaunch.ps1 -Configuration Release

Use a dedicated PowerShell terminal: these environment variables isolate both Windows helpers and the shared Engine from the installed user's data for the rest of that session. The scripts run CTest; they do not launch the interactive Server, install or register the input method. CI additionally runs the native Win32/x64 pipe probe after building the full Server.

Tests belong to the Server CMake project, which provides the Engine, GUI and third-party targets. server/tests/CMakeLists.txt is an add_subdirectory input, not an independent project. The obsolete test presets have been removed; an old locally generated server/tests/CMakePresets.json is no longer used.

Once test data is prepared, the convenience scripts work from any directory:

.\server\tests\scripts\llaunch.ps1 -Configuration Release  # build, then CTest
.\server\tests\scripts\lrun.ps1 -Configuration Release     # CTest only

Omitting -Configuration selects Debug in server/build; Release uses server/build-release. Both compile MetasequoiaImeServerTests and test_webview_contract in the parent build tree. Configuration, compilation, test failures and an empty CTest registry return failure rather than launching a stale executable or reporting success.

The equivalent direct CTest command from the repository root is:

ctest --test-dir server/build-release -C Release --output-on-failure --no-tests=error

Test Layout

  • tests/src/main.cpp
    • tiny custom test runner
  • tests/includes/test_framework.h
    • lightweight assertion helpers
  • tests/src/test_shuangpin_scheme.cpp
    • shuangpin scheme unit tests
  • tests/src/test_quanpin_scheme.cpp
    • quanpin scheme unit tests
  • tests/src/test_shuangpin_query.cpp
    • query/helper function tests
  • tests/src/test_engine_shuangpin_session.cpp
    • session-level behavior tests

When you change input behavior, add a regression test if the change affects:

  • input segmentation
  • space/enter/backspace behavior
  • helpcode handling
  • continuation after candidate selection
  • create-word flow
  • cloud suggestion timing

The best tests in this project are the ones that capture a concrete input example that previously broke.