File indexing completed on 2024-04-28 05:50:34
0001 /* 0002 SPDX-FileCopyrightText: 2008 Robert Knight <robertknight@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 // Own 0008 #include "PartTest.h" 0009 0010 // Qt 0011 #include <QDialog> 0012 #include <QFileInfo> 0013 #include <QLabel> 0014 #include <QTimer> 0015 #include <QVBoxLayout> 0016 // KDE 0017 #include <KPluginFactory> 0018 #include <KPtyDevice> 0019 #include <KPtyProcess> 0020 #include <QTest> 0021 0022 // Konsole 0023 #include "../Pty.h" 0024 0025 using namespace Konsole; 0026 0027 void PartTest::initTestCase() 0028 { 0029 /* Try to test against build konsolepart, so move directory containing 0030 executable to front of libraryPaths. KPluginLoader should find the 0031 part first in the build dir over the system installed ones. 0032 I believe the CI installs first and then runs the test so the other 0033 paths can not be removed. 0034 */ 0035 const auto libraryPaths = QCoreApplication::libraryPaths(); 0036 auto buildPath = libraryPaths.last(); 0037 QCoreApplication::removeLibraryPath(buildPath); 0038 // konsolepart.so is in ../autotests/ 0039 if (buildPath.endsWith(QStringLiteral("/autotests"))) { 0040 buildPath.chop(10); 0041 } 0042 QCoreApplication::addLibraryPath(buildPath); 0043 } 0044 0045 void PartTest::testFdShell() 0046 { 0047 // Maybe https://bugreports.qt.io/browse/QTBUG-82351 ??? 0048 QSKIP("Skipping on CI suse_tumbelweed_qt64", SkipSingle); 0049 return; 0050 0051 testFd(true); 0052 } 0053 0054 void PartTest::testFdStandalone() 0055 { 0056 testFd(false); 0057 } 0058 0059 void PartTest::testFd(bool runShell) 0060 { 0061 // find ping 0062 QStringList pingList; 0063 QFileInfo info; 0064 QString pingExe; 0065 pingList << QStringLiteral("/bin/ping") << QStringLiteral("/sbin/ping"); 0066 for (int i = 0; i < pingList.size(); ++i) { 0067 info.setFile(pingList.at(i)); 0068 if (info.exists() && info.isExecutable()) { 0069 pingExe = pingList.at(i); 0070 } 0071 } 0072 0073 if (pingExe.isEmpty()) { 0074 QSKIP("ping command not found."); 0075 return; 0076 } 0077 0078 // create a Konsole part and attempt to connect to it 0079 KParts::Part *terminalPart = createPart(); 0080 if (terminalPart == nullptr) { // not found 0081 QFAIL("konsolepart not found."); 0082 return; 0083 } 0084 0085 // start a pty process 0086 KPtyProcess ptyProcess; 0087 ptyProcess.setProgram(pingExe, QStringList() << QStringLiteral("localhost")); 0088 ptyProcess.setPtyChannels(KPtyProcess::AllChannels); 0089 ptyProcess.start(); 0090 QVERIFY(ptyProcess.waitForStarted()); 0091 0092 int fd = ptyProcess.pty()->masterFd(); 0093 0094 // test that the 2nd argument of openTeletype is optional, 0095 // to run without shell 0096 if (runShell) { 0097 // connect to an existing pty 0098 bool result = QMetaObject::invokeMethod(terminalPart, "openTeletype", Qt::DirectConnection, Q_ARG(int, fd)); 0099 QVERIFY(result); 0100 } else { 0101 // test the optional 2nd argument of openTeletype, to run without shell 0102 bool result = QMetaObject::invokeMethod(terminalPart, "openTeletype", Qt::DirectConnection, Q_ARG(int, fd), Q_ARG(bool, false)); 0103 QVERIFY(result); 0104 } 0105 0106 // suspend the KPtyDevice so that the embedded terminal gets a chance to 0107 // read from the pty. Otherwise the KPtyDevice will simply read everything 0108 // as soon as it becomes available and the terminal will not display any output 0109 ptyProcess.pty()->setSuspended(true); 0110 0111 QPointer<QDialog> dialog = new QDialog(); 0112 auto layout = new QVBoxLayout(dialog.data()); 0113 auto explanation = runShell ? QStringLiteral("Output of 'ping localhost' should appear in a terminal below for 5 seconds") 0114 : QStringLiteral("Output of 'ping localhost' should appear standalone below for 5 seconds"); 0115 layout->addWidget(new QLabel(explanation)); 0116 layout->addWidget(terminalPart->widget()); 0117 QTimer::singleShot(5000, dialog.data(), &QDialog::close); 0118 dialog.data()->exec(); 0119 0120 delete terminalPart; 0121 delete dialog.data(); 0122 ptyProcess.kill(); 0123 ptyProcess.waitForFinished(1000); 0124 } 0125 0126 KParts::Part *PartTest::createPart() 0127 { 0128 const KPluginMetaData metaData(QStringLiteral("konsolepart")); 0129 Q_ASSERT(metaData.isValid()); 0130 0131 KPluginFactory::Result<KParts::Part> result = KPluginFactory::instantiatePlugin<KParts::Part>(metaData, this); 0132 Q_ASSERT(result); 0133 0134 return result.plugin; 0135 } 0136 0137 QTEST_MAIN(PartTest) 0138 0139 #include "moc_PartTest.cpp"