diff --git a/src/libs/clangsupport/connectionclient.cpp b/src/libs/clangsupport/connectionclient.cpp index 07754a9490a..ff841f33d02 100644 --- a/src/libs/clangsupport/connectionclient.cpp +++ b/src/libs/clangsupport/connectionclient.cpp @@ -36,6 +36,8 @@ #include #include +using namespace Utils; + namespace ClangBackEnd { ConnectionClient::ConnectionClient(const QString &connectionName) @@ -159,7 +161,7 @@ void ConnectionClient::restartProcessIfTimerIsNotResettedAndSocketIsEmpty() restartProcessAsynchronously(); } -void ConnectionClient::endProcess(QProcess *process) +void ConnectionClient::endProcess(QtcProcess *process) { if (isProcessRunning(process) && isConnected()) { sendEndMessage(); @@ -167,15 +169,15 @@ void ConnectionClient::endProcess(QProcess *process) } } -void ConnectionClient::terminateProcess(QProcess *process) +void ConnectionClient::terminateProcess(QtcProcess *process) { - if (!Utils::HostOsInfo::isWindowsHost() && isProcessRunning()) { + if (!HostOsInfo::isWindowsHost() && isProcessRunning()) { process->terminate(); process->waitForFinished(1000); } } -void ConnectionClient::killProcess(QProcess *process) +void ConnectionClient::killProcess(QtcProcess *process) { if (isProcessRunning(process)) { process->kill(); @@ -213,7 +215,7 @@ void ConnectionClient::resetTemporaryDirectory() m_processCreator.resetTemporaryDirectory(); } -void ConnectionClient::initializeProcess(QProcess *process) +void ConnectionClient::initializeProcess(QtcProcess *process) { connectStandardOutputAndError(process); @@ -299,7 +301,7 @@ bool ConnectionClient::waitForConnected() } -QProcess *ConnectionClient::processForTestOnly() +QtcProcess *ConnectionClient::processForTestOnly() { getProcessFromFuture(); @@ -311,15 +313,15 @@ QIODevice *ConnectionClient::ioDevice() return m_localSocket; } -bool ConnectionClient::isProcessRunning(QProcess *process) +bool ConnectionClient::isProcessRunning(QtcProcess *process) { return process && process->state() == QProcess::Running; } -void ConnectionClient::connectStandardOutputAndError(QProcess *process) const +void ConnectionClient::connectStandardOutputAndError(QtcProcess *process) const { - connect(process, &QProcess::readyReadStandardOutput, this, &ConnectionClient::printStandardOutput); - connect(process, &QProcess::readyReadStandardError, this, &ConnectionClient::printStandardError); + connect(process, &QtcProcess::readyReadStandardOutput, this, &ConnectionClient::printStandardOutput); + connect(process, &QtcProcess::readyReadStandardError, this, &ConnectionClient::printStandardError); } void ConnectionClient::connectLocalSocketError() const diff --git a/src/libs/clangsupport/connectionclient.h b/src/libs/clangsupport/connectionclient.h index 258bb323d13..aae1864ff5b 100644 --- a/src/libs/clangsupport/connectionclient.h +++ b/src/libs/clangsupport/connectionclient.h @@ -28,6 +28,7 @@ #include "clangcodemodelserverproxy.h" #include "lineprefixer.h" #include "processcreator.h" +#include "processhandle.h" #include #include @@ -37,9 +38,7 @@ #include #include -QT_BEGIN_NAMESPACE -class QProcess; -QT_END_NAMESPACE +namespace Utils { class QtcProcess; } class Utf8String; class Utf8StringVector; @@ -77,7 +76,7 @@ public: bool waitForEcho(); bool waitForConnected(); - QProcess *processForTestOnly(); + Utils::QtcProcess *processForTestOnly(); signals: void connectedToLocalSocket(); @@ -103,22 +102,22 @@ protected: virtual void newConnectedServer(QLocalSocket *localSocket) = 0; private: - static bool isProcessRunning(QProcess *process); + static bool isProcessRunning(Utils::QtcProcess *process); void finishProcess(QProcessUniquePointer &&process); - void endProcess(QProcess *process); - void terminateProcess(QProcess *process); - void killProcess(QProcess *process); + void endProcess(Utils::QtcProcess *process); + void terminateProcess(Utils::QtcProcess *process); + void killProcess(Utils::QtcProcess *process); void finishConnection(); void printLocalSocketError(QLocalSocket::LocalSocketError socketError); void printStandardOutput(); void printStandardError(); - void initializeProcess(QProcess *process); + void initializeProcess(Utils::QtcProcess *process); void resetTemporaryDirectory(); void connectLocalSocketDisconnected(); void disconnectLocalSocketDisconnected(); - void connectStandardOutputAndError(QProcess *process) const; + void connectStandardOutputAndError(Utils::QtcProcess *process) const; void connectLocalSocketError() const; void connectAliveTimer(); void connectNewConnection(); diff --git a/src/libs/clangsupport/processcreator.cpp b/src/libs/clangsupport/processcreator.cpp index ad0d4b78840..c0b9393607d 100644 --- a/src/libs/clangsupport/processcreator.cpp +++ b/src/libs/clangsupport/processcreator.cpp @@ -28,10 +28,15 @@ #include "processexception.h" #include "processstartedevent.h" +#include +#include + #include #include #include +using namespace Utils; + namespace ClangBackEnd { using namespace std::chrono_literals; @@ -56,7 +61,7 @@ void ProcessCreator::setArguments(const QStringList &arguments) m_arguments = arguments; } -void ProcessCreator::setEnvironment(const Utils::Environment &environment) +void ProcessCreator::setEnvironment(const Environment &environment) { m_environment = environment; } @@ -65,10 +70,11 @@ std::future ProcessCreator::createProcess() const { return std::async(std::launch::async, [&] { checkIfProcessPathExists(); - auto process = QProcessUniquePointer(new QProcess); - process->setProcessChannelMode(QProcess::QProcess::ForwardedChannels); - process->setProcessEnvironment(processEnvironment()); - process->start(m_processPath, m_arguments); + auto process = QProcessUniquePointer(new QtcProcess(ProcessMode::Writer)); + process->setProcessChannelMode(QProcess::ForwardedChannels); + process->setEnvironment(processEnvironment()); + process->setCommand(CommandLine(FilePath::fromString(m_processPath), m_arguments)); + process->start(); process->waitForStarted(5000); checkIfProcessWasStartingSuccessful(process.get()); @@ -95,13 +101,13 @@ void ProcessCreator::checkIfProcessPathExists() const } } -void ProcessCreator::checkIfProcessWasStartingSuccessful(QProcess *process) const +void ProcessCreator::checkIfProcessWasStartingSuccessful(QtcProcess *process) const { if (process->exitStatus() == QProcess::CrashExit || process->exitCode() != 0) dispatchProcessError(process); } -void ProcessCreator::dispatchProcessError(QProcess *process) const +void ProcessCreator::dispatchProcessError(QtcProcess *process) const { switch (process->error()) { case QProcess::UnknownError: { @@ -158,24 +164,24 @@ const QTemporaryDir &ProcessCreator::temporaryDirectory() const void ProcessCreator::resetTemporaryDirectory() { - m_temporaryDirectory = std::make_unique(m_temporaryDirectoryPattern); + m_temporaryDirectory = std::make_unique(m_temporaryDirectoryPattern); } -QProcessEnvironment ProcessCreator::processEnvironment() const +Environment ProcessCreator::processEnvironment() const { - auto processEnvironment = QProcessEnvironment::systemEnvironment(); + auto processEnvironment = Environment::systemEnvironment(); if (temporaryDirectory().isValid()) { const QString temporaryDirectoryPath = temporaryDirectory().path(); - processEnvironment.insert("TMPDIR", temporaryDirectoryPath); - processEnvironment.insert("TMP", temporaryDirectoryPath); - processEnvironment.insert("TEMP", temporaryDirectoryPath); + processEnvironment.appendOrSet("TMPDIR", temporaryDirectoryPath); + processEnvironment.appendOrSet("TMP", temporaryDirectoryPath); + processEnvironment.appendOrSet("TEMP", temporaryDirectoryPath); } - const Utils::Environment &env = m_environment; + const Environment &env = m_environment; for (auto it = env.constBegin(); it != env.constEnd(); ++it) { if (env.isEnabled(it)) - processEnvironment.insert(env.key(it), env.expandedValueForKey(env.key(it))); + processEnvironment.appendOrSet(env.key(it), env.expandedValueForKey(env.key(it))); } return processEnvironment; diff --git a/src/libs/clangsupport/processcreator.h b/src/libs/clangsupport/processcreator.h index 928857319b7..5fdb797e30f 100644 --- a/src/libs/clangsupport/processcreator.h +++ b/src/libs/clangsupport/processcreator.h @@ -39,9 +39,13 @@ QT_BEGIN_NAMESPACE class QTemporaryDir; -class QProcessEnvironment; QT_END_NAMESPACE +namespace Utils { +class Environment; +class QtcProcess; +} + namespace ClangBackEnd { class CLANGSUPPORT_EXPORT ProcessCreator @@ -62,12 +66,12 @@ public: private: void checkIfProcessPathExists() const; - void checkIfProcessWasStartingSuccessful(QProcess *process) const; - [[noreturn]] void dispatchProcessError(QProcess *process) const; + void checkIfProcessWasStartingSuccessful(Utils::QtcProcess *process) const; + [[noreturn]] void dispatchProcessError(Utils::QtcProcess *process) const; void postProcessStartedEvent() const; [[noreturn]] void throwProcessException(const QString &message) const; - QProcessEnvironment processEnvironment() const; + Utils::Environment processEnvironment() const; private: std::unique_ptr m_temporaryDirectory; diff --git a/src/libs/clangsupport/processhandle.h b/src/libs/clangsupport/processhandle.h index c19b7ee007b..3f7444499b8 100644 --- a/src/libs/clangsupport/processhandle.h +++ b/src/libs/clangsupport/processhandle.h @@ -25,7 +25,7 @@ #pragma once -#include +#include #include @@ -34,7 +34,7 @@ namespace ClangBackEnd { class QProcessUniquePointerDeleter { public: - void operator()(QProcess* process) + void operator()(Utils::QtcProcess* process) { process->kill(); process->waitForFinished(); @@ -42,6 +42,6 @@ public: } }; -using QProcessUniquePointer = std::unique_ptr; +using QProcessUniquePointer = std::unique_ptr; } // namespace ClangBackEnd diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt index c6e8a68bc51..6b74776a28e 100644 --- a/tests/unit/unittest/CMakeLists.txt +++ b/tests/unit/unittest/CMakeLists.txt @@ -23,6 +23,9 @@ elseif (MINGW) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj") endif() +file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") +file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}") + add_qtc_test(unittest GTEST INCLUDES BEFORE "../mockup" @@ -40,6 +43,7 @@ add_qtc_test(unittest GTEST QTC_RESOURCE_DIR="${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator" TESTDATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data" ECHOSERVER="$/echo" + TEST_RELATIVE_LIBEXEC_PATH="${TEST_RELATIVE_LIBEXEC_PATH}" SOURCES abstractviewmock.h clientserverinprocess-test.cpp diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 733e311f948..3369cdfd693 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -56,6 +56,10 @@ QMAKE_LFLAGS += /INCREMENTAL } +TEST_RELATIVE_LIBEXEC_PATH = $$relative_path($$IDE_LIBEXEC_PATH, $$OUT_PWD) +win32:TEST_RELATIVE_LIBEXEC_PATH=../$$TEST_RELATIVE_LIBEXEC_PATH +DEFINES += 'TEST_RELATIVE_LIBEXEC_PATH="\\\"$$TEST_RELATIVE_LIBEXEC_PATH\\\""' + SOURCES += \ clientserverinprocess-test.cpp \ clientserveroutsideprocess-test.cpp \ diff --git a/tests/unit/unittest/unittest.qbs b/tests/unit/unittest/unittest.qbs index 563bf371c76..686f167029b 100644 --- a/tests/unit/unittest/unittest.qbs +++ b/tests/unit/unittest/unittest.qbs @@ -98,6 +98,10 @@ Project { if (libclang.present) { defines.push("CLANG_UNIT_TESTS"); } + var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, + qtc.ide_libexec_path); + var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath); + defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"'); return defines; } cpp.cxxFlags: { diff --git a/tests/unit/unittest/unittests-main.cpp b/tests/unit/unittest/unittests-main.cpp index 5f5146de794..532d4961f5b 100644 --- a/tests/unit/unittest/unittests-main.cpp +++ b/tests/unit/unittest/unittests-main.cpp @@ -29,10 +29,12 @@ #include #include +#include #include #include #include +#include #ifdef WITH_BENCHMARKS #include @@ -58,7 +60,9 @@ int main(int argc, char *argv[]) Sqlite::Database::activateLogging(); QGuiApplication application(argc, argv); - + Utils::LauncherInterface::startLauncher(qApp->applicationDirPath() + '/' + + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH)); + auto cleanup = qScopeGuard([] { Utils::LauncherInterface::stopLauncher(); }); testing::InitGoogleTest(&argc, argv); #ifdef WITH_BENCHMARKS benchmark::Initialize(&argc, argv);