forked from qt-creator/qt-creator
Clang: Add Process Generator
So far we only compiled the precompiled headers only sequentially. The process generator is creating, managing a queue of processes to compile the PCHs parallel. Change-Id: I8075def4ef9e6b0191bbd51b3631d1c51ec7b361 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include <connectionserver.h>
|
||||
#include <environment.h>
|
||||
#include <pchcreator.h>
|
||||
#include <pchgenerator.h>
|
||||
#include <pchmanagerserver.h>
|
||||
#include <pchmanagerclientproxy.h>
|
||||
#include <projectparts.h>
|
||||
@@ -36,12 +37,16 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QLoggingCategory>
|
||||
#include <QProcess>
|
||||
#include <QTemporaryDir>
|
||||
#include <QTimer>
|
||||
|
||||
#include <thread>
|
||||
|
||||
using ClangBackEnd::ClangPathWatcher;
|
||||
using ClangBackEnd::ConnectionServer;
|
||||
using ClangBackEnd::PchCreator;
|
||||
using ClangBackEnd::PchGenerator;
|
||||
using ClangBackEnd::PchManagerClientProxy;
|
||||
using ClangBackEnd::PchManagerServer;
|
||||
using ClangBackEnd::ProjectParts;
|
||||
@@ -60,6 +65,11 @@ public:
|
||||
return QString(CLANG_COMPILER_PATH);
|
||||
}
|
||||
|
||||
uint hardwareConcurrency() const
|
||||
{
|
||||
return std::thread::hardware_concurrency();
|
||||
}
|
||||
|
||||
private:
|
||||
QTemporaryDir temporaryDirectory;
|
||||
};
|
||||
@@ -96,13 +106,17 @@ int main(int argc, char *argv[])
|
||||
StringCache<Utils::SmallString> filePathCache;
|
||||
ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher(filePathCache);
|
||||
ApplicationEnvironment environment;
|
||||
PchGenerator<QProcess> pchGenerator(environment);
|
||||
PchCreator pchCreator(environment, filePathCache);
|
||||
pchCreator.setGenerator(&pchGenerator);
|
||||
ProjectParts projectParts;
|
||||
PchManagerServer clangPchManagerServer(filePathCache,
|
||||
includeWatcher,
|
||||
pchCreator,
|
||||
projectParts);
|
||||
includeWatcher.setNotifier(&clangPchManagerServer);
|
||||
pchGenerator.setNotifier(&clangPchManagerServer);
|
||||
|
||||
ConnectionServer<PchManagerServer, PchManagerClientProxy> connectionServer(connection);
|
||||
connectionServer.start();
|
||||
connectionServer.setServer(&clangPchManagerServer);
|
||||
|
||||
@@ -10,7 +10,9 @@ SOURCES += \
|
||||
$$PWD/pchcreatorinterface.cpp \
|
||||
$$PWD/clangpathwatcherinterface.cpp \
|
||||
$$PWD/projectpartsinterface.cpp \
|
||||
$$PWD/clangpathwatchernotifier.cpp
|
||||
$$PWD/clangpathwatchernotifier.cpp \
|
||||
$$PWD/pchgeneratornotifierinterface.cpp \
|
||||
$$PWD/pchgeneratorinterface.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/clangpchmanagerbackend_global.h \
|
||||
@@ -30,4 +32,7 @@ HEADERS += \
|
||||
$$PWD/clangpathwatcherinterface.h \
|
||||
$$PWD/projectpartsinterface.h \
|
||||
$$PWD/clangpathwatchernotifier.h \
|
||||
$$PWD/changedfilepathcompressor.h
|
||||
$$PWD/changedfilepathcompressor.h \
|
||||
$$PWD/pchgenerator.h \
|
||||
$$PWD/pchgeneratornotifierinterface.h \
|
||||
$$PWD/pchgeneratorinterface.h
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
llvm::StringRef /*relativePath*/,
|
||||
const clang::Module */*imported*/) override
|
||||
{
|
||||
if (file) {
|
||||
auto fileUID = file->getUID();
|
||||
|
||||
flagIncludeAlreadyRead(file);
|
||||
@@ -77,6 +78,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isNotInExcludedIncludeUID(uint uid) const
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@ class Environment
|
||||
public:
|
||||
virtual QString pchBuildDirectory() const = 0;
|
||||
virtual QString clangCompilerPath() const = 0;
|
||||
virtual uint hardwareConcurrency() const = 0;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
@@ -45,10 +44,12 @@ PchCreator::PchCreator(Environment &environment, StringCache<Utils::SmallString>
|
||||
|
||||
PchCreator::PchCreator(V2::ProjectPartContainers &&projectsParts,
|
||||
Environment &environment,
|
||||
StringCache<Utils::SmallString> &filePathCache)
|
||||
StringCache<Utils::SmallString> &filePathCache,
|
||||
PchGeneratorInterface *pchGenerator)
|
||||
: m_projectParts(std::move(projectsParts)),
|
||||
m_environment(environment),
|
||||
m_filePathCache(filePathCache)
|
||||
m_filePathCache(filePathCache),
|
||||
m_pchGenerator(pchGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -258,23 +259,17 @@ std::unique_ptr<QFile> PchCreator::generateGlobalPchHeaderFile()
|
||||
generateGlobalPchHeaderFileContent());
|
||||
}
|
||||
|
||||
void PchCreator::generatePch(const Utils::SmallStringVector &clangCompilerArguments)
|
||||
void PchCreator::generatePch(Utils::SmallStringVector &&compilerArguments,
|
||||
ProjectPartPch &&projectPartPch)
|
||||
{
|
||||
QProcess process;
|
||||
process.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
|
||||
process.start(m_environment.clangCompilerPath(),
|
||||
convertToQStringList(clangCompilerArguments));
|
||||
process.waitForFinished(100000);
|
||||
|
||||
checkIfProcessHasError(process);
|
||||
m_pchGenerator->startTask(std::move(compilerArguments), std::move(projectPartPch));
|
||||
}
|
||||
|
||||
void PchCreator::generateGlobalPch()
|
||||
{
|
||||
generateGlobalPchHeaderFile();
|
||||
|
||||
generatePch(generateGlobalClangCompilerArguments());
|
||||
generatePch(generateGlobalClangCompilerArguments(), ProjectPartPch());
|
||||
}
|
||||
|
||||
QStringList PchCreator::convertToQStringList(const Utils::SmallStringVector &compilerArguments)
|
||||
@@ -310,14 +305,6 @@ QByteArray PchCreator::globalProjectHash() const
|
||||
return result.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
}
|
||||
|
||||
void PchCreator::checkIfProcessHasError(const QProcess &process)
|
||||
{
|
||||
if (process.exitCode()) {
|
||||
const std::string errorString = process.errorString().toStdString();
|
||||
throw PchNotCreatedError(errorString);
|
||||
}
|
||||
}
|
||||
|
||||
Utils::SmallString PchCreator::generateGlobalPchFilePathWithoutExtension() const
|
||||
{
|
||||
QByteArray fileName = m_environment.pchBuildDirectory().toUtf8();
|
||||
@@ -449,27 +436,25 @@ Utils::SmallStringVector PchCreator::generateProjectPartClangCompilerArguments(
|
||||
return compilerArguments;
|
||||
}
|
||||
|
||||
std::pair<ProjectPartPch, IdPaths> PchCreator::generateProjectPartPch(
|
||||
const V2::ProjectPartContainer &projectPart)
|
||||
IdPaths PchCreator::generateProjectPartPch(const V2::ProjectPartContainer &projectPart)
|
||||
{
|
||||
auto includes = generateProjectPartPchIncludes(projectPart);
|
||||
auto content = generatePchIncludeFileContent(includes);
|
||||
auto pchIncludeFilePath = generateProjectPathPchHeaderFilePath(projectPart);
|
||||
auto pchFilePath = generateProjectPartPchFilePath(projectPart);
|
||||
auto file = generatePchHeaderFile(pchIncludeFilePath, content);
|
||||
generatePchHeaderFile(pchIncludeFilePath, content);
|
||||
|
||||
generatePch(generateProjectPartClangCompilerArguments(projectPart));
|
||||
generatePch(generateProjectPartClangCompilerArguments(projectPart),
|
||||
{projectPart.projectPartId().clone(), std::move(pchFilePath)});
|
||||
|
||||
return {{projectPart.projectPartId().clone(), std::move(pchFilePath)},
|
||||
{projectPart.projectPartId().clone(), includes}};
|
||||
return {projectPart.projectPartId().clone(), std::move(includes)};
|
||||
}
|
||||
|
||||
void PchCreator::generatePchs()
|
||||
{
|
||||
for (const V2::ProjectPartContainer &projectPart : m_projectParts) {
|
||||
auto projectInfos = generateProjectPartPch(projectPart);
|
||||
m_projectPartPchs.push_back(projectInfos.first);
|
||||
m_projectsIncludeIds.push_back(projectInfos.second);
|
||||
auto includePaths = generateProjectPartPch(projectPart);
|
||||
m_projectsIncludeIds.push_back(std::move(includePaths));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,16 +465,16 @@ void PchCreator::generatePchs(V2::ProjectPartContainers &&projectsParts)
|
||||
generatePchs();
|
||||
}
|
||||
|
||||
std::vector<ProjectPartPch> PchCreator::takeProjectPartPchs()
|
||||
{
|
||||
return std::move(m_projectPartPchs);
|
||||
}
|
||||
|
||||
std::vector<IdPaths> PchCreator::takeProjectsIncludes()
|
||||
{
|
||||
return std::move(m_projectsIncludeIds);
|
||||
}
|
||||
|
||||
void PchCreator::setGenerator(PchGeneratorInterface *pchGenerator)
|
||||
{
|
||||
m_pchGenerator = pchGenerator;
|
||||
}
|
||||
|
||||
std::unique_ptr<QFile> PchCreator::generatePchHeaderFile(
|
||||
const Utils::SmallString &filePath,
|
||||
const Utils::SmallString &content)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "pchcreatorinterface.h"
|
||||
|
||||
#include "pchgeneratorinterface.h"
|
||||
#include "stringcache.h"
|
||||
#include "idpaths.h"
|
||||
|
||||
@@ -50,12 +51,14 @@ public:
|
||||
StringCache<Utils::SmallString> &filePathCache);
|
||||
PchCreator(V2::ProjectPartContainers &&projectsParts,
|
||||
Environment &environment,
|
||||
StringCache<Utils::SmallString> &filePathCache);
|
||||
StringCache<Utils::SmallString> &filePathCache,
|
||||
PchGeneratorInterface *pchGenerator);
|
||||
|
||||
void generatePchs(V2::ProjectPartContainers &&projectsParts) override;
|
||||
std::vector<ProjectPartPch> takeProjectPartPchs() override;
|
||||
std::vector<IdPaths> takeProjectsIncludes() override;
|
||||
|
||||
void setGenerator(PchGeneratorInterface *pchGenerator);
|
||||
|
||||
unitttest_public:
|
||||
Utils::SmallStringVector generateGlobalHeaderPaths() const;
|
||||
Utils::SmallStringVector generateGlobalSourcePaths() const;
|
||||
@@ -70,7 +73,8 @@ unitttest_public:
|
||||
Utils::SmallString generatePchIncludeFileContent(const std::vector<uint> &includeIds) const;
|
||||
Utils::SmallString generateGlobalPchHeaderFileContent() const;
|
||||
std::unique_ptr<QFile> generateGlobalPchHeaderFile();
|
||||
void generatePch(const Utils::SmallStringVector &commandLineArguments);
|
||||
void generatePch(Utils::SmallStringVector &&commandLineArguments,
|
||||
ProjectPartPch &&projectPartPch);
|
||||
void generateGlobalPch();
|
||||
|
||||
Utils::SmallString globalPchContent() const;
|
||||
@@ -97,7 +101,7 @@ unitttest_public:
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
Utils::SmallStringVector generateProjectPartClangCompilerArguments(
|
||||
const V2::ProjectPartContainer &projectPart) const;
|
||||
std::pair<ProjectPartPch, IdPaths> generateProjectPartPch(
|
||||
IdPaths generateProjectPartPch(
|
||||
const V2::ProjectPartContainer &projectPart);
|
||||
static std::unique_ptr<QFile> generatePchHeaderFile(
|
||||
const Utils::SmallString &filePath,
|
||||
@@ -108,7 +112,6 @@ unitttest_public:
|
||||
private:
|
||||
static QByteArray projectPartHash(const V2::ProjectPartContainer &projectPart);
|
||||
QByteArray globalProjectHash() const;
|
||||
static void checkIfProcessHasError(const QProcess &process);
|
||||
|
||||
private:
|
||||
V2::ProjectPartContainers m_projectParts;
|
||||
@@ -116,6 +119,7 @@ private:
|
||||
std::vector<IdPaths> m_projectsIncludeIds;
|
||||
Environment &m_environment;
|
||||
StringCache<Utils::SmallString> &m_filePathCache;
|
||||
PchGeneratorInterface *m_pchGenerator = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
@@ -38,7 +38,6 @@ public:
|
||||
virtual ~PchCreatorInterface();
|
||||
|
||||
virtual void generatePchs(V2::ProjectPartContainers &&projectsParts) = 0;
|
||||
virtual std::vector<ProjectPartPch> takeProjectPartPchs() = 0;
|
||||
virtual std::vector<IdPaths> takeProjectsIncludes() = 0;
|
||||
};
|
||||
|
||||
|
||||
165
src/tools/clangpchmanagerbackend/source/pchgenerator.h
Normal file
165
src/tools/clangpchmanagerbackend/source/pchgenerator.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "environment.h"
|
||||
#include "pchgeneratorinterface.h"
|
||||
#include "pchgeneratornotifierinterface.h"
|
||||
|
||||
#include <projectpartpch.h>
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
#include <queue>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
template <typename Process>
|
||||
class PchGenerator final : public PchGeneratorInterface
|
||||
{
|
||||
public:
|
||||
PchGenerator(Environment &environment,
|
||||
PchGeneratorNotifierInterface *notifier=nullptr)
|
||||
: m_environment(environment),
|
||||
m_notifier(notifier)
|
||||
{
|
||||
}
|
||||
|
||||
~PchGenerator()
|
||||
{
|
||||
cleanupAllProcesses();
|
||||
}
|
||||
|
||||
void startTask(Utils::SmallStringVector &&compilerArguments, ProjectPartPch &&projectPartPch) override
|
||||
{
|
||||
addTask(std::move(compilerArguments), std::move(projectPartPch));
|
||||
}
|
||||
|
||||
void setNotifier(PchGeneratorNotifierInterface *notifier)
|
||||
{
|
||||
m_notifier = notifier;
|
||||
}
|
||||
|
||||
unitttest_public:
|
||||
Process *addTask(Utils::SmallStringVector &&compilerArguments, ProjectPartPch &&projectPartPch)
|
||||
{
|
||||
auto process = std::make_unique<Process>();
|
||||
Process *processPointer = process.get();
|
||||
|
||||
process->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
process->setArguments(compilerArguments);
|
||||
process->setProgram(m_environment.clangCompilerPath());
|
||||
|
||||
connectProcess(processPointer, std::move(projectPartPch));
|
||||
|
||||
if (!deferProcess())
|
||||
startProcess(std::move(process));
|
||||
else
|
||||
m_deferredProcesses.push(std::move(process));
|
||||
|
||||
return processPointer;
|
||||
}
|
||||
|
||||
void connectProcess(Process *process, ProjectPartPch &&projectPartPch)
|
||||
{
|
||||
auto finishedCallback = [=,projectPartPch=std::move(projectPartPch)] (int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
deleteProcess(process);
|
||||
activateNextDeferredProcess();
|
||||
m_notifier->taskFinished(generateTaskFinishStatus(exitCode, exitStatus), projectPartPch);
|
||||
};
|
||||
|
||||
QObject::connect(process,
|
||||
static_cast<void (Process::*)(int, QProcess::ExitStatus)>(&Process::finished),
|
||||
std::move(finishedCallback));
|
||||
}
|
||||
|
||||
void startProcess(std::unique_ptr<Process> &&process)
|
||||
{
|
||||
process->start();
|
||||
m_runningProcesses.push_back(std::move(process));
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<Process>> &runningProcesses() const
|
||||
{
|
||||
return m_runningProcesses;
|
||||
}
|
||||
|
||||
const std::queue<std::unique_ptr<Process>> &deferredProcesses() const
|
||||
{
|
||||
return m_deferredProcesses;
|
||||
}
|
||||
|
||||
void deleteProcess(Process *process)
|
||||
{
|
||||
auto found = std::find_if(m_runningProcesses.begin(),
|
||||
m_runningProcesses.end(),
|
||||
[=] (const std::unique_ptr<Process> &entry) {
|
||||
return entry.get() == process;
|
||||
});
|
||||
|
||||
if (found != m_runningProcesses.end()) {
|
||||
std::unique_ptr<Process> avoidDoubleDeletedProcess = std::move(*found);
|
||||
m_runningProcesses.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
void cleanupAllProcesses()
|
||||
{
|
||||
std::vector<std::unique_ptr<Process>> runningProcesses = std::move(m_runningProcesses);
|
||||
std::queue<std::unique_ptr<Process>> deferredProcesses = std::move(m_deferredProcesses);
|
||||
}
|
||||
|
||||
static TaskFinishStatus generateTaskFinishStatus(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
if (exitCode != 0 || exitStatus != QProcess::NormalExit)
|
||||
return TaskFinishStatus::Unsuccessfully;
|
||||
else
|
||||
return TaskFinishStatus::Successfully;
|
||||
}
|
||||
|
||||
bool deferProcess() const
|
||||
{
|
||||
return m_environment.hardwareConcurrency() <= m_runningProcesses.size();
|
||||
}
|
||||
|
||||
void activateNextDeferredProcess()
|
||||
{
|
||||
if (!m_deferredProcesses.empty()) {
|
||||
std::unique_ptr<Process> process = std::move(m_deferredProcesses.front());
|
||||
m_deferredProcesses.pop();
|
||||
|
||||
startProcess(std::move(process));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Process>> m_runningProcesses;
|
||||
std::queue<std::unique_ptr<Process>> m_deferredProcesses;
|
||||
Environment &m_environment;
|
||||
PchGeneratorNotifierInterface *m_notifier=nullptr;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
@@ -0,0 +1,31 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "pchgeneratorinterface.h"
|
||||
|
||||
ClangBackEnd::PchGeneratorInterface::~PchGeneratorInterface()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class ProjectPartPch;
|
||||
|
||||
class PchGeneratorInterface
|
||||
{
|
||||
public:
|
||||
virtual ~PchGeneratorInterface();
|
||||
|
||||
virtual void startTask(Utils::SmallStringVector &&compilerArguments,
|
||||
ProjectPartPch &&projectPartPch) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "pchgeneratornotifierinterface.h"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
PchGeneratorNotifierInterface::~PchGeneratorNotifierInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, TaskFinishStatus status)
|
||||
{
|
||||
enum class TaskFinishStatus
|
||||
{
|
||||
Successfully,
|
||||
Unsuccessfully
|
||||
};
|
||||
|
||||
if (status == ClangBackEnd::TaskFinishStatus::Successfully)
|
||||
out << "Successfully";
|
||||
else
|
||||
out << "Unsuccessfully";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
class ProjectPartPch;
|
||||
|
||||
enum class TaskFinishStatus
|
||||
{
|
||||
Successfully,
|
||||
Unsuccessfully
|
||||
};
|
||||
|
||||
class PchGeneratorNotifierInterface
|
||||
{
|
||||
public:
|
||||
virtual ~PchGeneratorNotifierInterface();
|
||||
|
||||
virtual void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) = 0;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, TaskFinishStatus status);
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
@@ -58,8 +58,6 @@ void PchManagerServer::updatePchProjectParts(UpdatePchProjectPartsMessage &&mess
|
||||
{
|
||||
m_pchCreator.generatePchs(m_projectParts.update(message.takeProjectsParts()));
|
||||
|
||||
client()->precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage(m_pchCreator.takeProjectPartPchs()));
|
||||
|
||||
m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes());
|
||||
}
|
||||
|
||||
@@ -74,9 +72,13 @@ void PchManagerServer::pathsWithIdsChanged(const Utils::SmallStringVector &ids)
|
||||
{
|
||||
m_pchCreator.generatePchs(m_projectParts.projects(ids));
|
||||
|
||||
client()->precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage(m_pchCreator.takeProjectPartPchs()));
|
||||
|
||||
m_fileSystemWatcher.updateIdPaths(m_pchCreator.takeProjectsIncludes());
|
||||
}
|
||||
|
||||
void PchManagerServer::taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch)
|
||||
{
|
||||
if (status == TaskFinishStatus::Successfully)
|
||||
client()->precompiledHeadersUpdated(PrecompiledHeadersUpdatedMessage({projectPartPch.clone()}));
|
||||
}
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "clangpathwatcherinterface.h"
|
||||
#include "clangpathwatchernotifier.h"
|
||||
#include "pchcreatorinterface.h"
|
||||
#include "pchgeneratornotifierinterface.h"
|
||||
#include "pchmanagerserverinterface.h"
|
||||
#include "projectpartsinterface.h"
|
||||
#include "stringcache.h"
|
||||
@@ -36,7 +37,9 @@ namespace ClangBackEnd {
|
||||
|
||||
class SourceRangesAndDiagnosticsForQueryMessage;
|
||||
|
||||
class PchManagerServer : public PchManagerServerInterface, public ClangPathWatcherNotifier
|
||||
class PchManagerServer : public PchManagerServerInterface,
|
||||
public ClangPathWatcherNotifier,
|
||||
public PchGeneratorNotifierInterface
|
||||
{
|
||||
public:
|
||||
PchManagerServer(StringCache<Utils::SmallString> &filePathCache,
|
||||
@@ -50,6 +53,7 @@ public:
|
||||
void removePchProjectParts(RemovePchProjectPartsMessage &&message) override;
|
||||
|
||||
void pathsWithIdsChanged(const Utils::SmallStringVector &ids) override;
|
||||
void taskFinished(TaskFinishStatus status, const ProjectPartPch &projectPartPch) override;
|
||||
|
||||
private:
|
||||
StringCache<Utils::SmallString> &m_filePathCache;
|
||||
|
||||
88
tests/unit/unittest/fakeprocess.cpp
Normal file
88
tests/unit/unittest/fakeprocess.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "fakeprocess.h"
|
||||
|
||||
FakeProcess::FakeProcess()
|
||||
{
|
||||
}
|
||||
|
||||
FakeProcess::~FakeProcess()
|
||||
{
|
||||
if (m_isStarted && !m_isFinished)
|
||||
emit finished(0, QProcess::NormalExit);
|
||||
}
|
||||
|
||||
void FakeProcess::finishUnsuccessfully()
|
||||
{
|
||||
m_isFinished = true;
|
||||
emit finished(1, QProcess::NormalExit);
|
||||
}
|
||||
|
||||
void FakeProcess::finishByCrash()
|
||||
{
|
||||
m_isFinished = true;
|
||||
emit finished(0, QProcess::CrashExit);
|
||||
}
|
||||
|
||||
void FakeProcess::finish()
|
||||
{
|
||||
m_isFinished = true;
|
||||
emit finished(0, QProcess::NormalExit);
|
||||
}
|
||||
|
||||
void FakeProcess::setArguments(const QStringList &arguments)
|
||||
{
|
||||
m_arguments = arguments;
|
||||
}
|
||||
|
||||
void FakeProcess::setProgram(const QString &program)
|
||||
{
|
||||
m_applicationPath = program;
|
||||
}
|
||||
|
||||
void FakeProcess::setProcessChannelMode(QProcess::ProcessChannelMode)
|
||||
{
|
||||
}
|
||||
|
||||
void FakeProcess::start()
|
||||
{
|
||||
m_isStarted = true;
|
||||
}
|
||||
|
||||
bool FakeProcess::isStarted() const
|
||||
{
|
||||
return m_isStarted;
|
||||
}
|
||||
|
||||
const QStringList &FakeProcess::arguments() const
|
||||
{
|
||||
return m_arguments;
|
||||
}
|
||||
|
||||
const QString &FakeProcess::applicationPath() const
|
||||
{
|
||||
return m_applicationPath;
|
||||
}
|
||||
62
tests/unit/unittest/fakeprocess.h
Normal file
62
tests/unit/unittest/fakeprocess.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
class FakeProcess : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FakeProcess();
|
||||
~FakeProcess();
|
||||
|
||||
void finishUnsuccessfully();
|
||||
void finishByCrash();
|
||||
void finish();
|
||||
|
||||
void start();
|
||||
void setArguments(const QStringList &arguments);
|
||||
void setProgram(const QString &program);
|
||||
|
||||
void setProcessChannelMode(QProcess::ProcessChannelMode mode);
|
||||
|
||||
|
||||
bool isStarted() const;
|
||||
|
||||
const QStringList &arguments() const;
|
||||
const QString &applicationPath() const;
|
||||
|
||||
signals:
|
||||
void finished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
private:
|
||||
QStringList m_arguments;
|
||||
QString m_applicationPath;
|
||||
bool m_isFinished = false;
|
||||
bool m_isStarted = false;
|
||||
};
|
||||
@@ -36,8 +36,6 @@ class MockPchCreator : public ClangBackEnd::PchCreatorInterface
|
||||
public:
|
||||
MOCK_METHOD1(generatePchs,
|
||||
void(const std::vector<ClangBackEnd::V2::ProjectPartContainer> &projectParts));
|
||||
MOCK_METHOD0(takeProjectPartPchs,
|
||||
std::vector<ClangBackEnd::ProjectPartPch>());
|
||||
MOCK_METHOD0(takeProjectsIncludes,
|
||||
std::vector<ClangBackEnd::IdPaths>());
|
||||
|
||||
|
||||
38
tests/unit/unittest/mockpchgeneratornotifier.h
Normal file
38
tests/unit/unittest/mockpchgeneratornotifier.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include <pchgeneratornotifierinterface.h>
|
||||
|
||||
class MockPchGeneratorNotifier : public ClangBackEnd::PchGeneratorNotifierInterface
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD2(taskFinished,
|
||||
void (ClangBackEnd::TaskFinishStatus status,
|
||||
const ClangBackEnd::ProjectPartPch &projectPartPch));
|
||||
};
|
||||
@@ -25,9 +25,12 @@
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include "fakeprocess.h"
|
||||
#include "mockpchgeneratornotifier.h"
|
||||
#include "testenvironment.h"
|
||||
|
||||
#include <pchcreator.h>
|
||||
#include <pchgenerator.h>
|
||||
#include <stringcache.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
@@ -70,9 +73,12 @@ protected:
|
||||
{header2Path.clone()},
|
||||
{main2Path.clone()}};
|
||||
TestEnvironment environment;
|
||||
NiceMock<MockPchGeneratorNotifier> mockPchGeneratorNotifier;
|
||||
ClangBackEnd::PchGenerator<FakeProcess> generator{environment, &mockPchGeneratorNotifier};
|
||||
ClangBackEnd::PchCreator creator{{projectPart1.clone(),projectPart2.clone()},
|
||||
environment,
|
||||
filePathCache};
|
||||
filePathCache,
|
||||
&generator};
|
||||
};
|
||||
|
||||
using PchCreatorSlowTest = PchCreator;
|
||||
@@ -116,7 +122,7 @@ TEST_F(PchCreator, CreateGlobalCommandLine)
|
||||
ASSERT_THAT(arguments, ElementsAre(environment.clangCompilerPath(), "-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header", "-I", TESTDATA_DIR, "-x" , "c++-header", "-Wno-pragma-once-outside-header"));
|
||||
}
|
||||
|
||||
TEST_F(PchCreator, CreateGlobalPchIncludes)
|
||||
TEST_F(PchCreatorVerySlowTest, CreateGlobalPchIncludes)
|
||||
{
|
||||
auto includeIds = creator.generateGlobalPchIncludeIds();
|
||||
|
||||
@@ -167,13 +173,6 @@ TEST_F(PchCreator, CreateGlobalClangCompilerArguments)
|
||||
Not(Contains(environment.clangCompilerPath()))));
|
||||
}
|
||||
|
||||
TEST_F(PchCreatorVerySlowTest, CreateGlobalPch)
|
||||
{
|
||||
creator.generateGlobalPch();
|
||||
|
||||
ASSERT_TRUE(QFileInfo::exists(creator.generateGlobalPchFilePath()));
|
||||
}
|
||||
|
||||
TEST_F(PchCreator, CreateProjectPartCommandLine)
|
||||
{
|
||||
auto commandLine = creator.generateProjectPartCommandLine(projectPart1);
|
||||
@@ -258,23 +257,34 @@ TEST_F(PchCreatorVerySlowTest, CreatePartPchs)
|
||||
{
|
||||
creator.generateGlobalPch();
|
||||
|
||||
auto projectPartPchAndIdPath = creator.generateProjectPartPch(projectPart1);
|
||||
auto includePaths = creator.generateProjectPartPch(projectPart1);
|
||||
|
||||
ASSERT_THAT(projectPartPchAndIdPath.first.id(), projectPart1.projectPartId());
|
||||
ASSERT_THAT(projectPartPchAndIdPath.first.path(), creator.generateProjectPartPchFilePath(projectPart1));
|
||||
ASSERT_THAT(projectPartPchAndIdPath.second.id, projectPart1.projectPartId());
|
||||
ASSERT_THAT(projectPartPchAndIdPath.second.paths, UnorderedElementsAre(1, 2, 3));
|
||||
ASSERT_THAT(includePaths.id, projectPart1.projectPartId());
|
||||
ASSERT_THAT(includePaths.paths, UnorderedElementsAre(1, 2, 3));
|
||||
}
|
||||
|
||||
TEST_F(PchCreatorVerySlowTest, IncludesForCreatePchsForProjectParts)
|
||||
{
|
||||
creator.generatePchs();
|
||||
|
||||
ASSERT_THAT(creator.takeProjectsIncludes(),
|
||||
ElementsAre(Field(&IdPaths::id, "project1"),
|
||||
Field(&IdPaths::id, "project2")));
|
||||
}
|
||||
|
||||
TEST_F(PchCreatorVerySlowTest, ProjectPartPchsForCreatePchsForProjectParts)
|
||||
{
|
||||
creator.generatePchs();
|
||||
|
||||
ASSERT_THAT(creator.takeProjectPartPchs(),
|
||||
ElementsAre(Property(&ProjectPartPch::id, "project1"),
|
||||
EXPECT_CALL(mockPchGeneratorNotifier,
|
||||
taskFinished(ClangBackEnd::TaskFinishStatus::Successfully,
|
||||
Property(&ProjectPartPch::id, "project1")));
|
||||
EXPECT_CALL(mockPchGeneratorNotifier,
|
||||
taskFinished(ClangBackEnd::TaskFinishStatus::Successfully,
|
||||
Property(&ProjectPartPch::id, "project2")));
|
||||
|
||||
creator.generatePchs();
|
||||
}
|
||||
|
||||
|
||||
TEST_F(PchCreatorVerySlowTest, IdPathsForCreatePchsForProjectParts)
|
||||
{
|
||||
creator.generatePchs();
|
||||
|
||||
224
tests/unit/unittest/pchgenerator-test.cpp
Normal file
224
tests/unit/unittest/pchgenerator-test.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "googletest.h"
|
||||
|
||||
#include "fakeprocess.h"
|
||||
#include "testenvironment.h"
|
||||
#include "mockpchgeneratornotifier.h"
|
||||
|
||||
#include <pchgenerator.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using testing::_;
|
||||
using testing::Contains;
|
||||
using testing::Eq;
|
||||
using testing::NiceMock;
|
||||
using testing::Not;
|
||||
using testing::PrintToString;
|
||||
using ClangBackEnd::TaskFinishStatus;
|
||||
|
||||
MATCHER_P(ContainsProcess, process,
|
||||
std::string(negation ? "isn't" : "is")
|
||||
+ " process " + PrintToString(process))
|
||||
{
|
||||
auto found = std::find_if(arg.begin(),
|
||||
arg.end(),
|
||||
[&] (const std::unique_ptr<FakeProcess> &processOwner) {
|
||||
return processOwner.get() == process;
|
||||
});
|
||||
|
||||
return found != arg.end();
|
||||
}
|
||||
|
||||
class PchGenerator : public testing::Test
|
||||
{
|
||||
protected:
|
||||
TestEnvironment environment;
|
||||
NiceMock<MockPchGeneratorNotifier> mockNotifier;
|
||||
ClangBackEnd::PchGenerator<FakeProcess> generator{environment, &mockNotifier};
|
||||
Utils::SmallStringVector compilerArguments = {"-DXXXX", "-Ifoo"};
|
||||
ClangBackEnd::ProjectPartPch projectPartPch{"projectPartId", "/path/to/pch"};
|
||||
};
|
||||
|
||||
bool operator==(const std::unique_ptr<FakeProcess> &first, FakeProcess *const second)
|
||||
{
|
||||
return first.get() == second;
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, ProcessFinished)
|
||||
{
|
||||
EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Successfully, std::move(projectPartPch)));
|
||||
|
||||
generator.startTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, ProcessFinishedForDeferredProcess)
|
||||
{
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
generator.startTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Successfully, std::move(projectPartPch)))
|
||||
.Times(3);
|
||||
|
||||
generator.startTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
process->finish();
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, ProcessSuccessfullyFinished)
|
||||
{
|
||||
EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Unsuccessfully, std::move(projectPartPch)));
|
||||
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
process->finishUnsuccessfully();
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, ProcessSuccessfullyFinishedByWrongExitCode)
|
||||
{
|
||||
EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Unsuccessfully, std::move(projectPartPch)));
|
||||
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
process->finishUnsuccessfully();
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, AddTaskAddsProcessToProcesses)
|
||||
{
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
ASSERT_THAT(generator.runningProcesses(), ContainsProcess(process));
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, RemoveProcessAfterFinishingProcess)
|
||||
{
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
process->finish();
|
||||
|
||||
ASSERT_THAT(generator.runningProcesses(), Not(ContainsProcess(process)));
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, ProcessSuccessfullyFinishedByCrash)
|
||||
{
|
||||
EXPECT_CALL(mockNotifier, taskFinished(TaskFinishStatus::Unsuccessfully, std::move(projectPartPch)));
|
||||
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
process->finishByCrash();
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, CreateProcess)
|
||||
{
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
ASSERT_THAT(generator.runningProcesses(), ContainsProcess(process));
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, DeleteProcess)
|
||||
{
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
generator.deleteProcess(process);
|
||||
|
||||
ASSERT_THAT(generator.runningProcesses(), Not(ContainsProcess(process)));
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, StartProcessApplicationPath)
|
||||
{
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
ASSERT_THAT(process->applicationPath(), environment.clangCompilerPath());
|
||||
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, SetCompilerArguments)
|
||||
{
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
ASSERT_THAT(process->arguments(), compilerArguments);
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, ProcessIsStartedAfterAddingTask)
|
||||
{
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
ASSERT_TRUE(process->isStarted());
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, DeferProcess)
|
||||
{
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
auto deferProcess = generator.deferProcess();
|
||||
|
||||
ASSERT_TRUE(deferProcess);
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, ThirdTaskIsDeferred)
|
||||
{
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
ASSERT_THAT(process, generator.deferredProcesses().back().get());
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, ThirdTaskIsNotRunning)
|
||||
{
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
ASSERT_THAT(generator.runningProcesses(), Not(ContainsProcess(process)));
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, DoNotDeferProcess)
|
||||
{
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
auto deferProcess = generator.deferProcess();
|
||||
|
||||
ASSERT_FALSE(deferProcess);
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, DoNotActivateIfNothingIsDeferred)
|
||||
{
|
||||
generator.activateNextDeferredProcess();
|
||||
}
|
||||
|
||||
TEST_F(PchGenerator, AfterActivationProcessIsRunning)
|
||||
{
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
auto process = generator.addTask(compilerArguments.clone(), projectPartPch.clone());
|
||||
|
||||
generator.activateNextDeferredProcess();
|
||||
|
||||
ASSERT_THAT(generator.runningProcesses(), ContainsProcess(process));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -47,6 +47,7 @@ using testing::IsEmpty;
|
||||
|
||||
using Utils::SmallString;
|
||||
using ClangBackEnd::V2::ProjectPartContainer;
|
||||
using ClangBackEnd::TaskFinishStatus;
|
||||
|
||||
class PchManagerServer : public ::testing::Test
|
||||
{
|
||||
@@ -76,18 +77,28 @@ protected:
|
||||
{main2Path.clone()}};
|
||||
std::vector<ClangBackEnd::V2::ProjectPartContainer> projectParts{projectPart1, projectPart2};
|
||||
ClangBackEnd::UpdatePchProjectPartsMessage updatePchProjectPartsMessage{Utils::clone(projectParts)};
|
||||
std::vector<ClangBackEnd::ProjectPartPch> projectPartPchs{{projectPart1.projectPartId().clone(), "/path1/to/pch"},
|
||||
{projectPart2.projectPartId().clone(), "/path2/to/pch"}};
|
||||
ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage{Utils::clone(projectPartPchs)};
|
||||
ClangBackEnd::ProjectPartPch projectPartPch1{projectPart1.projectPartId().clone(), "/path1/to/pch"};
|
||||
ClangBackEnd::ProjectPartPch projectPartPch2{projectPart2.projectPartId().clone(), "/path2/to/pch"};
|
||||
std::vector<ClangBackEnd::ProjectPartPch> projectPartPchs{projectPartPch1, projectPartPch2};
|
||||
ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage1{{projectPartPch1}};
|
||||
ClangBackEnd::PrecompiledHeadersUpdatedMessage precompiledHeaderUpdatedMessage2{{projectPartPch2}};
|
||||
ClangBackEnd::RemovePchProjectPartsMessage removePchProjectPartsMessage{{projectPart1.projectPartId().clone(),
|
||||
projectPart2.projectPartId().clone()}};
|
||||
};
|
||||
|
||||
TEST_F(PchManagerServer, CallPrecompiledHeadersUpdatedInClientForUpdate)
|
||||
TEST_F(PchManagerServer, CallPrecompiledHeadersForSuccessfullyFinishedTask)
|
||||
{
|
||||
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(precompiledHeaderUpdatedMessage));
|
||||
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(precompiledHeaderUpdatedMessage1));
|
||||
|
||||
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
|
||||
server.taskFinished(TaskFinishStatus::Successfully, projectPartPch1);
|
||||
}
|
||||
|
||||
TEST_F(PchManagerServer, DoNotCallPrecompiledHeadersForUnsuccessfullyFinishedTask)
|
||||
{
|
||||
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(precompiledHeaderUpdatedMessage1))
|
||||
.Times(0);
|
||||
|
||||
server.taskFinished(TaskFinishStatus::Unsuccessfully, projectPartPch1);
|
||||
}
|
||||
|
||||
TEST_F(PchManagerServer, CallBuildInPchCreator)
|
||||
@@ -150,15 +161,6 @@ TEST_F(PchManagerServer, CallGeneratePchsInPchCreatorForIncludeChange)
|
||||
server.pathsWithIdsChanged({projectPartId1});
|
||||
}
|
||||
|
||||
TEST_F(PchManagerServer, CallPrecompiledHeadersUpdatedInClientForIncludeChange)
|
||||
{
|
||||
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
|
||||
|
||||
EXPECT_CALL(mockPchManagerClient, precompiledHeadersUpdated(precompiledHeaderUpdatedMessage));
|
||||
|
||||
server.pathsWithIdsChanged({projectPartId1});
|
||||
}
|
||||
|
||||
TEST_F(PchManagerServer, CallUpdateIdPathsInFileSystemWatcherForIncludeChange)
|
||||
{
|
||||
server.updatePchProjectParts(updatePchProjectPartsMessage.clone());
|
||||
@@ -172,8 +174,6 @@ void PchManagerServer::SetUp()
|
||||
{
|
||||
server.setClient(&mockPchManagerClient);
|
||||
|
||||
ON_CALL(mockPchCreator, takeProjectPartPchs())
|
||||
.WillByDefault(Return(projectPartPchs));
|
||||
ON_CALL(mockProjectParts, update(projectParts))
|
||||
.WillByDefault(Return(projectParts));
|
||||
ON_CALL(mockProjectParts, projects(Utils::SmallStringVector{{projectPartId1}}))
|
||||
|
||||
@@ -45,6 +45,11 @@ public:
|
||||
return QString::fromUtf8(CLANG_COMPILER_PATH);
|
||||
}
|
||||
|
||||
uint hardwareConcurrency() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
private:
|
||||
QTemporaryDir temporaryDirectory;
|
||||
};
|
||||
|
||||
@@ -49,7 +49,9 @@ SOURCES += \
|
||||
projectparts-test.cpp \
|
||||
stringcache-test.cpp \
|
||||
changedfilepathcompressor-test.cpp \
|
||||
faketimer.cpp
|
||||
faketimer.cpp \
|
||||
pchgenerator-test.cpp \
|
||||
fakeprocess.cpp
|
||||
|
||||
!isEmpty(LIBCLANG_LIBS) {
|
||||
SOURCES += \
|
||||
@@ -148,7 +150,9 @@ HEADERS += \
|
||||
mockprojectparts.h \
|
||||
mockclangpathwatchernotifier.h \
|
||||
mockchangedfilepathcompressor.h \
|
||||
faketimer.h
|
||||
faketimer.h \
|
||||
mockpchgeneratornotifier.h \
|
||||
fakeprocess.h
|
||||
|
||||
!isEmpty(LIBCLANG_LIBS) {
|
||||
HEADERS += \
|
||||
|
||||
Reference in New Issue
Block a user