File indexing completed on 2025-02-02 05:17:19

0001 /***************************************************************************
0002  *   SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com>       *
0003  *                                                                         *
0004  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  ***************************************************************************/
0006 
0007 #include <ApplicationAddonsModel.h>
0008 #include <Category/CategoryModel.h>
0009 #include <ReviewsBackend/ReviewsModel.h>
0010 #include <Transaction/TransactionModel.h>
0011 #include <resources/AbstractBackendUpdater.h>
0012 #include <resources/DiscoverAction.h>
0013 #include <resources/ResourcesModel.h>
0014 #include <resources/ResourcesProxyModel.h>
0015 #include <resources/SourcesModel.h>
0016 
0017 #include <QSignalSpy>
0018 #include <QStandardPaths>
0019 #include <QTest>
0020 
0021 class FlatpakTest : public QObject
0022 {
0023     Q_OBJECT
0024 public:
0025     AbstractResourcesBackend *backendByName(ResourcesModel *m, const QString &name)
0026     {
0027         const QVector<AbstractResourcesBackend *> backends = m->backends();
0028         for (AbstractResourcesBackend *backend : backends) {
0029             if (QLatin1String(backend->metaObject()->className()) == name) {
0030                 return backend;
0031             }
0032         }
0033         return nullptr;
0034     }
0035 
0036     FlatpakTest(QObject *parent = nullptr)
0037         : QObject(parent)
0038     {
0039         QDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + QLatin1String("/discover-flatpak-test")).removeRecursively();
0040 
0041         QStandardPaths::setTestModeEnabled(true);
0042         qputenv("FLATPAK_TEST_MODE", "ON");
0043         m_model = new ResourcesModel(QStringLiteral("flatpak-backend"), this);
0044         m_appBackend = backendByName(m_model, QStringLiteral("FlatpakBackend"));
0045     }
0046 
0047 private Q_SLOTS:
0048     void initTestCase()
0049     {
0050         QVERIFY(m_appBackend);
0051         while (m_appBackend->isFetching()) {
0052             QSignalSpy spy(m_appBackend, &AbstractResourcesBackend::fetchingChanged);
0053             QVERIFY(spy.wait());
0054         }
0055     }
0056 
0057     void testAddSource()
0058     {
0059         auto res = getAllResources(m_appBackend);
0060         QCOMPARE(res.count(), 0);
0061 
0062         auto m = SourcesModel::global();
0063         auto bk = qobject_cast<AbstractSourcesBackend *>(m->index(0, 0).data(SourcesModel::SourcesBackend).value<QObject *>());
0064 
0065         QSignalSpy initializedSpy(m_appBackend, SIGNAL(initialized()));
0066         if (m->rowCount() == 1) {
0067             QSignalSpy spy(m, &SourcesModel::rowsInserted);
0068             qobject_cast<DiscoverAction *>(bk->actions().constFirst().value<QObject *>())->trigger();
0069             QVERIFY(spy.count() || spy.wait(200000));
0070         }
0071         QVERIFY(initializedSpy.count() || initializedSpy.wait(200000));
0072         auto resFlathub = getAllResources(m_appBackend);
0073         QVERIFY(resFlathub.count() > 0);
0074     }
0075 
0076     void testListOrigin()
0077     {
0078         AbstractResourcesBackend::Filters f;
0079         f.origin = QStringLiteral("flathub");
0080         auto resources = getResources(m_appBackend->search(f), true);
0081         QVERIFY(resources.count() > 0);
0082     }
0083 
0084     void testInstallApp()
0085     {
0086         AbstractResourcesBackend::Filters f;
0087         f.resourceUrl = QUrl(QStringLiteral("appstream://dosbox.desktop"));
0088         const auto res = getResources(m_appBackend->search(f));
0089         QCOMPARE(res.count(), 1);
0090 
0091         const auto ourResource = res.constFirst();
0092         QCOMPARE(ourResource->state(), AbstractResource::None);
0093         QCOMPARE(waitTransaction(m_appBackend->installApplication(ourResource)), Transaction::DoneStatus);
0094         QCOMPARE(ourResource->state(), AbstractResource::Installed);
0095         QCOMPARE(waitTransaction(m_appBackend->removeApplication(ourResource)), Transaction::DoneStatus);
0096         QCOMPARE(ourResource->state(), AbstractResource::None);
0097     }
0098 
0099     void testFlatpakref()
0100     {
0101         AbstractResourcesBackend::Filters f;
0102         f.resourceUrl = QUrl(QStringLiteral("https://dl.flathub.org/repo/appstream/com.dosbox.DOSBox.flatpakref"));
0103         const auto res = getResources(m_appBackend->search(f));
0104         QCOMPARE(res.count(), 1);
0105 
0106         f.resourceUrl = QUrl(QStringLiteral("appstream://dosbox.desktop"));
0107         const auto res2 = getResources(m_appBackend->search(f));
0108         QCOMPARE(res2, res);
0109 
0110         f.resourceUrl = QUrl(QStringLiteral("appstream://com.dosbox.DOSBox.desktop"));
0111         const auto res3 = getResources(m_appBackend->search(f));
0112         QCOMPARE(res3, res);
0113     }
0114 
0115     /*
0116         void testCancelInstallation()
0117         {
0118             AbstractResourcesBackend::Filters f;
0119             f.resourceUrl = QUrl(QStringLiteral("appstream://com.github.rssguard.desktop"));
0120             const auto res = getResources(m_appBackend->search(f));
0121             QCOMPARE(res.count(), 1);
0122 
0123             const auto resRssguard = res.constFirst();
0124             QCOMPARE(resRssguard->state(), AbstractResource::None);
0125             auto t = m_appBackend->installApplication(resRssguard);
0126             QSignalSpy spy(t, &Transaction::statusChanged);
0127             QVERIFY(spy.wait());
0128             QCOMPARE(t->status(), Transaction::CommittingStatus);
0129             t->cancel();
0130             QVERIFY(spy.wait());
0131             QCOMPARE(t->status(), Transaction::CancelledStatus);
0132         }*/
0133 
0134 private:
0135     Transaction::Status waitTransaction(Transaction *t)
0136     {
0137         int lastProgress = -1;
0138         connect(t, &Transaction::progressChanged, this, [t, &lastProgress] {
0139             Q_ASSERT(lastProgress <= t->progress());
0140             lastProgress = t->progress();
0141         });
0142 
0143         TransactionModel::global()->addTransaction(t);
0144         QSignalSpy spyInstalled(TransactionModel::global(), &TransactionModel::transactionRemoved);
0145         QSignalSpy destructionSpy(t, &QObject::destroyed);
0146 
0147         Transaction::Status ret = t->status();
0148         connect(TransactionModel::global(), &TransactionModel::transactionRemoved, t, [t, &ret](Transaction *trans) {
0149             if (trans == t) {
0150                 ret = trans->status();
0151             }
0152         });
0153         connect(t, &Transaction::statusChanged, t, [t] {
0154             qDebug() << "status" << t->status();
0155         });
0156         while (t && spyInstalled.count() == 0) {
0157             qDebug() << "waiting, currently" << ret << t->progress() << spyInstalled.count() << destructionSpy.count();
0158             spyInstalled.wait(1000);
0159         }
0160         Q_ASSERT(destructionSpy.count() || destructionSpy.wait());
0161         return ret;
0162     }
0163 
0164     QVector<AbstractResource *> getResources(ResultsStream *stream, bool canBeEmpty = true)
0165     {
0166         Q_ASSERT(stream);
0167         QSignalSpy spyResources(stream, &ResultsStream::destroyed);
0168         QVector<AbstractResource *> resources;
0169         connect(stream, &ResultsStream::resourcesFound, this, [&resources](const QVector<StreamResult> &res) {
0170             for (auto result : res) {
0171                 resources += result.resource;
0172             }
0173         });
0174         Q_ASSERT(spyResources.wait(100000));
0175         Q_ASSERT(!resources.isEmpty() || canBeEmpty);
0176         return resources;
0177     }
0178 
0179     QVector<AbstractResource *> getAllResources(AbstractResourcesBackend *backend)
0180     {
0181         AbstractResourcesBackend::Filters f;
0182         if (CategoryModel::global()->rootCategories().isEmpty())
0183             CategoryModel::global()->populateCategories();
0184         f.category = CategoryModel::global()->rootCategories().constFirst();
0185         return getResources(backend->search(f), true);
0186     }
0187 
0188     ResourcesModel *m_model;
0189     AbstractResourcesBackend *m_appBackend;
0190 };
0191 
0192 QTEST_GUILESS_MAIN(FlatpakTest)
0193 
0194 #include "FlatpakTest.moc"