// SPDX-License-Identifier: MIT #include "toolmodel.h" #include #include #include #include class ToolModelTest : public QObject { Q_OBJECT private Q_SLOTS: void comparesRpmVersions_data() { QTest::addColumn("installed"); QTest::addColumn("available"); QTest::addColumn("update"); QTest::newRow("numeric release") << QStringLiteral("0.1.0-9.fc44") << QStringLiteral("0.1.0-11.fc44") << true; QTest::newRow("same version") << QStringLiteral("0.1.0-11.fc44") << QStringLiteral("0.1.0-11.fc44") << false; QTest::newRow("locally newer") << QStringLiteral("0.1.0-25.fc44") << QStringLiteral("0.1.0-23.fc44") << false; QTest::newRow("epoch wins") << QStringLiteral("2.0-1") << QStringLiteral("1:1.0-1") << true; QTest::newRow("installed epoch wins") << QStringLiteral("1:1.0-1") << QStringLiteral("2.0-1") << false; QTest::newRow("implicit zero epoch") << QStringLiteral("0:1.0-1") << QStringLiteral("1.0-1") << false; QTest::newRow("prerelease") << QStringLiteral("1.0~rc1-1") << QStringLiteral("1.0-1") << true; QTest::newRow("snapshot") << QStringLiteral("1.0-1") << QStringLiteral("1.0^git1-1") << true; QTest::newRow("newer than snapshot") << QStringLiteral("1.0^git1-1") << QStringLiteral("1.0.1-1") << true; } void comparesRpmVersions() { QFETCH(QString, installed); QFETCH(QString, available); QFETCH(bool, update); ToolModel model; // Match an older noarch install against its native-architecture update. // No DNF transaction state or privileged files are needed to compare EVRs. const PackageRecord current{QStringLiteral("touchpad-hold-tap"), installed, QStringLiteral("noarch"), QStringLiteral("Gesture")}; const PackageRecord candidate{current.name, available, QStringLiteral("x86_64"), current.summary}; model.setPackages({current}, {candidate}); QCOMPARE(model.data(model.index(0), ToolModel::UpdateAvailableRole).toBool(), update); model.setPackages({}, {candidate}); QVERIFY(!model.data(model.index(0), ToolModel::UpdateAvailableRole).toBool()); } void incompatibleFrameworkIsOnlyListedWhenInstalled() { if (packageCompatibilityError(QStringLiteral("framework-laptop-tools")).isEmpty()) QSKIP("Requires a non-Framework test host"); const PackageRecord package{QStringLiteral("framework-laptop-tools"), QStringLiteral("1"), QStringLiteral("x86_64"), QStringLiteral("Hardware controls")}; ToolModel model; model.setPackages({}, {package}); QCOMPARE(model.rowCount(), 0); model.setPackages({package}, {package}); QCOMPARE(model.rowCount(), 1); QVERIFY(!model.data(model.index(0), ToolModel::CompatibilityErrorRole).toString().isEmpty()); QVERIFY(!model.mayInstall(package.name)); QVERIFY(model.mayRemove(package.name)); QVERIFY(!model.data(model.index(0), ToolModel::ConfigurableRole).toBool()); } void discoversLocallyInstalledToolSettings() { QTemporaryDir directory; QVERIFY(directory.isValid()); const QByteArray original = qgetenv("XDG_DATA_HOME"); qputenv("XDG_DATA_HOME", directory.path().toUtf8()); QVERIFY(QDir(directory.path()).mkpath(QStringLiteral("fedora-tools/settings"))); QFile registration(directory.filePath(QStringLiteral("fedora-tools/settings/local-tool.json"))); QVERIFY(registration.open(QIODevice::WriteOnly)); registration.write("{\"command\":[\"/bin/true\",\"--settings\"]}"); registration.close(); ToolModel model; const PackageRecord package{QStringLiteral("local-tool"), QStringLiteral("1"), QStringLiteral("noarch"), QStringLiteral("Local tool")}; model.setPackages({package}, {}); QCOMPARE(model.rowCount(), 1); QVERIFY(model.data(model.index(0), ToolModel::ConfigurableRole).toBool()); QVERIFY(model.data(model.index(0), ToolModel::ExternalConfigurationRole).toBool()); QVERIFY(!model.data(model.index(0), ToolModel::AvailableRole).toBool()); QCOMPARE(model.configurationCommand(package.name), QStringList({QStringLiteral("/bin/true"), QStringLiteral("--settings")})); // Repository entries alone must not expose locally registered commands. model.setPackages({}, {package}); QVERIFY(!model.data(model.index(0), ToolModel::ConfigurableRole).toBool()); QVERIFY(model.configurationCommand(package.name).isEmpty()); qputenv("XDG_DATA_HOME", original); } void mergesInstalledAndAvailablePackages() { ToolModel model; const PackageRecord installed{QStringLiteral("touchpad-hold-tap"), QStringLiteral("0.1.0-5.fc44"), QStringLiteral("noarch"), QStringLiteral("Gesture")}; const PackageRecord available{QStringLiteral("touchpad-hold-tap"), QStringLiteral("0.1.0-6.fc44"), QStringLiteral("noarch"), QStringLiteral("Gesture")}; model.setPackages({installed}, {available}); QCOMPARE(model.rowCount(), 1); const QModelIndex index = model.index(0); QCOMPARE(model.data(index, ToolModel::InstalledRole).toBool(), true); QCOMPARE(model.data(index, ToolModel::AvailableRole).toBool(), true); QCOMPARE(model.data(index, ToolModel::UpdateAvailableRole).toBool(), true); QCOMPARE(model.mayInstall(QStringLiteral("touchpad-hold-tap")), true); QCOMPARE(model.mayRemove(QStringLiteral("touchpad-hold-tap")), true); QCOMPARE(model.mayRemove(QStringLiteral("missing-tool")), false); } void doesNotOfferDowngrades() { ToolModel model; const PackageRecord installed{QStringLiteral("touchpad-hold-tap"), QStringLiteral("0.1.0-7.fc44"), QStringLiteral("noarch"), QStringLiteral("Gesture")}; const PackageRecord available{QStringLiteral("touchpad-hold-tap"), QStringLiteral("0.1.0-6.fc44"), QStringLiteral("noarch"), QStringLiteral("Gesture")}; model.setPackages({installed}, {available}); QCOMPARE(model.data(model.index(0), ToolModel::UpdateAvailableRole).toBool(), false); } void makesFingerprintControllerConfigurable() { ToolModel model; const PackageRecord package{QStringLiteral("plasma-fingerprint-workaround"), QStringLiteral("0.1.0-2.fc44"), QStringLiteral("noarch"), QStringLiteral("Fingerprint")}; model.setPackages({package}, {package}); QCOMPARE(model.data(model.index(0), ToolModel::ConfigurableRole).toBool(), true); } void sortsAlphabeticallyRegardlessOfInstallState() { ToolModel model; const PackageRecord installed{QStringLiteral("touchpad-hold-tap"), QStringLiteral("1"), QStringLiteral("noarch"), QStringLiteral("Touchpad")}; const PackageRecord availableFirst{QStringLiteral("plasma-always-show-unlock"), QStringLiteral("1"), QStringLiteral("noarch"), QStringLiteral("Lock screen")}; const PackageRecord availableLast{QStringLiteral("touchpad-hold-tap"), QStringLiteral("1"), QStringLiteral("noarch"), QStringLiteral("Old touchpad summary")}; model.setPackages({installed}, {availableFirst, availableLast}); QCOMPARE(model.data(model.index(0), ToolModel::PackageNameRole).toString(), QStringLiteral("plasma-always-show-unlock")); QCOMPARE(model.data(model.index(1), ToolModel::PackageNameRole).toString(), QStringLiteral("touchpad-hold-tap")); QCOMPARE(model.data(model.index(1), ToolModel::SummaryRole).toString(), QStringLiteral("Touchpad")); } void makesInstalledToolsWithSettingsConfigurable() { ToolModel model; const PackageRecord shortcuts{QStringLiteral("plasma-task-group-shortcuts"), QStringLiteral("1"), QStringLiteral("x86_64"), QStringLiteral("Shortcuts")}; const PackageRecord touchpad{QStringLiteral("touchpad-hold-tap"), QStringLiteral("1"), QStringLiteral("noarch"), QStringLiteral("Touchpad")}; model.setPackages({shortcuts, touchpad}, {shortcuts, touchpad}); QCOMPARE(model.data(model.index(0), ToolModel::ConfigurableRole).toBool(), true); QCOMPARE(model.data(model.index(1), ToolModel::ConfigurableRole).toBool(), true); } }; QTEST_MAIN(ToolModelTest) #include "test-toolmodel.moc"