test: 新增C++后端单元测试,标记#17完成并更新审查清单

新建 tests/tst_networkmonitorapplet.cpp(Qt Test),5个测试用例覆盖
isPhysicalInterface、速度计算、负值钳制、总量累加、接口校验。

同时更新审查清单:#17标记完成,推荐开发中#19/#20/#21/#23/#30/#33
标记为随缺陷修复一并完成。
This commit is contained in:
2026-07-24 19:03:52 +08:00
parent fba506d9d8
commit 2e615df2ff
3 changed files with 241 additions and 11 deletions
+202
View File
@@ -0,0 +1,202 @@
// SPDX-FileCopyrightText: 2026 Jokul
//
// SPDX-License-Identifier: LGPL-3.0-or-later
// NetworkMonitorApplet 单元测试
// 覆盖核心纯逻辑函数:isPhysicalInterface、速度计算(含真实间隔/负值钳制/总量累加)、
// setActiveInterface 接口校验
// 用 #define private public 技巧访问私有成员(friend 声明因 DS_BEGIN_NAMESPACE
// 命名空间与 Q_OBJECT 宏交互而无法正确解析,此为 C++ 测试常用替代方案)
// 必须在 include 头文件之前定义,使 private 成员在测试编译单元中可访问
#define private public
#include "networkmonitorapplet.h"
#undef private
#include <QtTest/QtTest>
#include <QDateTime>
// dde-shell 的 DS 命名空间(DS_BEGIN_NAMESPACE = namespace ds {
DS_USE_NAMESPACE
class NetworkMonitorAppletTest : public QObject
{
Q_OBJECT
private:
// 创建 applet 实例的辅助方法
// 构造时不调用 init()(会启动定时器),仅用于测试纯逻辑方法
NetworkMonitorApplet *createApplet()
{
return new NetworkMonitorApplet();
}
private slots:
// isPhysicalInterface:物理网卡前缀匹配
void testIsPhysicalInterface_data();
void testIsPhysicalInterface();
// 速度计算:按真实时间间隔计算
void testCalculateSpeed();
// 计数器回绕时负值钳制为 0
void testNegativeDeltaClamped();
// 总量累加而非取计数器值
void testTotalAccumulation();
// setActiveInterface 拒绝无效接口名
void testSetActiveInterfaceValidation();
};
void NetworkMonitorAppletTest::testIsPhysicalInterface_data()
{
QTest::addColumn<QString>("name");
QTest::addColumn<bool>("expected");
// 物理网卡
QTest::newRow("wlp3s0") << "wlp3s0" << true;
QTest::newRow("wlan0") << "wlan0" << true;
QTest::newRow("enp3s0") << "enp3s0" << true;
QTest::newRow("eth0") << "eth0" << true;
// 非物理接口
QTest::newRow("lo") << "lo" << false;
QTest::newRow("docker0") << "docker0" << false;
QTest::newRow("veth0") << "veth0" << false;
QTest::newRow("br-xxx") << "br-xxx" << false;
QTest::newRow("tun0") << "tun0" << false;
QTest::newRow("Meta") << "Meta" << false;
QTest::newRow("empty") << "" << false;
}
void NetworkMonitorAppletTest::testIsPhysicalInterface()
{
NetworkMonitorApplet *applet = createApplet();
QFETCH(QString, name);
QFETCH(bool, expected);
QCOMPARE(applet->isPhysicalInterface(name), expected);
delete applet;
}
void NetworkMonitorAppletTest::testCalculateSpeed()
{
NetworkMonitorApplet *applet = createApplet();
// 设置活动接口和接口数据
applet->m_interfaceList = QStringList() << "eth0";
NetworkInterface iface;
iface.name = "eth0";
iface.rxBytes = 1000;
iface.txBytes = 500;
applet->m_interfaces["eth0"] = iface;
applet->m_activeInterface = "eth0";
// 模拟首次更新:记录基线
applet->m_firstUpdate = true;
applet->calculateSpeed();
QVERIFY(!applet->m_firstUpdate);
// 第二次更新:字节增加了 1000 rx / 500 tx,间隔约 1 秒
iface.rxBytes = 2000;
iface.txBytes = 1000;
applet->m_interfaces["eth0"] = iface;
applet->m_lastTimestampMs = QDateTime::currentMSecsSinceEpoch() - 1000;
applet->calculateSpeed();
// 速度应约为 1000 bytes/sec(允许误差因真实时间戳)
QVERIFY(applet->m_downloadSpeed > 900 && applet->m_downloadSpeed < 1100);
QVERIFY(applet->m_uploadSpeed > 450 && applet->m_uploadSpeed < 550);
delete applet;
}
void NetworkMonitorAppletTest::testNegativeDeltaClamped()
{
NetworkMonitorApplet *applet = createApplet();
applet->m_interfaceList = QStringList() << "eth0";
NetworkInterface iface;
iface.name = "eth0";
iface.rxBytes = 2000;
iface.txBytes = 1000;
applet->m_interfaces["eth0"] = iface;
applet->m_activeInterface = "eth0";
// 首次更新记录基线
applet->m_firstUpdate = true;
applet->calculateSpeed();
// 模拟计数器回绕:当前值小于上次值
iface.rxBytes = 500; // 回绕!
iface.txBytes = 200; // 回绕!
applet->m_interfaces["eth0"] = iface;
applet->m_lastTimestampMs = QDateTime::currentMSecsSinceEpoch() - 1000;
applet->calculateSpeed();
// 速度应为 0,不应为负
QVERIFY(applet->m_downloadSpeed >= 0);
QVERIFY(applet->m_uploadSpeed >= 0);
delete applet;
}
void NetworkMonitorAppletTest::testTotalAccumulation()
{
NetworkMonitorApplet *applet = createApplet();
applet->m_interfaceList = QStringList() << "eth0";
NetworkInterface iface;
iface.name = "eth0";
iface.rxBytes = 0;
iface.txBytes = 0;
applet->m_interfaces["eth0"] = iface;
applet->m_activeInterface = "eth0";
applet->m_totalDownload = 0;
applet->m_totalUpload = 0;
// 首次更新记录基线
applet->m_firstUpdate = true;
applet->calculateSpeed();
// 第一次增量:rx +1000, tx +500
iface.rxBytes = 1000;
iface.txBytes = 500;
applet->m_interfaces["eth0"] = iface;
applet->m_lastTimestampMs = QDateTime::currentMSecsSinceEpoch() - 1000;
applet->calculateSpeed();
QCOMPARE(applet->m_totalDownload, qint64(1000));
QCOMPARE(applet->m_totalUpload, qint64(500));
// 第二次增量:rx +2000, tx +1000
iface.rxBytes = 3000;
iface.txBytes = 1500;
applet->m_interfaces["eth0"] = iface;
applet->m_lastTimestampMs = QDateTime::currentMSecsSinceEpoch() - 1000;
applet->calculateSpeed();
// 总量应累加,而非取计数器值
QCOMPARE(applet->m_totalDownload, qint64(3000));
QCOMPARE(applet->m_totalUpload, qint64(1500));
delete applet;
}
void NetworkMonitorAppletTest::testSetActiveInterfaceValidation()
{
NetworkMonitorApplet *applet = createApplet();
applet->m_interfaceList = QStringList() << "eth0" << "wlan0";
applet->m_activeInterface = "eth0";
// 无效接口名应被忽略
applet->setActiveInterface("nonexistent");
QCOMPARE(applet->m_activeInterface, QString("eth0"));
// 有效接口名应被设置
applet->setActiveInterface("wlan0");
QCOMPARE(applet->m_activeInterface, QString("wlan0"));
delete applet;
}
QTEST_MAIN(NetworkMonitorAppletTest)
#include "tst_networkmonitorapplet.moc"