File indexing completed on 2024-04-14 03:54:15
0001 /* 0002 SPDX-FileCopyrightText: 2007 Bertjan Broeksema <b.broeksema@kdemail.net> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "plasmoidpackagetest.h" 0008 #include "../src/kpackage/config-package.h" 0009 0010 #include <KJob> 0011 #include <QDir> 0012 #include <QFile> 0013 #include <QSignalSpy> 0014 #include <QStandardPaths> 0015 #include <kzip.h> 0016 0017 #include <QDebug> 0018 #include <QJsonDocument> 0019 #include <QJsonObject> 0020 #include <qtestcase.h> 0021 0022 #include "packagejob.h" 0023 #include "packageloader.h" 0024 #include "private/utils.h" 0025 0026 void PlasmoidPackageTest::initTestCase() 0027 { 0028 QStandardPaths::setTestModeEnabled(true); 0029 } 0030 0031 void PlasmoidPackageTest::init() 0032 { 0033 qDebug() << "PlasmoidPackage::init()"; 0034 qRegisterMetaType<KPackage::Package>(); // Needed for signal spy 0035 m_package = QStringLiteral("Package"); 0036 m_packageRoot = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/packageRoot"; 0037 const auto pack = KPackage::PackageLoader::self()->loadPackageStructure("Plasma/TestKPackageInternalPlasmoid"); 0038 QVERIFY(pack); 0039 m_defaultPackage = KPackage::Package(pack); 0040 cleanup(); // to prevent previous runs from interfering with this one 0041 } 0042 0043 void PlasmoidPackageTest::cleanup() 0044 { 0045 qDebug() << "cleaning up"; 0046 // Clean things up. 0047 QDir(m_packageRoot).removeRecursively(); 0048 } 0049 0050 void PlasmoidPackageTest::createTestPackage(const QString &packageName, const QString &version) 0051 { 0052 qDebug() << "Create test package" << m_packageRoot; 0053 QDir pRoot(m_packageRoot); 0054 // Create the root and package dir. 0055 if (!pRoot.exists()) { 0056 QVERIFY(QDir().mkpath(m_packageRoot)); 0057 } 0058 0059 // Create the package dir 0060 QVERIFY(QDir().mkpath(m_packageRoot + "/" + packageName)); 0061 qDebug() << "Created" << (m_packageRoot + "/" + packageName); 0062 0063 // Create the metadata.json file 0064 QFile file(m_packageRoot + "/" + packageName + "/metadata.json"); 0065 0066 QVERIFY(file.open(QIODevice::WriteOnly)); 0067 0068 QJsonObject kplugin; 0069 kplugin.insert(QLatin1String("Id"), packageName); 0070 kplugin.insert(QLatin1String("Name"), packageName); 0071 kplugin.insert(QLatin1String("Version"), version); 0072 QJsonObject root{{QLatin1String("KPlugin"), kplugin}}; 0073 0074 QTextStream out(&file); 0075 file.write(QJsonDocument(root).toJson()); 0076 file.flush(); 0077 file.close(); 0078 0079 qDebug() << "OUT: " << packageName; 0080 0081 // Create the ui dir. 0082 QVERIFY(QDir().mkpath(m_packageRoot + "/" + packageName + "/contents/ui")); 0083 0084 // Create the main file. 0085 file.setFileName(m_packageRoot + "/" + packageName + "/contents/ui/main.qml"); 0086 QVERIFY(file.open(QIODevice::WriteOnly)); 0087 0088 out << "THIS IS A PLASMOID SCRIPT....."; 0089 file.flush(); 0090 file.close(); 0091 0092 qDebug() << "THIS IS A PLASMOID SCRIPT THING"; 0093 // Now we have a minimal plasmoid package which is valid. Let's add some 0094 // files to it for test purposes. 0095 0096 // Create the images dir. 0097 QVERIFY(QDir().mkpath(m_packageRoot + "/" + packageName + "/contents/images")); 0098 file.setFileName(m_packageRoot + "/" + packageName + "/contents/images/image-1.svg"); 0099 0100 QVERIFY(file.open(QIODevice::WriteOnly)); 0101 0102 out << "<svg>This is a test image</svg>"; 0103 file.flush(); 0104 file.close(); 0105 0106 file.setFileName(m_packageRoot + "/" + packageName + "/contents/images/image-2.svg"); 0107 0108 QVERIFY(file.open(QIODevice::WriteOnly)); 0109 0110 out.setDevice(&file); 0111 out << "<svg>This is another test image</svg>"; 0112 file.flush(); 0113 file.close(); 0114 0115 // Create the scripts dir. 0116 QVERIFY(QDir().mkpath(m_packageRoot + "/" + packageName + "/contents/code")); 0117 0118 // Create 2 js files 0119 file.setFileName(m_packageRoot + "/" + packageName + "/contents/code/script.js"); 0120 QVERIFY(file.open(QIODevice::WriteOnly)); 0121 0122 out << "THIS IS A SCRIPT....."; 0123 file.flush(); 0124 file.close(); 0125 } 0126 0127 void PlasmoidPackageTest::isValid() 0128 { 0129 KPackage::Package p(m_defaultPackage); 0130 p.setPath(m_packageRoot + '/' + m_package); 0131 #ifndef NDEBUG 0132 qDebug() << "package path is" << p.path(); 0133 #endif 0134 0135 // A PlasmoidPackage is valid when: 0136 // - The package root exists. 0137 // - The package root consists an file named "ui/main.qml" 0138 QVERIFY(!p.isValid()); 0139 0140 // Create the root and package dir. 0141 QVERIFY(QDir().mkpath(m_packageRoot)); 0142 QVERIFY(QDir().mkpath(m_packageRoot + "/" + m_package)); 0143 0144 // Should still be invalid. 0145 p = KPackage::Package(m_defaultPackage); 0146 p.setPath(m_packageRoot + '/' + m_package); 0147 QVERIFY(!p.isValid()); 0148 0149 // Create the ui dir. 0150 QVERIFY(QDir().mkpath(m_packageRoot + "/" + m_package + "/contents/ui")); 0151 0152 // No main file yet so should still be invalid. 0153 p = KPackage::Package(m_defaultPackage); 0154 p.setPath(m_packageRoot + '/' + m_package); 0155 QVERIFY(!p.isValid()); 0156 0157 // Create the main file. 0158 QFile file(m_packageRoot + "/" + m_package + "/contents/ui/main.qml"); 0159 QVERIFY(file.open(QIODevice::WriteOnly)); 0160 0161 QTextStream out(&file); 0162 out << "THIS IS A PLASMOID SCRIPT.....\n"; 0163 file.flush(); 0164 file.close(); 0165 0166 file.setPermissions(QFile::ReadUser | QFile::WriteUser); 0167 // Main file exists so should be valid now. 0168 p = KPackage::Package(m_defaultPackage); 0169 p.setPath(m_packageRoot + '/' + m_package); 0170 QVERIFY(p.isValid()); 0171 QCOMPARE(p.cryptographicHash(QCryptographicHash::Sha1), QByteArrayLiteral("468c7934dfa635986a85e3364363b1f39d157cd5")); 0172 } 0173 0174 void PlasmoidPackageTest::filePath() 0175 { 0176 // Package::filePath() returns 0177 // - {package_root}/{package_name}/path/to/file if the file exists 0178 // - QString() otherwise. 0179 KPackage::Package p(m_defaultPackage); 0180 p.setPath(m_packageRoot + '/' + m_package); 0181 0182 QCOMPARE(p.filePath("scripts", QStringLiteral("main")), QString()); 0183 0184 QVERIFY(QDir().mkpath(m_packageRoot + "/" + m_package + "/contents/ui/")); 0185 QFile file(m_packageRoot + "/" + m_package + "/contents/ui/main.qml"); 0186 QVERIFY(file.open(QIODevice::WriteOnly)); 0187 0188 QTextStream out(&file); 0189 out << "THIS IS A PLASMOID SCRIPT....."; 0190 file.flush(); 0191 file.close(); 0192 0193 // The package is valid by now so a path for code/main should get returned. 0194 p = KPackage::Package(m_defaultPackage); 0195 p.setPath(m_packageRoot + '/' + m_package); 0196 0197 const QString path = QFileInfo(m_packageRoot + "/" + m_package + "/contents/ui/main.qml").canonicalFilePath(); 0198 0199 // Two ways to get the same info. 0200 // 1. Give the file type which refers to a class of files (a directory) in 0201 // the package structure and the file name. 0202 // 2. Give the file type which refers to a file in the package structure. 0203 // 0204 // NOTE: scripts, main and mainscript are defined in packages.cpp and are 0205 // specific for a PlasmoidPackage. 0206 QCOMPARE(p.filePath("mainscript"), path); 0207 QCOMPARE(p.filePath("ui", QStringLiteral("main.qml")), path); 0208 } 0209 0210 void PlasmoidPackageTest::entryList() 0211 { 0212 // Create a package named @p packageName which is valid and has some images. 0213 createTestPackage(m_package, QStringLiteral("1.1")); 0214 0215 // Create a package object and verify that it is valid. 0216 KPackage::Package p(m_defaultPackage); 0217 p.setPath(m_packageRoot + '/' + m_package); 0218 QVERIFY(p.isValid()); 0219 0220 // Now we have a valid package that should contain the following files in 0221 // given filetypes: 0222 // fileTye - Files 0223 // scripts - {"script.js"} 0224 // images - {"image-1.svg", "image-2.svg"} 0225 QStringList files = p.entryList("scripts"); 0226 QCOMPARE(files.size(), 1); 0227 QVERIFY(files.contains(QStringLiteral("script.js"))); 0228 0229 files = p.entryList("images"); 0230 QCOMPARE(files.size(), 2); 0231 QVERIFY(files.contains(QStringLiteral("image-1.svg"))); 0232 QVERIFY(files.contains(QStringLiteral("image-2.svg"))); 0233 } 0234 0235 void PlasmoidPackageTest::createAndInstallPackage() 0236 { 0237 qDebug() << " "; 0238 qDebug() << " CreateAndInstall "; 0239 createTestPackage(QStringLiteral("plasmoid_to_package"), QStringLiteral("1.1")); 0240 const QString packagePath = m_packageRoot + '/' + "testpackage.plasmoid"; 0241 0242 KZip creator(packagePath); 0243 QVERIFY(creator.open(QIODevice::WriteOnly)); 0244 creator.addLocalDirectory(m_packageRoot + '/' + "plasmoid_to_package", QStringLiteral(".")); 0245 creator.close(); 0246 QDir rootDir(m_packageRoot + "/plasmoid_to_package"); 0247 rootDir.removeRecursively(); 0248 0249 QVERIFY2(QFile::exists(packagePath), qPrintable(packagePath)); 0250 0251 KZip package(packagePath); 0252 QVERIFY(package.open(QIODevice::ReadOnly)); 0253 const KArchiveDirectory *dir = package.directory(); 0254 QVERIFY(dir); // 0255 QVERIFY(dir->entry(QStringLiteral("metadata.json"))); 0256 const KArchiveEntry *contentsEntry = dir->entry(QStringLiteral("contents")); 0257 QVERIFY(contentsEntry); 0258 QVERIFY(contentsEntry->isDirectory()); 0259 const KArchiveDirectory *contents = static_cast<const KArchiveDirectory *>(contentsEntry); 0260 QVERIFY(contents->entry(QStringLiteral("ui"))); 0261 QVERIFY(contents->entry(QStringLiteral("images"))); 0262 0263 KPackage::PackageLoader::self()->addKnownPackageStructure(m_defaultPackageStructure, new KPackage::PackageStructure(this)); 0264 KPackage::Package p; 0265 qDebug() << "Installing " << packagePath; 0266 auto job = KPackage::PackageJob::install(m_defaultPackageStructure, packagePath, m_packageRoot); 0267 connect(job, &KJob::finished, this, [&p, job]() { // clazy:exclude=lambda-in-connect 0268 p = job->package(); 0269 }); 0270 QSignalSpy spy(job, &KJob::finished); 0271 QVERIFY(spy.wait(1000)); 0272 0273 // is the package instance usable (ie proper path) after the install job has been completed? 0274 QCOMPARE(p.path(), QString(QDir(m_packageRoot % "/plasmoid_to_package").canonicalPath() + QLatin1Char('/'))); 0275 cleanupPackage(QStringLiteral("plasmoid_to_package")); 0276 } 0277 0278 void PlasmoidPackageTest::createAndUpdatePackage() 0279 { 0280 // does the version number parsing work? 0281 QVERIFY(isVersionNewer(QStringLiteral("1.1"), QStringLiteral("1.1.1"))); 0282 QVERIFY(!isVersionNewer(QStringLiteral("1.1.1"), QStringLiteral("1.1"))); 0283 QVERIFY(isVersionNewer(QStringLiteral("1.1.1"), QStringLiteral("1.1.2"))); 0284 QVERIFY(isVersionNewer(QStringLiteral("1.1.2"), QStringLiteral("2.1"))); 0285 QVERIFY(isVersionNewer(QStringLiteral("0.1.2"), QStringLiteral("2"))); 0286 QVERIFY(!isVersionNewer(QStringLiteral("1"), QStringLiteral("0.1.2"))); 0287 0288 qDebug() << " "; 0289 qDebug() << " CreateAndUpdate "; 0290 createTestPackage(QStringLiteral("plasmoid_to_package"), QStringLiteral("1.1")); 0291 const QString packagePath = m_packageRoot + '/' + "testpackage.plasmoid"; 0292 0293 KZip creator(packagePath); 0294 QVERIFY(creator.open(QIODevice::WriteOnly)); 0295 creator.addLocalDirectory(m_packageRoot + '/' + "plasmoid_to_package", QStringLiteral(".")); 0296 creator.close(); 0297 QDir rootDir(m_packageRoot + "/plasmoid_to_package"); 0298 rootDir.removeRecursively(); 0299 0300 QVERIFY(QFile::exists(packagePath)); 0301 0302 KZip package(packagePath); 0303 QVERIFY(package.open(QIODevice::ReadOnly)); 0304 const KArchiveDirectory *dir = package.directory(); 0305 QVERIFY(dir); // 0306 QVERIFY(dir->entry(QStringLiteral("metadata.json"))); 0307 const KArchiveEntry *contentsEntry = dir->entry(QStringLiteral("contents")); 0308 QVERIFY(contentsEntry); 0309 QVERIFY(contentsEntry->isDirectory()); 0310 const KArchiveDirectory *contents = static_cast<const KArchiveDirectory *>(contentsEntry); 0311 QVERIFY(contents->entry(QStringLiteral("ui"))); 0312 QVERIFY(contents->entry(QStringLiteral("images"))); 0313 0314 qDebug() << "Installing " << packagePath; 0315 0316 KJob *job = KPackage::PackageJob::update(m_defaultPackageStructure, packagePath, m_packageRoot); 0317 connect(job, &KJob::finished, [this, job]() { 0318 packageInstalled(job); 0319 }); 0320 QSignalSpy spy(job, &KJob::finished); 0321 QVERIFY(spy.wait(1000)); 0322 0323 // same version, should fail 0324 job = KPackage::PackageJob::update(m_defaultPackageStructure, packagePath, m_packageRoot); 0325 QSignalSpy spyFail(job, &KJob::finished); 0326 QVERIFY(spyFail.wait(1000)); 0327 QVERIFY(job->error() == KPackage::PackageJob::JobError::NewerVersionAlreadyInstalledError); 0328 qDebug() << job->errorText(); 0329 0330 // create a new package with higher version 0331 createTestPackage(QStringLiteral("plasmoid_to_package"), QStringLiteral("1.2")); 0332 0333 KZip creator2(packagePath); 0334 QVERIFY(creator2.open(QIODevice::WriteOnly)); 0335 creator2.addLocalDirectory(m_packageRoot + '/' + "plasmoid_to_package", QStringLiteral(".")); 0336 creator2.close(); 0337 QDir rootDir2(m_packageRoot + "/plasmoid_to_package"); 0338 rootDir2.removeRecursively(); 0339 0340 KJob *job2 = KPackage::PackageJob::update(m_defaultPackageStructure, packagePath, m_packageRoot); 0341 connect(job2, &KJob::finished, [this, job2]() { 0342 packageInstalled(job2); 0343 }); 0344 QSignalSpy spy2(job2, &KJob::finished); 0345 QVERIFY(spy2.wait(1000)); 0346 0347 cleanupPackage(QStringLiteral("plasmoid_to_package")); 0348 } 0349 0350 void PlasmoidPackageTest::uncompressPackageWithSubFolder() 0351 { 0352 KPackage::PackageStructure *structure = new KPackage::PackageStructure; 0353 KPackage::Package package(structure); 0354 package.setPath(QFINDTESTDATA("data/customcontent.tar.gz")); 0355 0356 QCOMPARE(readKPackageType(package.metadata()), "KPackage/CustomContent"); 0357 } 0358 0359 void PlasmoidPackageTest::cleanupPackage(const QString &packageName) 0360 { 0361 KJob *j = KPackage::PackageJob::uninstall(m_defaultPackageStructure, packageName, m_packageRoot); 0362 connect(j, &KJob::finished, [this, j]() { 0363 packageUninstalled(j); 0364 }); 0365 0366 QSignalSpy spy(j, &KJob::finished); 0367 QVERIFY(spy.wait(1000)); 0368 } 0369 0370 void PlasmoidPackageTest::packageInstalled(KJob *j) 0371 { 0372 QVERIFY2(j->error() == KJob::NoError, qPrintable(j->errorText())); 0373 } 0374 0375 void PlasmoidPackageTest::packageUninstalled(KJob *j) 0376 { 0377 QVERIFY2(j->error() == KJob::NoError, qPrintable(j->errorText())); 0378 } 0379 void PlasmoidPackageTest::testInstallNonExistentPackageStructure() 0380 { 0381 const QString packageName = "testpackage"; 0382 createTestPackage(packageName, "1.0"); 0383 auto job = KPackage::PackageJob::install("KPackage/DoesNotExist", packageName, m_packageRoot); 0384 connect(job, &KJob::result, this, [job]() { 0385 QVERIFY(!job->package().isValid()); 0386 QCOMPARE(job->error(), KPackage::PackageJob::JobError::InvalidPackageStructure); 0387 QCOMPARE(job->errorText(), "Could not load package structure KPackage/DoesNotExist"); 0388 }); 0389 QSignalSpy spy(job, &KJob::result); 0390 QVERIFY(spy.wait(1000)); 0391 } 0392 0393 QTEST_MAIN(PlasmoidPackageTest) 0394 0395 #include "moc_plasmoidpackagetest.cpp"