Warning, file /frameworks/kio/autotests/kfilecopytomenutest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2014 David Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include <QMenu> 0009 #include <QSignalSpy> 0010 #include <QTemporaryDir> 0011 #include <QTest> 0012 0013 #include "jobuidelegatefactory.h" 0014 #include "kiotesthelper.h" 0015 #include <KConfigGroup> 0016 #include <KFileCopyToMenu> 0017 #include <KSharedConfig> 0018 0019 #include <KIO/CopyJob> 0020 0021 class KFileCopyToMenuTest : public QObject 0022 { 0023 Q_OBJECT 0024 0025 private Q_SLOTS: 0026 void initTestCase() 0027 { 0028 QStandardPaths::setTestModeEnabled(true); 0029 qputenv("KIOSLAVE_ENABLE_TESTMODE", "1"); // ensure the KIO workers call QStandardPaths::setTestModeEnabled too 0030 0031 QVERIFY(m_tempDir.isValid()); 0032 QVERIFY(m_tempDestDir.isValid()); 0033 QVERIFY(m_nonWritableTempDir.isValid()); 0034 QVERIFY(QFile(m_nonWritableTempDir.path()).setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::ExeOwner | QFile::ExeUser)); 0035 m_srcDir = m_tempDir.path(); 0036 m_destDir = m_tempDestDir.path(); 0037 0038 m_srcFile = m_srcDir + QStringLiteral("/srcfile"); 0039 0040 KIO::setDefaultJobUiDelegateFactoryV2(nullptr); // no "skip" dialogs 0041 0042 // Set a recent dir 0043 KConfigGroup recentDirsGroup(KSharedConfig::openConfig(), "kuick-copy"); 0044 m_recentDirs << m_destDir + QStringLiteral("/nonexistentsubdir") // will be action number count-3 0045 << m_nonWritableTempDir.path() // will be action number count-2 0046 << m_destDir; // will be action number count-1 0047 recentDirsGroup.writeEntry("Paths", m_recentDirs); 0048 0049 m_lastActionCount = 0; 0050 } 0051 0052 void cleanupTestCase() 0053 { 0054 QVERIFY(QFile(m_nonWritableTempDir.path()) 0055 .setPermissions(QFile::ReadOwner | QFile::ReadUser | QFile::WriteOwner | QFile::WriteUser | QFile::ExeOwner | QFile::ExeUser)); 0056 } 0057 0058 // Before every test method, ensure the test file m_srcFile exists 0059 void init() 0060 { 0061 if (QFile::exists(m_srcFile)) { 0062 QVERIFY(QFileInfo(m_srcFile).isWritable()); 0063 } else { 0064 QFile srcFile(m_srcFile); 0065 QVERIFY2(srcFile.open(QFile::WriteOnly), qPrintable(srcFile.errorString())); 0066 srcFile.write("Hello world\n"); 0067 } 0068 QVERIFY(QFileInfo(m_srcFile).isWritable()); 0069 } 0070 0071 void shouldHaveParentWidget() 0072 { 0073 KFileCopyToMenu generator(&m_parentWidget); 0074 QCOMPARE(generator.parent(), &m_parentWidget); 0075 } 0076 0077 void shouldAddActions() 0078 { 0079 KFileCopyToMenu generator(&m_parentWidget); 0080 QMenu menu; 0081 generator.addActionsTo(&menu); 0082 QList<QUrl> urls; 0083 urls << QUrl::fromLocalFile(m_srcFile); 0084 generator.setUrls(urls); 0085 QCOMPARE(extractActionNames(menu), QStringList() << QStringLiteral("copyTo_submenu") << QStringLiteral("moveTo_submenu")); 0086 QAction *copyMenuAction = menu.actions().at(0); 0087 0088 // When 0089 menu.setActiveAction(copyMenuAction); 0090 menu.popup(QPoint(-100, -100)); 0091 0092 // Then 0093 const QStringList actionNames = extractActionNames(*copyMenuAction->menu()); 0094 QVERIFY(!actionNames.isEmpty()); 0095 QCOMPARE(actionNames.first(), QStringLiteral("home")); 0096 QVERIFY(actionNames.contains(QLatin1String("browse"))); 0097 QCOMPARE(actionNames.at(actionNames.count() - 2), m_nonWritableTempDir.path()); 0098 QCOMPARE(actionNames.last(), m_destDir); 0099 } 0100 0101 void shouldTryCopyingToRecentPath_data() 0102 { 0103 QTest::addColumn<int>("actionNumber"); // from the bottom of the menu, starting at 1; see the recentDirs list in initTestCase 0104 QTest::addColumn<int>("expectedErrorCode"); 0105 0106 QTest::newRow("working") << 1 << 0; // no error 0107 QTest::newRow("non_writable") << 2 << int(KIO::ERR_WRITE_ACCESS_DENIED); 0108 QTest::newRow("non_existing") << 3 << int(KIO::ERR_CANNOT_OPEN_FOR_WRITING); 0109 } 0110 0111 void shouldTryCopyingToRecentPath() 0112 { 0113 QFETCH(int, actionNumber); 0114 QFETCH(int, expectedErrorCode); 0115 0116 KFileCopyToMenu generator(&m_parentWidget); 0117 QMenu menu; 0118 QList<QUrl> urls; 0119 urls << QUrl::fromLocalFile(m_srcFile); 0120 generator.setUrls(urls); 0121 generator.addActionsTo(&menu); 0122 QAction *copyMenuAction = menu.actions().at(0); 0123 menu.setActiveAction(copyMenuAction); 0124 0125 menu.popup(QPoint(-100, -100)); 0126 const QList<QAction *> actions = copyMenuAction->menu()->actions(); 0127 if (m_lastActionCount == 0) { 0128 m_lastActionCount = actions.count(); 0129 } else { 0130 QCOMPARE(actions.count(), m_lastActionCount); // should be stable, i.e. selecting a recent dir shouldn't duplicate it 0131 } 0132 QAction *copyAction = actions.at(actions.count() - actionNumber); 0133 QSignalSpy spy(&generator, &KFileCopyToMenu::error); 0134 0135 // When 0136 copyAction->trigger(); 0137 0138 // Then 0139 QTRY_COMPARE(spy.count(), expectedErrorCode ? 1 : 0); 0140 if (expectedErrorCode) { 0141 QCOMPARE(spy.at(0).at(0).toInt(), expectedErrorCode); 0142 } else { 0143 QTRY_VERIFY(QFile::exists(m_destDir + QStringLiteral("/srcfile"))); 0144 } 0145 0146 if (actionNumber == 1) { // This part only makes sense if the copy is going to work 0147 QFile::remove(m_destDir + QStringLiteral("/srcfile")); 0148 // Remove the recent dirs entry for m_destDir from the config 0149 KConfigGroup group(KSharedConfig::openConfig(), "kuick-copy"); 0150 auto list = group.readEntry("Paths", QStringList{}); 0151 list.removeOne(m_destDir); 0152 group.writeEntry("Paths", list); 0153 group.sync(); 0154 // Triggering the action again, should insert a recent dirs corresponding 0155 // to m_destDir, which calls KFileCopyToMainMenu::copyOrMoveTo(), which 0156 // trims the recent dirs config to 10 urls, and _shouldn't_ crash 0157 copyAction->trigger(); 0158 0159 // Back to normal for the next tests to pass 0160 group.writeEntry("Paths", m_recentDirs); 0161 } 0162 } 0163 0164 private: 0165 static QStringList extractActionNames(const QMenu &menu) 0166 { 0167 QStringList ret; 0168 const QList<QAction *> actionsList = menu.actions(); 0169 for (const QAction *action : actionsList) { 0170 ret.append(action->objectName()); 0171 } 0172 return ret; 0173 } 0174 0175 QTemporaryDir m_tempDir; 0176 QString m_srcDir; 0177 QString m_srcFile; 0178 QTemporaryDir m_tempDestDir; 0179 QString m_destDir; 0180 QTemporaryDir m_nonWritableTempDir; 0181 QWidget m_parentWidget; 0182 QStringList m_recentDirs; 0183 int m_lastActionCount; 0184 }; 0185 0186 QTEST_MAIN(KFileCopyToMenuTest) 0187 0188 #include "kfilecopytomenutest.moc"