Skip to content

test: adapt unit tests for Qt5/Qt6 dual compatibility#205

Merged
pengfeixx merged 1 commit into
linuxdeepin:masterfrom
pengfeixx:feat/add-unit-tests
Jun 2, 2026
Merged

test: adapt unit tests for Qt5/Qt6 dual compatibility#205
pengfeixx merged 1 commit into
linuxdeepin:masterfrom
pengfeixx:feat/add-unit-tests

Conversation

@pengfeixx

Copy link
Copy Markdown
Contributor

Add qteventcompat.h with QT_COMPAT_MOUSE_EVENT and QT_COMPAT_WHEEL_EVENT macros to handle QMouseEvent and QWheelEvent constructor signature changes between Qt5/Qt6.

Update CMakeLists.txt to auto-detect Qt version (5 or 6), upgrade C++ standard to C++17, use modern cmake target-based linking, and remove deprecated qt5_use_modules.

添加qteventcompat.h兼容头文件,处理Qt5/Qt6鼠标和滚轮
事件构造函数签名差异;更新CMake构建系统自动检测Qt版本,
升级C++标准至C++17,使用现代CMake链接方式。

Log: 单元测试适配Qt5/Qt6双版本兼容
Influence: 测试代码可同时兼容Qt5和Qt6构建环境,无需
手动修改事件构造代码即可在不同Qt版本上编译运行。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @pengfeixx, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

Add qteventcompat.h with QT_COMPAT_MOUSE_EVENT and
QT_COMPAT_WHEEL_EVENT macros to handle QMouseEvent and
QWheelEvent constructor signature changes between Qt5/Qt6.

Update CMakeLists.txt to auto-detect Qt version (5 or 6),
upgrade C++ standard to C++17, use modern cmake target-based
linking, and remove deprecated qt5_use_modules.

添加qteventcompat.h兼容头文件,处理Qt5/Qt6鼠标和滚轮
事件构造函数签名差异;更新CMake构建系统自动检测Qt版本,
升级C++标准至C++17,使用现代CMake链接方式。

Log: 单元测试适配Qt5/Qt6双版本兼容
Influence: 测试代码可同时兼容Qt5和Qt6构建环境,无需
手动修改事件构造代码即可在不同Qt版本上编译运行。
@pengfeixx pengfeixx force-pushed the feat/add-unit-tests branch from c8dacf2 to ed61fea Compare June 2, 2026 08:46
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

你好!我是CodeGeeX。我已经仔细审查了你提供的 Git Diff。本次修改的主要目的是将测试工程从 Qt5 升级兼容到 Qt6,同时调整了 C++ 标准、CMake 最低版本,并引入了自定义宏来解决 Qt5/Qt6 事件构造函数的兼容性问题。

总体来说,这是一次结构清晰、目标明确的重构。但在语法逻辑、代码质量和安全性方面,我发现了几个需要特别注意和改进的地方,尤其是 CMake 中的严重拼写错误和 C++ 宏的潜在风险。

以下是详细的审查意见:

一、 语法与逻辑

1. CMake 严重拼写错误导致链接标志失效
tests/CMakeLists.txt 的修改中,存在一个会导致编译或链接失败的严重问题:

-    set(CMAKE_L_FLAGS "-g -O1 -fprofile-arcs -ftest-coverage")
+    set(CMAKE_L_FLAGS "-fsanitize=undefined,address,leak -fno-omit-frame-pointer -g -O1 -fprofile-arcs -ftest-coverage")

问题CMAKE_L_FLAGS 中的 是全角字符(Unicode FF2C),而不是半角的英文字母 L。CMake 无法识别该变量,这会导致链接器标志丢失。虽然原代码就存在这个问题,但既然在重构,应当一并修复。
改进建议:将其修正为 CMAKE_C_FLAGSCMAKE_CXX_FLAGS,或者如果是针对链接器的,应使用 CMAKE_EXE_LINKER_FLAGS。根据上下文,这里应该是想设置 C 语言和 C++ 的编译器标志,建议修改为:

set(CMAKE_C_FLAGS "-fsanitize=undefined,address,leak -fno-omit-frame-pointer -g -O1 -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_FLAGS "-fsanitize=undefined,address,leak -fno-omit-frame-pointer -g -O1 -fprofile-arcs -ftest-coverage")

2. CMake 中 DTK 版本降级回退逻辑缺陷

    if(Qt6_FOUND)
        set(QT_VERSION_MAJOR 6)
        set(DTK_VERSION_MAJOR 6)
    else()
        find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Test)
        set(QT_VERSION_MAJOR 5)
        set(DTK_VERSION_MAJOR "")
    endif()

