mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00

much simpler and easier to maintain, also it will be proper D-Bus service now with no sockets, process title hack and whatnot. KCrash and startkde script (in kde-workspace repo) have to be adjusted for it tho note that the internal KIO scheduler already has the functionality to put slaves on hold but now they will be started as detached process. eventually they may become plugins (they are loaded as such by kioslave program) without event loop dispatcher fixes application startup notification (ASN) and cleanup issues Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
266 lines
11 KiB
C++
266 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
|
|
* Copyright (C) 2007, 2009 David Faure <faure@kde.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "krununittest.h"
|
|
#include "moc_krununittest.cpp"
|
|
#include <qtest_kde.h>
|
|
QTEST_KDEMAIN( KRunUnitTest, NoGUI )
|
|
|
|
#include "krun.h"
|
|
#include <kshell.h>
|
|
#include <kservice.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kconfiggroup.h>
|
|
#include <kprocess.h>
|
|
#include "kiotesthelper.h" // createTestFile etc.
|
|
|
|
void KRunUnitTest::initTestCase()
|
|
{
|
|
// testProcessDesktopExec works only if your terminal application is set to "x-term"
|
|
KConfigGroup cg(KGlobal::config(), "General");
|
|
cg.writeEntry("TerminalApplication", "x-term");
|
|
|
|
// Determine the full path of sh - this is needed to make testProcessDesktopExecNoFile()
|
|
// pass on systems where KStandardDirs::findExe("sh") is not "/bin/sh".
|
|
m_sh = KStandardDirs::findExe("sh");
|
|
if (m_sh.isEmpty()) m_sh = "/bin/sh";
|
|
}
|
|
|
|
void KRunUnitTest::testBinaryName_data()
|
|
{
|
|
QTest::addColumn<QString>("execLine");
|
|
QTest::addColumn<bool>("removePath");
|
|
QTest::addColumn<QString>("expected");
|
|
|
|
QTest::newRow("/usr/bin/ls true") << "/usr/bin/ls" << true << "ls";
|
|
QTest::newRow("/usr/bin/ls false") << "/usr/bin/ls" << false << "/usr/bin/ls";
|
|
QTest::newRow("/path/to/wine \"long argument with path\"") << "/path/to/wine \"long argument with path\"" << true << "wine";
|
|
QTest::newRow("/path/with/a/sp\\ ace/exe arg1 arg2") << "/path/with/a/sp\\ ace/exe arg1 arg2" << true << "exe";
|
|
QTest::newRow("\"progname\" \"arg1\"") << "\"progname\" \"arg1\"" << true << "progname";
|
|
QTest::newRow("'quoted' \"arg1\"") << "'quoted' \"arg1\"" << true << "quoted";
|
|
QTest::newRow(" 'leading space' arg1") << " 'leading space' arg1" << true << "leading space";
|
|
}
|
|
|
|
void KRunUnitTest::testBinaryName()
|
|
{
|
|
QFETCH(QString, execLine);
|
|
QFETCH(bool, removePath);
|
|
QFETCH(QString, expected);
|
|
QCOMPARE(KRun::binaryName(execLine, removePath), expected);
|
|
}
|
|
|
|
//static const char *bt(bool tr) { return tr?"true":"false"; }
|
|
static void checkPDE(const char* exec, const char* term, const char* sus,
|
|
const KUrl::List &urls, bool tf, const QString& b)
|
|
{
|
|
QFile out( "kruntest.desktop" );
|
|
if ( !out.open( QIODevice::WriteOnly ) )
|
|
abort();
|
|
QByteArray str ( "[Desktop Entry]\n"
|
|
"Type=Application\n"
|
|
"Name=just_a_test\n"
|
|
"Icon=~/icon.png\n");
|
|
str += QByteArray(exec) + '\n';
|
|
str += QByteArray(term) + '\n';
|
|
str += QByteArray(sus) + '\n';
|
|
out.write( str );
|
|
out.close();
|
|
|
|
KService service(QDir::currentPath() + "/kruntest.desktop");
|
|
/*qDebug() << QString().sprintf(
|
|
"processDesktopExec( "
|
|
"service = {\nexec = %s\nterminal = %s, terminalOptions = %s\nsubstituteUid = %s, user = %s },"
|
|
"\nURLs = { %s },\ntemp_files = %s )",
|
|
service.exec().toLatin1().constData(), bt(service.terminal()), service.terminalOptions().toLatin1().constData(), bt(service.substituteUid()), service.username().toLatin1().constData(),
|
|
KShell::joinArgs(urls.toStringList()).toLatin1().constData(), bt(tf));
|
|
*/
|
|
QCOMPARE(KShell::joinArgs(KRun::processDesktopExec(service,urls,tf)), b);
|
|
|
|
QFile::remove("kruntest.desktop");
|
|
}
|
|
|
|
void KRunUnitTest::testProcessDesktopExec()
|
|
{
|
|
KUrl::List l0;
|
|
static const char
|
|
* const execs[] = { "Exec=date -u", "Exec=echo $PWD" },
|
|
* const terms[] = { "Terminal=false", "Terminal=true\nTerminalOptions=-T \"%f - %c\"" },
|
|
* const sus[] = { "X-KDE-SubstituteUID=false", "X-KDE-SubstituteUID=true\nX-KDE-Username=sprallo" },
|
|
* const rslts[] = {
|
|
"/bin/date -u", // 0
|
|
"/bin/sh -c 'echo $PWD '", // 1
|
|
"x-term -T ' - just_a_test' -e /bin/date -u", // 2
|
|
"x-term -T ' - just_a_test' -e /bin/sh -c 'echo $PWD '", // 3
|
|
/* kdesudo */ " -u sprallo -c '/bin/date -u'", // 4
|
|
/* kdesudo */ " -u sprallo -c '/bin/sh -c '\\''echo $PWD '\\'''", // 5
|
|
"x-term -T ' - just_a_test' -e su sprallo -c '/bin/date -u'", // 6
|
|
"x-term -T ' - just_a_test' -e su sprallo -c '/bin/sh -c '\\''echo $PWD '\\'''", // 7
|
|
};
|
|
|
|
// Find out the full path of the shell which will be used to execute shell commands
|
|
KProcess process;
|
|
process.setShellCommand("");
|
|
const QString shellPath = process.program().at(0);
|
|
|
|
// Arch moved /bin/date to /usr/bin/date...
|
|
const QString datePath = KStandardDirs::findExe("date");
|
|
|
|
for (int su = 0; su < 2; su++)
|
|
for (int te = 0; te < 2; te++)
|
|
for (int ex = 0; ex < 2; ex++) {
|
|
int pt = ex+te*2+su*4;
|
|
QString exe;
|
|
if (pt == 4 || pt == 5) {
|
|
exe = KStandardDirs::findExe("kdesudo");
|
|
if (exe.isEmpty()) {
|
|
qWarning() << "kdesudo not found, skipping test";
|
|
continue;
|
|
}
|
|
}
|
|
const QString result = QString::fromLatin1(rslts[pt])
|
|
.replace("/bin/sh", shellPath)
|
|
.replace("/bin/date", datePath);
|
|
checkPDE( execs[ex], terms[te], sus[su], l0, false, exe + result);
|
|
}
|
|
}
|
|
|
|
void KRunUnitTest::testProcessDesktopExecNoFile_data()
|
|
{
|
|
QTest::addColumn<QString>("execLine");
|
|
QTest::addColumn<KUrl::List>("urls");
|
|
QTest::addColumn<bool>("tempfiles");
|
|
QTest::addColumn<QString>("expected");
|
|
|
|
KUrl::List l0;
|
|
KUrl::List l1; l1 << KUrl( "file:/tmp" );
|
|
KUrl::List l2; l2 << KUrl( "http://localhost/foo" );
|
|
KUrl::List l3; l3 << KUrl( "file:/local/file" ) << KUrl( "http://remotehost.org/bar" );
|
|
KUrl::List l4; l4 << KUrl( "http://login:password@www.kde.org" );
|
|
|
|
// A real-world use case would be kate.
|
|
// But I picked klauncher4 since it's installed by kdelibs
|
|
QString klauncher = KStandardDirs::findExe("klauncher4");
|
|
if (klauncher.isEmpty()) klauncher = "klauncher4";
|
|
|
|
QString kioexec = KStandardDirs::findExe("kioexec");
|
|
if (kioexec.isEmpty())
|
|
QSKIP("kioexec not found, kdebase needed", SkipAll);
|
|
|
|
QString kmailservice = KStandardDirs::findExe("kmailservice");
|
|
if (kmailservice.isEmpty()) kmailservice = "kmailservice";
|
|
if (!klauncher.isEmpty()) {
|
|
QVERIFY(!kmailservice.isEmpty());
|
|
}
|
|
|
|
// NOTE: using QString() for concats to avoid QStringBuilder metatype, which is not valid
|
|
QTest::newRow("%U l0") << "klauncher4 %U" << l0 << false << klauncher;
|
|
QTest::newRow("%U l1") << "klauncher4 %U" << l1 << false << QString(klauncher + " /tmp");
|
|
QTest::newRow("%U l2") << "klauncher4 %U" << l2 << false << QString(klauncher + " http://localhost/foo");
|
|
QTest::newRow("%U l3") << "klauncher4 %U" << l3 << false << QString(klauncher + " /local/file http://remotehost.org/bar");
|
|
|
|
//QTest::newRow("%u l0") << "klauncher4 %u" << l0 << false << klauncher; // gives runtime warning
|
|
QTest::newRow("%u l1") << "klauncher4 %u" << l1 << false << QString(klauncher + " /tmp");
|
|
QTest::newRow("%u l2") << "klauncher4 %u" << l2 << false << QString(klauncher + " http://localhost/foo");
|
|
//QTest::newRow("%u l3") << "klauncher4 %u" << l3 << false << klauncher; // gives runtime warning
|
|
|
|
QTest::newRow("%F l0") << "klauncher4 %F" << l0 << false << klauncher;
|
|
QTest::newRow("%F l1") << "klauncher4 %F" << l1 << false << QString(klauncher + " /tmp");
|
|
QTest::newRow("%F l2") << "klauncher4 %F" << l2 << false << QString(kioexec + " 'klauncher4 %F' http://localhost/foo");
|
|
QTest::newRow("%F l3") << "klauncher4 %F" << l3 << false << QString(kioexec + " 'klauncher4 %F' file:///local/file http://remotehost.org/bar");
|
|
|
|
QTest::newRow("%F l1 tempfile") << "klauncher4 %F" << l1 << true << QString(kioexec + " --tempfiles 'klauncher4 %F' file:///tmp");
|
|
|
|
QTest::newRow("sh -c klauncher4 %F") << "sh -c \"klauncher4 \"'\\\"'\"%F\"'\\\"'"
|
|
<< l1 << false << QString(m_sh + " -c 'klauncher4 \\\"/tmp\\\"'");
|
|
|
|
QTest::newRow("kmailservice %u l1") << "kmailservice %u" << l1 << false << QString(kmailservice + " /tmp");
|
|
QTest::newRow("kmailservice %u l4") << "kmailservice %u" << l4 << false << QString(kmailservice + " http://login:password@www.kde.org");
|
|
}
|
|
|
|
void KRunUnitTest::testProcessDesktopExecNoFile()
|
|
{
|
|
QFETCH(QString, execLine);
|
|
KService service("dummy", execLine, "app");
|
|
QFETCH(KUrl::List, urls);
|
|
QFETCH(bool, tempfiles);
|
|
QFETCH(QString, expected);
|
|
QCOMPARE(KShell::joinArgs(KRun::processDesktopExec(service,urls,tempfiles)), expected);
|
|
}
|
|
|
|
class KRunImpl : public KRun
|
|
{
|
|
public:
|
|
KRunImpl(const KUrl& url, bool isLocalFile = false)
|
|
: KRun(url, 0, 0, isLocalFile, false) {}
|
|
|
|
void foundMimeType(const QString& type) final {
|
|
m_mimeType = type;
|
|
// don't call KRun::foundMimeType, we don't want to start an app ;-)
|
|
setFinished(true);
|
|
}
|
|
|
|
void error(const QString& message) final {
|
|
// don't show message box, this is unit test
|
|
Q_UNUSED(message);
|
|
}
|
|
|
|
QString mimeTypeFound() const { return m_mimeType; }
|
|
|
|
private:
|
|
QString m_mimeType;
|
|
};
|
|
|
|
void KRunUnitTest::testMimeTypeFile()
|
|
{
|
|
const QString filePath = homeTmpDir() + "file";
|
|
createTestFile(filePath, true);
|
|
KRunImpl* krun = new KRunImpl(filePath, true);
|
|
QTest::kWaitForSignal(krun, SIGNAL(finished()), 1000);
|
|
QCOMPARE(krun->mimeTypeFound(), QString::fromLatin1("text/plain"));
|
|
}
|
|
|
|
void KRunUnitTest::testMimeTypeDirectory()
|
|
{
|
|
const QString dir = homeTmpDir() + "dir";
|
|
createTestDirectory(dir);
|
|
KRunImpl* krun = new KRunImpl(dir, true);
|
|
QTest::kWaitForSignal(krun, SIGNAL(finished()), 1000);
|
|
QCOMPARE(krun->mimeTypeFound(), QString::fromLatin1("inode/directory"));
|
|
}
|
|
|
|
void KRunUnitTest::testMimeTypeBrokenLink()
|
|
{
|
|
const QString dir = homeTmpDir() + "dir";
|
|
createTestDirectory(dir);
|
|
KRunImpl* krun = new KRunImpl(KUrl(dir + "/testlink"), true);
|
|
QSignalSpy spyError(krun, SIGNAL(error()));
|
|
QTest::kWaitForSignal(krun, SIGNAL(finished()), 1000);
|
|
QVERIFY(krun->mimeTypeFound().isEmpty());
|
|
QCOMPARE(spyError.count(), 1);
|
|
}
|
|
|
|
void KRunUnitTest::testMimeTypeDoesNotExist()
|
|
{
|
|
KRunImpl* krun = new KRunImpl(KUrl("/does/not/exist"));
|
|
QSignalSpy spyError(krun, SIGNAL(error()));
|
|
QTest::kWaitForSignal(krun, SIGNAL(finished()), 1000);
|
|
QVERIFY(krun->mimeTypeFound().isEmpty());
|
|
QCOMPARE(spyError.count(), 1);
|
|
}
|