完成 StellarX 核心重构、缺陷修复与测试收口
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
# 功能变更 ID: Feature-20260915-0001
|
||||
|
||||
> 适用场景:记录小到中等规模的功能、接口、行为、默认值或配置变化。
|
||||
> 不适用场景:新增核心模块、重大模块重构、架构级设计,请使用“新增功能模块”模板。
|
||||
|
||||
## 基本信息
|
||||
|
||||
- ID: Feature-20260915-0001
|
||||
- 标题: 全量缺陷修复与 API 调整
|
||||
- 状态:非 UI 与人工 UI 已验证,待提交
|
||||
- 类型:修改 / 删除 / 重命名
|
||||
- 级别:L3 重大
|
||||
- 模块: Control / Window / Canvas / Dialog / TabControl / Table / SxLogger / Test
|
||||
- 版本 / 分支: 当前工作区
|
||||
- 环境: Windows + Visual Studio 2022 + MSVC v143 + EasyX
|
||||
- 负责人: Codex 协作修改
|
||||
|
||||
## 变更背景
|
||||
|
||||
- 背景:
|
||||
- 代码审查发现控件回调期间所有权变化、空 TabControl、快照尺寸、几何残影、Dialog 关闭、Table coverage、日志滚动、MBCS 文本、Tooltip 和事件循环等问题。
|
||||
- 原有测试主要依赖 `KEY` 场景和手工观察,缺少不创建窗口的逻辑验证、ASan 验证以及可重复的外部 UI 断言。
|
||||
- 目标:
|
||||
- 修复高、中、低严重度缺陷,消除明确的 UAF、越界、残影、数据截断和所有权丢失风险。
|
||||
- 通过稳定句柄和延迟变更事务收口控件容器生命周期。
|
||||
- 建立可重复的逻辑、像素不变量和真实 UI 回归验证。
|
||||
- 明确破坏性 API 的迁移方式。
|
||||
- 不做什么:[可选]
|
||||
- 不迁移 Unicode,继续使用 MBCS/GBK 风格字符处理。
|
||||
- 不把 GUI 改造成多线程模型。
|
||||
- 不在本次将 `StellarX.Core` 改为 DLL,也不处理安装包制作。
|
||||
|
||||
## 变更内容
|
||||
|
||||
- 变更摘要:
|
||||
- 修复 14 项高、中、低严重度问题。
|
||||
- 将核心框架独立为 `StellarX.Core` 静态库,并让应用、单元测试和 UI Fixture 共用该实现。
|
||||
- 新增 Native Unit Test、ASan、EasyX UI Fixture 和 PowerShell 自动化入口。
|
||||
- 新增项:[可选]
|
||||
- `StellarX::ControlHandle` 及受控控件所有权接口。
|
||||
- `MutationTransaction` 延迟变更机制。
|
||||
- `SxEventLoopInternal.h` 和 `SxTextInternal.h` 内部测试辅助。
|
||||
- `StellarX.Tests`、`StellarX.UiFixture` 和 `scripts/test.ps1`。
|
||||
- 修改项:[可选]
|
||||
- Button/Label/TextBox/Canvas/Table/TabControl 的 geometry、snapshot、coverage 和绘制提交逻辑。
|
||||
- Dialog 关闭和 overlay 收口逻辑。
|
||||
- SxLogger sink 配置和滚动逻辑。
|
||||
- Tooltip tick、MBCS 密码掩码和事件循环批处理。
|
||||
- 删除 / 废弃项:[可选]
|
||||
- 删除 `Window::getControls()` 和 `Canvas::getControls()` 的 mutable 容器入口。
|
||||
- 删除 `Canvas::clearAllControls()`。
|
||||
- `ControlText::lpszFace` 废弃并替换为 `faceName`。
|
||||
- 旧的按文本/旧参数添加 Tab 控件方式不再作为首选接口。
|
||||
- 受影响的文件 / 类 / 函数:
|
||||
- 工程:`StellarX.Core.vcxproj`、`imGui-easyX.vcxproj`、`imGui-easyX.sln`。
|
||||
- 所有权和事务:`CoreTypes.h`、`Control.h/.cpp`、`Window.h/.cpp`、`Canvas.h/.cpp`。
|
||||
- 控件和重绘:`Button.h/.cpp`、`Label.h/.cpp`、`TextBox.cpp`、`Table.cpp`、`Dialog.cpp`、`TabControl.h/.cpp`。
|
||||
- 日志:`SxLog.h/.cpp`。
|
||||
- 示例入口:`z-testDome.cpp`。
|
||||
- 测试:`tests/StellarXTests.cpp`、`tests/UiFixture.cpp`、`scripts/test.ps1`、`scripts/run-ui-tests.ps1`。
|
||||
- 对外 API / 属性变化:[可选]
|
||||
- `ControlHandle addControl(std::unique_ptr<Control>)`
|
||||
- `bool removeControl(ControlHandle)`、`void clearControls()`
|
||||
- `Control* findControl(ControlHandle)`、`std::vector<ControlHandle> getControlHandles() const`
|
||||
- `ControlText::faceName` 替代 `lpszFace`。
|
||||
- `bool SxLogger::setConfig(const SxLogConfig&)`。
|
||||
- `size_t TabControl::addTab(...)`、`bool setActiveIndex(int)`、`tryAddToPage(...)`。
|
||||
|
||||
## 行为对照
|
||||
|
||||
- 变更前:
|
||||
- 回调中直接删除当前或兄弟控件可能使遍历中的裸指针失效。
|
||||
- 空 TabControl 激活和绘制路径可能访问不存在的页签。
|
||||
- 控件几何变化、Tooltip、Dialog 和 Table 的局部 coverage 可能留下旧像素或污染快照。
|
||||
- 日志滚动失败时可能截断原日志;字体名可能引用悬空内存;密码掩码可能按字节而非逻辑字符生成。
|
||||
- 事件循环每轮只处理一条消息并固定休眠,消息积压时响应和重绘收口不稳定。
|
||||
- 变更后:
|
||||
- 控件增删清空在最外层遍历事务结束后提交,回调期间不会释放正在使用的遍历对象。
|
||||
- 空页签路径安全返回,待激活索引在首个页签加入后应用,非法运行期索引返回 `false`。
|
||||
- 几何 setter 先恢复旧 coverage,再登记旧新区域并集;快照、绘制和 coverage 使用一致的矩形语义。
|
||||
- 日志 sink 候选打开成功后才原子替换,滚动重命名失败时继续 append 原文件。
|
||||
- MBCS 文本按逻辑字符处理,Tooltip 由 tick 链驱动到期和清除。
|
||||
- 兼容性说明:不兼容
|
||||
- 迁移说明:[可选]
|
||||
- 调用方应使用稳定 `ControlHandle`,不再保存可变控件容器引用。
|
||||
- 将 `lpszFace` 改为 `faceName`,将旧 Tab 添加路径迁移到索引 API。
|
||||
- 具体示例见 [`MIGRATION.md`](D:/programming/imGUI-easyX/imGui-easyX/开发记录/MIGRATION.md)。
|
||||
|
||||
## 全量缺陷修复矩阵
|
||||
|
||||
| 严重度 | 问题 | 根因与修复 | 主要验证 |
|
||||
|---|---|---|---|
|
||||
| 高 | 回调删除当前控件导致 UAF | 引入稳定 `ControlHandle` 和 `MutationTransaction`;事件、绘制、按钮回调期间的 Add/Remove/Clear 延迟提交。 | self/sibling/remove/clear/add 回调测试;x64 ASan |
|
||||
| 高 | 空 TabControl 激活索引越界 | 空容器绘制不访问末元素;待激活索引延迟到首个页签加入后应用;非法索引返回 `false`。 | 空容器设置 0/大索引并绘制;随后新增页签 |
|
||||
| 中 | Button 快照尺寸恒不匹配 | 提取统一快照矩形计算,比较、保存和 coverage 使用相同宽高。 | hover/click/redraw/hide 像素不变量 |
|
||||
| 中 | 运行时几何 setter 遗留旧像素 | setter 记录旧 coverage、恢复并释放旧快照,再更新矩形并登记旧新区域并集。 | Button/Label/TextBox/Canvas/Table/Tab 移动、缩放、隐藏 |
|
||||
| 中 | Dialog 清理触发额外全量重绘 | `Close()` 统一登记 overlay 关闭,清理只释放对象和快照,Window 在 sweep 后统一重绘。 | 两层异步 Dialog 关闭上层后下层可见、可交互 |
|
||||
| 中 | Table 宽度、列宽和 coverage 不一致 | 计算最小宽度并夹紧请求值;列宽总和严格等于有效内容宽;按 MBCS 边界省略文本。 | 极窄 Table、多列长文本、分页按钮和 coverage |
|
||||
| 中 | 日志滚动失败截断原日志 | 滚动名加入毫秒和递增序号;检查 rename 错误;失败时重新 append 原文件,不执行 trunc。 | 同毫秒滚动、同名文件、无效路径 |
|
||||
| 中 | ControlText 字体名悬空和地址比较 | 使用拥有型 `std::string faceName`;EasyX/GDI 调用使用 `.c_str()`;比较按字符串内容。 | 临时字符串析构、相同内容不同地址、内容变化测量 |
|
||||
| 中 | `setConfig()` 不同步文件 sink | 锁内构造并打开候选 sink,成功后替换;禁用、路径、append 和 rotate 变化同步重开。 | 启用/禁用、切换文件、无效路径和输出一致性 |
|
||||
| 中 | 同名页签可同时激活 | 通过索引排除当前页签,不按标题排除;允许重复标题但只保留一个激活页。 | 两个同名页签来回切换 |
|
||||
| 低 | Tooltip 静止时不会到期显示 | 增加 Control tick 链,Window 传入单调时钟;到期时置脏并登记重绘;禁用和移出统一 hide。 | 假时钟、静止鼠标、到期显示和移出清除 |
|
||||
| 低 | 密码掩码按字节生成 | 复用 MBCS 字符边界遍历,每个逻辑字符生成一个 `*`,非法尾字节仍保证前进。 | ASCII、GBK 双字节、非法尾字节 |
|
||||
| 低 | 事件循环每轮只处理一条消息并固定 Sleep | 提取批处理器,每轮最多 128 条;活动轮不休眠,空闲轮 `Sleep(1)`;批次尾统一收口 resize/重绘。 | 一次注入 1000 条消息;关闭和 resize 顺序 |
|
||||
| 低 | 按文本添加页控件失败时静默销毁 | `tryAddToPage` 失败原样返还 `unique_ptr`;索引重载为首选,文本重载只匹配首个同名页签。 | 不存在标题、非法索引和同名标题 |
|
||||
|
||||
## 验证与落地
|
||||
|
||||
- 验证方式:
|
||||
- 使用 VS Native Unit Test 对所有权、Tab、文本、Tooltip、事件循环和日志逻辑进行测试。
|
||||
- 使用 Debug x64 ASan 对回调生命周期和核心逻辑进行内存安全验证。
|
||||
- 使用真实 EasyX UI Fixture 和 Win32 `SendInput`、`SetWindowPos` 驱动窗口。
|
||||
- 使用 JSON 状态、关键像素、后备缓冲 PNG 和 Fixture 日志进行断言。
|
||||
- 验证结果:
|
||||
- 2026-09-29 执行 `scripts/test.ps1 -Suite NonUI`,Debug x64、Debug x64 ASan、Release x64、Debug Win32 均为 15/15 通过。
|
||||
- x64 ASan 未报告内存错误;KEY1 至 KEY6 均编译、链接通过。
|
||||
- 2026-09-30 为 `scripts/test.ps1` 补充 UTF-8 BOM 后,使用 Windows PowerShell 5.1 重跑 `NonUI`,结果保持通过。
|
||||
- 本轮按约定未启动自动 UI Fixture;用户于 2026-09-30 按 `TESTING.md` 手工完成 KEY1 至 KEY6,暂未发现明显问题。
|
||||
- 2026-07-22 的 UI 六类场景连续三轮通过记录保留为历史证据;当前快照以 2026-09-30 的人工验收结果为准。
|
||||
- TRX 等诊断产物位于未跟踪的 `TestResults/`。
|
||||
- 关联 BUG / Fix:[可选]
|
||||
- 历史重绘和 Tab 相关记录见 `开发记录/BUG`、`开发记录/Fix` 目录。
|
||||
- 本次新增内容以本记录的严重度矩阵统一收口,避免为同一批次重复创建 14 组 BUG/Fix 文档。
|
||||
- Commit:
|
||||
- 当前工作区未提交
|
||||
- PR:[可选]
|
||||
- 发布版本:[可选]
|
||||
- 备注:[可选]
|
||||
- 当前 `Render` 入口复用 UI Fixture,尚未形成完全独立的进程内 Native Render 测试类别。
|
||||
- GUI 仍限定在主线程,字符集仍为 MBCS。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [`Module-20260915-0001-StellarX核心库与自动化测试基础设施.md`](D:/programming/imGUI-easyX/imGui-easyX/开发记录/模块/Module-20260915-0001-StellarX核心库与自动化测试基础设施.md)
|
||||
- [`MIGRATION.md`](D:/programming/imGUI-easyX/imGui-easyX/开发记录/MIGRATION.md)
|
||||
- [`TESTING.md`](D:/programming/imGUI-easyX/imGui-easyX/开发记录/TESTING.md)
|
||||
Reference in New Issue
Block a user