问题:当找不到 Qt6 时,DTK_VERSION_MAJOR 被设置为空字符串 ""。随后在 pkg_check_modules 中使用了 dtk${DTK_VERSION_MAJOR}widget,这会展开为 dtkwidget,这在 Qt5 环境下是正确的。但是,如果未来存在 Qt5 环境下的 DTK5,或者主工程对 DTK 有明确的版本要求,这种硬编码空字符串的做法不够健壮。
改进建议:建议显式指定 Qt5 对应的 DTK 版本号(通常为 5),保持变量语义的一致性:

    else()
        find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Test)
        set(QT_VERSION_MAJOR 5)
        set(DTK_VERSION_MAJOR 5) # 明确指定版本
    endif()

3. CMake 中 Qt5 查找组件缺失

    else()
        find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Test)

问题:在下方定义 QtModule 时,Qt5 包含了 DBus PrintSupport Svg Concurrent,但在 if(NOT DEFINED QT_VERSION_MAJOR) 的 else 分支提前查找 Qt5 时,只写了 Core Widgets Gui Test。虽然后续 find_package(Qt5 REQUIRED COMPONENTS ${QtModule}) 会再次查找,但这会导致 CMake 执行冗余的查找操作,且逻辑不够严密。
改进建议:直接移除提前的 find_package(Qt5 REQUIRED ...),让后面的统一 find_package 逻辑去处理;或者在此处补全所有需要的 Components。

二、 代码质量

1. 宏 QT_COMPAT_MOUSE_EVENT / QT_COMPAT_WHEEL_EVENT 的设计风险
qteventcompat.h 中,使用了宏来“原地构造”局部变量:

#define QT_COMPAT_MOUSE_EVENT(name, type, pos, button, buttons, modifiers) \
    QMouseEvent name((type), (pos), (pos), (button), (buttons), (modifiers))

问题:使用宏声明局部变量是一种反模式,它破坏了作用域规则,容易引发变量名冲突,且在调试时宏展开可能会导致困惑。
改进建议:强烈建议将宏改为 内联函数。这不仅类型安全,而且符合 C++17 的最佳实践。由于 Qt6 的 QMouseEvent 构造函数需要 globalPos,可以提供两个重载(支持 QPointQPointF):

// 替代宏的 inline 函数方案
namespace QtEventCompat {

inline QMouseEvent createMouseEvent(QEvent::Type type, const QPointF &pos, 
                                    Qt::MouseButton button, Qt::MouseButtons buttons, 
                                    Qt::KeyboardModifiers modifiers) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    return QMouseEvent(type, pos, pos, button, buttons, modifiers);
#else
    return QMouseEvent(type, pos, button, buttons, modifiers);
#endif
}

inline QWheelEvent createWheelEvent(const QPointF &pos, int delta, 
                                    Qt::MouseButton button, Qt::KeyboardModifiers modifiers) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    return QWheelEvent(pos, pos, QPoint(), QPoint(0, delta), 
                       Qt::MouseButtons(button), modifiers, Qt::NoScrollPhase, false);
#else
    return QWheelEvent(pos, delta, button, modifiers);
#endif
}

} // namespace QtEventCompat

调用方式从:
QT_COMPAT_MOUSE_EVENT(mouseEvent, ...)
改为:
QMouseEvent mouseEvent = QtEventCompat::createMouseEvent(...)

2. 冗余的注释清理

-    #set(CMAKE_CXX_FLAGS "-g -O1 -fprofile-arcs -ftest-coverage")
     set(CMAKE_CXX_FLAGS "-g -O1 -fprofile-arcs -ftest-coverage")
-    #set(CMAKE_C_FLAGS "-g -O1 -fprofile-arcs -ftest-coverage")
-    set(CMAKE_L_FLAGS "-g -O1 -fprofile-arcs -ftest-coverage")

改进建议:删除被注释掉的旧代码,保持 CMakeLists.txt 的整洁。既然已经使用了 Git,历史记录由 Git 保管,无需在代码中保留注释掉的废代码。

三、 代码性能

本次修改对运行时性能没有明显的负面影响。但有两点可以微调:

  1. foreach(module IN LISTS QtModule) 循环调用 target_link_libraries:这在 CMake 中性能影响微乎其微,但更 CMake 化的写法是直接展开:target_link_libraries(${PROJECT_NAME} Qt${QT_VERSION_MAJOR}::${module}) 可以通过列表拼接一次性链接,不过目前的写法可读性更好,可以保留。
  2. 如果采用了上述的 inline 函数替代宏,由于编译器的 RVO(返回值优化)和内联展开,QMouseEventQWheelEvent 的构造将没有任何额外的拷贝开销,性能与宏完全一致。

