diff --git a/src/common/utils.cpp b/src/common/utils.cpp index cd770510..8668e40a 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -593,7 +593,9 @@ QStringList Utils::parseNestedQString(QString str) #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) auto spStr = QRegExp(QStringLiteral("\\s+")); #else - auto spStr = QStringLiteral("\\s+"); + // Qt6 下 split 需要传 QRegularExpression;同时显式 SkipEmptyParts, + // 以避免 "bash -c " 末尾空白产生空字符串元素,与 Qt5 行为保持一致。 + auto spStr = QRegularExpression(QStringLiteral("\\s+")); #endif // 如果只有一个引号 @@ -617,16 +619,16 @@ QStringList Utils::parseNestedQString(QString str) } qCDebug(common) << "Splitting string by whitespace"; - paraList.append(str.split(spStr)); + paraList.append(str.split(spStr, SKIP_EMPTY_PARTS)); return paraList; } qCDebug(common) << "Processing quoted string with left index:" << iLeft << "right index:" << iRight; - paraList.append(str.left(iLeft).split(spStr)); + paraList.append(str.left(iLeft).split(spStr, SKIP_EMPTY_PARTS)); paraList.append(str.mid(iLeft + 1, iRight - iLeft - 1)); if (str.size() != iRight + 1) { qCDebug(common) << "Adding remaining part after quote"; - paraList.append(str.right(str.size() - iRight - 1).split(spStr)); + paraList.append(str.right(str.size() - iRight - 1).split(spStr, SKIP_EMPTY_PARTS)); } qCDebug(common) << "Nested string parsing result:" << paraList; diff --git a/tests/src/main/ut_dbusmanager_test.cpp b/tests/src/main/ut_dbusmanager_test.cpp index 86c4171a..13dad18c 100644 --- a/tests/src/main/ut_dbusmanager_test.cpp +++ b/tests/src/main/ut_dbusmanager_test.cpp @@ -5,8 +5,11 @@ #include "ut_dbusmanager_test.h" #include "dbusmanager.h" +#include "settings.h" #include "ut_stub_defines.h" +#include + UT_Dbusmanager_Test::UT_Dbusmanager_Test() { m_pDbusManager = new DBusManager(); @@ -85,5 +88,142 @@ TEST_F(UT_Dbusmanager_Test, listenDesktopSwitched) EXPECT_TRUE(UT_STUB_QDBUS_CONNECT_RESULT); } +// 测试 entry 函数,验证信号 entryArgs 会被发射 +TEST_F(UT_Dbusmanager_Test, entry) +{ + QStringList args = {"deepin-terminal", "-e", "ls"}; + QSignalSpy spy(m_pDbusManager, SIGNAL(entryArgs(QStringList))); + m_pDbusManager->entry(args); + EXPECT_EQ(spy.count(), 1); +} + +// 测试 callKDECurrentDesktop 函数(DBus call 通过 stub 拦截,返回 InvalidMessage,函数返回 -1) +TEST_F(UT_Dbusmanager_Test, callKDECurrentDesktop) +{ + UT_STUB_QDBUS_CALL_CREATE + int result = m_pDbusManager->callKDECurrentDesktop(); + // stub 返回空 QDBusMessage,type() != ReplyMessage,应返回 -1 + EXPECT_EQ(result, -1); + EXPECT_TRUE(UT_STUB_QDBUS_CALL_RESULT); +} + +// 字体大小 getter/setter +TEST_F(UT_Dbusmanager_Test, consoleFontSize) +{ + const int expectSize = 18; + Settings::instance()->setFontSize(expectSize); + EXPECT_EQ(m_pDbusManager->consoleFontSize(), expectSize); +} + +TEST_F(UT_Dbusmanager_Test, setConsoleFontSize) +{ + const int newSize = 22; + m_pDbusManager->setConsoleFontSize(newSize); + EXPECT_EQ(Settings::instance()->fontSize(), newSize); +} + +// 字体 family getter/setter +TEST_F(UT_Dbusmanager_Test, consoleFontFamily) +{ + // 验证 getter 可正常返回(setFontName 依赖 DBus 字体列表,测试环境下走默认值) + const QString family = m_pDbusManager->consoleFontFamily(); + EXPECT_FALSE(family.isNull()); +} + +TEST_F(UT_Dbusmanager_Test, setConsoleFontFamily) +{ + // setFontName 会查询 DBus 字体列表,测试环境下大概率匹配不上,仅验证不崩溃 + m_pDbusManager->setConsoleFontFamily(QStringLiteral("Noto Sans Mono")); + SUCCEED(); +} + +// 透明度 getter/setter(Settings 内部把 int 百分比换算为 0~1 的 qreal) +TEST_F(UT_Dbusmanager_Test, consoleOpacity) +{ + const int expectPercent = 85; + Settings::instance()->setOpacity(expectPercent); + EXPECT_NEAR(m_pDbusManager->consoleOpacity(), expectPercent / 100.0, 0.001); +} + +TEST_F(UT_Dbusmanager_Test, setConsoleOpacity) +{ + const int newOpacity = 60; + m_pDbusManager->setConsoleOpacity(newOpacity); + EXPECT_NEAR(Settings::instance()->opacity(), newOpacity / 100.0, 0.001); +} + +// 光标形状 getter/setter +TEST_F(UT_Dbusmanager_Test, consoleCursorShape) +{ + const int expectShape = 1; + Settings::instance()->setCursorShape(expectShape); + EXPECT_EQ(m_pDbusManager->consoleCursorShape(), expectShape); +} + +TEST_F(UT_Dbusmanager_Test, setConsoleCursorShape) +{ + const int newShape = 2; + m_pDbusManager->setConsoleCursorShape(newShape); + EXPECT_EQ(Settings::instance()->cursorShape(), newShape); +} + +// 光标闪烁 getter/setter +TEST_F(UT_Dbusmanager_Test, consoleCursorBlink) +{ + const bool expectBlink = true; + Settings::instance()->setCursorBlink(expectBlink); + EXPECT_EQ(m_pDbusManager->consoleCursorBlink(), expectBlink); +} + +TEST_F(UT_Dbusmanager_Test, setConsoleCursorBlink) +{ + const bool newBlink = false; + m_pDbusManager->setConsoleCursorBlink(newBlink); + EXPECT_EQ(Settings::instance()->cursorBlink(), newBlink); +} + +// 配色方案 getter/setter +TEST_F(UT_Dbusmanager_Test, consoleColorScheme) +{ + EXPECT_FALSE(m_pDbusManager->consoleColorScheme().isEmpty()); +} + +TEST_F(UT_Dbusmanager_Test, setConsoleColorScheme) +{ + const QString newScheme = QStringLiteral("Dark"); + m_pDbusManager->setConsoleColorScheme(newScheme); + EXPECT_EQ(Settings::instance()->colorScheme(), newScheme); +} + +// shell 路径 getter/setter +TEST_F(UT_Dbusmanager_Test, consoleShell) +{ + EXPECT_FALSE(m_pDbusManager->consoleShell().isEmpty()); +} + +TEST_F(UT_Dbusmanager_Test, setConsoleShell) +{ + // setConsoleShell 会从 /etc/shells 找匹配,匹配不上时不动设置;这里只验证不崩溃 + m_pDbusManager->setConsoleShell(QStringLiteral("/bin/bash")); + SUCCEED(); +} + +// 测试 callSystemSound(依赖 DBus call,验证函数能正常执行) +TEST_F(UT_Dbusmanager_Test, callSystemSound) +{ + UT_STUB_QDBUS_CALL_CREATE + m_pDbusManager->callSystemSound(QStringLiteral("message")); + EXPECT_TRUE(UT_STUB_QDBUS_CALL_RESULT); +} + +// 测试 callAppearanceFont 的重载版本(传入空列表) +TEST_F(UT_Dbusmanager_Test, callAppearanceFontFromList) +{ + UT_STUB_QDBUS_CALL_CREATE + FontDataList result = m_pDbusManager->callAppearanceFont(QStringList(), QStringLiteral("monospacefont")); + EXPECT_TRUE(result.isEmpty()); + EXPECT_TRUE(UT_STUB_QDBUS_CALL_RESULT); +} + #endif diff --git a/tests/src/main/ut_service_test.cpp b/tests/src/main/ut_service_test.cpp index 5669a7d4..00341a4c 100644 --- a/tests/src/main/ut_service_test.cpp +++ b/tests/src/main/ut_service_test.cpp @@ -394,10 +394,15 @@ TEST_F(UT_Service_Test, hideSettingDialog) if(nullptr == m_service->m_settingDialog) m_service->m_settingDialog = new DSettingsDialog(); - UT_STUB_QWIDGET_SETVISIBLE_CREATE; + // Qt6 中 QWidget::hide() 通过虚表 jmp 到 setVisible(false), + // stub-ext 改 setVisible 入口字节码对虚表跳转无效,因此直接 stub hide() + Stub stub; + stub.set((void (QWidget::*)())ADDR(QWidget, hide), ut_QWidget_update); + ut_QWidget_update_hasRuned = false; + m_service->hideSettingDialog(); - //会调用setvisible函数 - EXPECT_TRUE(UT_STUB_QWIDGET_SETVISIBLE_RESULT); + // hideSettingDialog 内部会调用 hide() + EXPECT_TRUE(ut_QWidget_update_hasRuned); } #endif diff --git a/tests/src/remotemanage/ut_remotemanagementpanel_test.cpp b/tests/src/remotemanage/ut_remotemanagementpanel_test.cpp index b42c6e24..708e2d0f 100644 --- a/tests/src/remotemanage/ut_remotemanagementpanel_test.cpp +++ b/tests/src/remotemanage/ut_remotemanagementpanel_test.cpp @@ -239,9 +239,11 @@ TEST_F(UT_RemoteManagementPanel_Test, refreshSearchState) panel.refreshPanel(); // 两个数据,搜索框显示 panel.refreshSearchState(); - // list中数据的数量 + // list中数据的数量: + // fillManagePanel 末尾会追加 "Groups"(GroupLabel) 和 "Servers"(ItemLabel) 两个标题项, + // 它们也计入 m_listWidget->count(),所以总数 = 服务器配置数 + 标题数。 int count = panel.m_listWidget->count(); - EXPECT_EQ(count, 2); + EXPECT_EQ(count, 2 /* server items */ + 2 /* GroupLabel + ItemLabel */); ServerConfigManager::instance()->m_serverConfigs.clear(); } @@ -358,6 +360,10 @@ TEST_F(UT_RemoteManagementPanel_Test, lambda) RemoteManagementPanel remotePanel; remotePanel.show(); remotePanel.m_isShow = true; + // 清理 ServerConfigManager 单例中 SetUp/preparedData 残留的配置, + // 避免下面 refreshList 信号触发 refreshPanel 后, + // 列表中存在可聚焦的服务器项导致 m_currentIndex 被设置。 + ServerConfigManager::instance()->m_serverConfigs.clear(); // 刷新界面 emit ServerConfigManager::instance()->refreshList(); diff --git a/tests/src/settings/ut_newdspinbox_test.cpp b/tests/src/settings/ut_newdspinbox_test.cpp index 5ecda8c7..9d120aaf 100644 --- a/tests/src/settings/ut_newdspinbox_test.cpp +++ b/tests/src/settings/ut_newdspinbox_test.cpp @@ -78,4 +78,129 @@ TEST_F(UT_NewDSpinBox_Test, eventFilter_Key_Down) spinBox->deleteLater(); } +// 设置字体大小范围(5~50),验证边界值不越界 +TEST_F(UT_NewDSpinBox_Test, setRange_FontRange) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(5, 50); + spinBox->setValue(50); + EXPECT_EQ(spinBox->value(), 50); + spinBox->setValue(5); + EXPECT_EQ(spinBox->value(), 5); + spinBox->deleteLater(); +} + +// 设置历史记录范围(1000~10000),setRange 会把 minimum 放宽到 1 +TEST_F(UT_NewDSpinBox_Test, setRange_HistoryRange) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(1000, 10000); + // 此时允许临时输入更小的值进行智能补全 + spinBox->setValue(1); + EXPECT_EQ(spinBox->value(), 1); + spinBox->setValue(10000); + EXPECT_EQ(spinBox->value(), 10000); + spinBox->deleteLater(); +} + +// 设置其它范围,验证通用范围分支 +TEST_F(UT_NewDSpinBox_Test, setRange_OtherRange) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(100, 500); + spinBox->setValue(100); + EXPECT_EQ(spinBox->value(), 100); + spinBox->deleteLater(); +} + +// 测试 keyPressEvent 在历史记录范围下按 Enter 触发智能补全(输入 5 -> 5000) +TEST_F(UT_NewDSpinBox_Test, keyPressEvent_EnterSmartComplete) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(1000, 10000); + spinBox->lineEdit()->setText("5"); + QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); + QApplication::sendEvent(spinBox, &event); + EXPECT_EQ(spinBox->value(), 5000); + spinBox->deleteLater(); +} + +// 测试 keyPressEvent 在历史记录范围下按非 Enter 键不触发智能补全 +TEST_F(UT_NewDSpinBox_Test, keyPressEvent_OtherKey) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(1000, 10000); + spinBox->setValue(2000); + QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier); + QApplication::sendEvent(spinBox, &event); + // 普通按键不会触发智能补全逻辑,值保持不变 + EXPECT_EQ(spinBox->value(), 2000); + spinBox->deleteLater(); +} + +// 测试 keyPressEvent 在字体大小范围下按 Enter 不触发智能补全 +TEST_F(UT_NewDSpinBox_Test, keyPressEvent_Enter_FontRange) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(5, 50); + spinBox->setValue(20); + QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); + QApplication::sendEvent(spinBox, &event); + // 字体范围不会进入智能补全逻辑 + EXPECT_EQ(spinBox->value(), 20); + spinBox->deleteLater(); +} + +// 测试 focusOutEvent 在历史记录范围下触发智能补全 +TEST_F(UT_NewDSpinBox_Test, focusOutEvent_HistoryRange) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(1000, 10000); + spinBox->lineEdit()->setText("22"); + QFocusEvent event(QEvent::FocusOut); + QApplication::sendEvent(spinBox, &event); + // 22 -> 2200 + EXPECT_EQ(spinBox->value(), 2200); + spinBox->deleteLater(); +} + +// 测试 focusOutEvent 在字体范围下不触发智能补全 +TEST_F(UT_NewDSpinBox_Test, focusOutEvent_FontRange) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(5, 50); + spinBox->setValue(20); + QFocusEvent event(QEvent::FocusOut); + QApplication::sendEvent(spinBox, &event); + EXPECT_EQ(spinBox->value(), 20); + spinBox->deleteLater(); +} + +// 测试 focusOutEvent 在历史记录范围下输入无效文本时使用当前值兜底 +TEST_F(UT_NewDSpinBox_Test, focusOutEvent_InvalidText) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setRange(1000, 10000); + spinBox->setValue(3000); + spinBox->lineEdit()->setText("abc"); + QFocusEvent event(QEvent::FocusOut); + QApplication::sendEvent(spinBox, &event); + // 无效输入应使用 value() 兜底,smartComplete(3000) 返回 3000 + EXPECT_EQ(spinBox->value(), 3000); + spinBox->deleteLater(); +} + +// 测试 wheelEvent 在无焦点时不响应(直接 return,不调用基类) +TEST_F(UT_NewDSpinBox_Test, wheelEvent_NoFocus) +{ + NewDspinBox *spinBox = new NewDspinBox; + spinBox->setValue(20); + // 默认情况下没有焦点,wheelEvent 不应改变值 + QWheelEvent event(QPointF(63, 29), QPointF(63, 29), QPoint(0, 120), QPoint(0, 120), + Qt::NoButton, Qt::NoModifier, Qt::ScrollUpdate, false); + QApplication::sendEvent(spinBox, &event); + EXPECT_EQ(spinBox->value(), 20); + spinBox->deleteLater(); +} + #endif diff --git a/tests/src/settings/ut_settings_test.cpp b/tests/src/settings/ut_settings_test.cpp index 4f411806..945043a9 100644 --- a/tests/src/settings/ut_settings_test.cpp +++ b/tests/src/settings/ut_settings_test.cpp @@ -115,11 +115,24 @@ TEST_F(UT_Settings_Test, SettingsTest) EXPECT_TRUE(UT_STUB_DSETTINGSOPTION_VALUE_RESULT); } +// Qt6 中 QObject::tr() 走 QCoreApplication::translate 静态函数, +// 而非 QTranslator::translate 虚函数。直接 stub 静态符号才能拦截。 +static bool ut_QCoreApplication_translate_hasRuned = false; +static QString ut_QCoreApplication_translate(const char *, const char *, const char *, int) +{ + ut_QCoreApplication_translate_hasRuned = true; + return QString(); +} + TEST_F(UT_Settings_Test, GenerateSettingTranslate) { - UT_STUB_QTRANSLATE_TRANSLATE_CREATE; + using TranslateFunc = QString (*)(const char *, const char *, const char *, int); + Stub stub; + stub.set((TranslateFunc)ADDR(QCoreApplication, translate), ut_QCoreApplication_translate); + ut_QCoreApplication_translate_hasRuned = false; + GenerateSettingTranslate(); - EXPECT_TRUE(UT_STUB_QTRANSLATE_TRANSLATE_RESULT); + EXPECT_TRUE(ut_QCoreApplication_translate_hasRuned); } TEST_F(UT_Settings_Test, createSpinButtonHandle) diff --git a/tests/src/views/ut_termwidgetpage_test.cpp b/tests/src/views/ut_termwidgetpage_test.cpp index 7d64af2a..e55eb62b 100644 --- a/tests/src/views/ut_termwidgetpage_test.cpp +++ b/tests/src/views/ut_termwidgetpage_test.cpp @@ -312,13 +312,22 @@ TEST_F(UT_TermWidgetPage_Test, setBlinkingCursor) termWidgetPage.resize(800, 600); termWidgetPage.show(); - UT_STUB_QWIDGET_UPDATES_CREATE; + // setBlinkingCursor 的调用链: + // TermWidgetPage::setBlinkingCursor + // -> QTermWidget::setBlinkingCursor + // -> TerminalDisplay::setBlinkingCursor + // -> focusInEvent/focusOutEvent + // -> updateCursor() -> update(QRect) ← 有参重载 + // Qt6 中不再触发 QWidget::update() 无参版本,因此 stub 有参重载。 + Stub stub; + stub.set((void (QWidget::*)(const QRect &))ADDR(QWidget, update), ut_terminalDisplay_update); + ut_terminalDisplay_update_hasRunned = false; termWidgetPage.setBlinkingCursor(false); - EXPECT_TRUE(UT_STUB_QWIDGET_UPDATES_RESULT); + EXPECT_TRUE(ut_terminalDisplay_update_hasRunned); - UT_STUB_QWIDGET_UPDATES_PREPARE; + ut_terminalDisplay_update_hasRunned = false; termWidgetPage.setBlinkingCursor(true); - EXPECT_TRUE(UT_STUB_QWIDGET_UPDATES_RESULT); + EXPECT_TRUE(ut_terminalDisplay_update_hasRunned); } TEST_F(UT_TermWidgetPage_Test, setPressingScroll)