/** * @file CheckRunner.hpp * @brief 离屏检查的注册表与统一断言/输出接口。 * * 每个检查都是一个签名为 `int (const CheckOptions&)` 的函数, * 通过 `Expect()` 记录断言;返回值只用于"该检查自己额外发现的失败数"(通常直接返回全局失败数)。 */ #ifndef __CHECKRUNNER_HPP__ #define __CHECKRUNNER_HPP__ #include #include #include "OffscreenSupport.hpp" namespace jdi { namespace tools { /** @brief 一次检查运行的参数(来自命令行)。 */ struct CheckOptions { std::string dataPath; /**< 数据文件路径(ASCII 或本地代码页)。 */ std::string outDir; /**< 输出目录(默认 `../Temp/tools`)。 */ std::string mode; /**< `verify`(默认)/ `record` / `compare`。 */ int frames = 8; /**< 连续帧数量(仅 `frames` 检查使用)。 */ bool savePng = true; /**< 是否把抓到的帧落盘(默认开,便于事后分析)。 */ }; /** @brief 一个可运行的检查。 */ struct CheckDescriptor { const char* name = ""; /**< 检查名(命令行 `-run ` 使用)。 */ const char* summary = ""; /**< 一句话说明(ASCII,`-list` 打印)。 */ /** 检查实现:`session` 已 `Start()` 并加载好数据文件;返回该检查的失败断言数。 */ int (*run)(Session& session, const CheckOptions& options) = nullptr; }; /** @brief 全部已注册检查(顺序即执行顺序)。 */ const std::vector& AvailableChecks(); /** @brief 按名字查检查;找不到返回 nullptr。 */ const CheckDescriptor* FindCheck(const std::string& name); /** @brief 统一输出(同时写标准输出与报告文件,由 `Main.cpp` 提供实现)。 */ void EmitLine(const char* format, ...); /** @brief 断言总数。 */ int& CheckTotal(); /** @brief 失败断言数。 */ int& CheckFailed(); /** @brief 记录一条断言(失败会打印 `[FAIL]` 并累加失败数)。 */ void Expect(const bool ok, const std::string& what); /** @brief 记录一条"整数相等"断言。 */ void ExpectEqual(const long long actual, const long long expected, const std::string& what); /** @brief 记录一条数值近似断言。 */ void ExpectNear(const double actual, const double expected, const double tolerance, const std::string& what); /** @brief 把 `gd::RectF` 转成整像素矩形(向外取整,保证覆盖)。 */ inline PixelRect ToPixelRect(const gd::RectF& rect) { PixelRect result; result.x = static_cast(std::floor(rect.X)); result.y = static_cast(std::floor(rect.Y)); result.width = static_cast(std::ceil(rect.X + rect.Width)) - result.x; result.height = static_cast(std::ceil(rect.Y + rect.Height)) - result.y; return result; } /** @brief 读取一个文本文件(失败返回空串)。 */ std::string ReadTextFile(const std::string& path); /** @brief 写一个文本文件(自动建目录)。 */ bool WriteTextFile(const std::string& path, const std::string& content); } // namespace tools } // namespace jdi #endif // __CHECKRUNNER_HPP__