四、 代码安全

1. C++ 标准库内部破坏风险(已修复,值得表扬)
test_function.cpptest_qtestmain.cpp 中,你添加了:

// Pre-include standard headers before #define private public to avoid
// breaking C++ standard library internals (e.g. std::basic_stringbuf).
#include <sstream>

#define protected public
#define private public

评价:这是一个非常棒且关键的修复!在 C++ 中 #define private public 会导致包含该宏之后引入的标准库头文件内部的类访问控制被破坏,引发难以排查的编译错误或 ODR(单一定义规则)违背。将 <sstream> 等标准库前置包含是正确且安全的做法。

2. #define private public 的原生风险
虽然你修复了标准库的问题,但 #define private public 本身依然是一种极其危险的 Hack 行为,它破坏了封装性,且在 C++17 的严格别名和内存模型下可能导致未定义行为。
建议:如果仅仅是为了在测试中访问私有成员,建议使用更现代、安全的技术:

  • 对于 Qt 的私有成员,使用 Qt 官方提供的 QT_D_FLAGS / 暴露的内部头文件(如 #include <private/xxx_p.h>)。
  • 对于 C++ 类的私有成员,考虑使用 C++17 的结构化绑定技巧(Pointer-to-Member Hack)来合法获取访问句柄,而不是粗暴地重定义关键字。

3. 版权年份的修改

-// SPDX-FileCopyrightText: 2020 - 2022 UnionTech Software Technology Co., Ltd.
+// SPDX-FileCopyrightText: 2020-2026 UnionTech Software Technology Co., Ltd.

问题:将版权年份改为 2026(未来年份)。通常开源协议和版权声明中的年份应该是作品创建或发布的真实年份,写未来年份在法律上并不被推荐,也无实际保护意义。
建议:如果是今年修改的,建议改为 2020-2023(或当前实际年份)。

总结与核心修改代码示例

请务必修复 CMake 中的全角字符 问题。关于事件兼容层,我强烈建议你使用 inline 函数替代宏,以下是改进后的 qteventcompat.h 代码:

// SPDX-FileCopyrightText: 2020-2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef QTEVENTCOMPAT_H
#define QTEVENTCOMPAT_H

#include <QtGlobal>
#include <QEvent>
#include <QPointF>
#include <QPoint>
#include <Qt>
#include <QWheelEvent>
#include <QMouseEvent>

namespace QtEventCompat {

inline QMouseEvent createMouseEvent(QEvent::Type type, const QPointF &pos, 
                                    Qt::MouseButton button, Qt::MouseButtons buttons, 
                                    Qt::KeyboardModifiers modifiers) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    return QMouseEvent(type, pos, pos, button, buttons, modifiers);
#else
    return QMouseEvent(type, pos, button, buttons, modifiers);
#endif
}

// 针对 QPoint 的重载,方便原有代码直接传入 QPoint
inline QMouseEvent createMouseEvent(QEvent::Type type, const QPoint &pos, 
                                    Qt::MouseButton button, Qt::MouseButtons buttons, 
                                    Qt::KeyboardModifiers modifiers) {
    return createMouseEvent(type, QPointF(pos), button, buttons, modifiers);
}

inline QWheelEvent createWheelEvent(const QPointF &pos, int delta, 
                                    Qt::MouseButton button, Qt::KeyboardModifiers modifiers) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    return QWheelEvent(pos, pos, QPoint(), QPoint(0, delta), 
                       Qt::MouseButtons(button), modifiers, Qt::NoScrollPhase, false);
#else
    return QWheelEvent(pos, delta, button, modifiers);
#endif
}

} // namespace QtEventCompat

#endif // QTEVENTCOMPAT_H

调用方式修改示例:

// 旧方式:
// QT_COMPAT_MOUSE_EVENT(mousePressEvent, QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);

// 新方式:
QMouseEvent mousePressEvent = QtEventCompat::createMouseEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);

希望这些审查意见对你有所帮助!如果有任何疑问,欢迎继续讨论。

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: lzwind, pengfeixx

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@pengfeixx

Copy link
Copy Markdown
Contributor Author

/merge

@pengfeixx pengfeixx merged commit f72633d into linuxdeepin:master Jun 2, 2026
16 checks passed
@pengfeixx pengfeixx deleted the feat/add-unit-tests branch June 2, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants