ClangPchManager: Introduce PchTaskQueue

With the PchTaskQueue the pipeline is almost complete.

Task-number: QTCREATORBUG-21346
Change-Id: I5f05d525db1679eb37dd1d462076c1ed42958099
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2018-12-04 19:03:48 +01:00
parent 96eb407266
commit 390a227df6
34 changed files with 979 additions and 143 deletions

View File

@@ -190,9 +190,10 @@ public:
table.setUseIfNotExists(true);
table.setName("precompiledHeaders");
table.addColumn("projectPartId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("pchPath", Sqlite::ColumnType::Text);
table.addColumn("pchBuildTime", Sqlite::ColumnType::Integer);
table.addColumn("projectPchPath", Sqlite::ColumnType::Text);
table.addColumn("projectPchBuildTime", Sqlite::ColumnType::Integer);
table.addColumn("systemPchPath", Sqlite::ColumnType::Text);
table.addColumn("systemPchBuildTime", Sqlite::ColumnType::Integer);
table.initialize(database);
}

View File

@@ -133,10 +133,8 @@ bool BaseStatement::next() const
return true;
else if (resultCode == SQLITE_DONE)
return false;
else
checkForStepError(resultCode);
return false;
checkForStepError(resultCode);
}
void BaseStatement::step() const

View File

@@ -6,7 +6,8 @@ SOURCES += \
$$PWD/projectparts.cpp \
$$PWD/projectpartqueue.cpp \
$$PWD/pchtaskgenerator.cpp \
$$PWD/pchtasksmerger.cpp
$$PWD/pchtasksmerger.cpp \
$$PWD/pchtaskqueue.cpp
HEADERS += \
$$PWD/pchmanagerserver.h \
@@ -38,7 +39,8 @@ HEADERS += \
$$PWD/usedmacrofilter.h \
$$PWD/pchtasksmergerinterface.h \
$$PWD/pchtasksmerger.h \
$$PWD/pchtaskqueueinterface.h
$$PWD/pchtaskqueueinterface.h \
$$PWD/pchtaskqueue.h
!isEmpty(LIBTOOLING_LIBS) {
SOURCES += \

View File

@@ -326,11 +326,16 @@ IdPaths PchCreator::generateProjectPartPch(const V2::ProjectPartContainer &proje
return {projectPart.projectPartId.clone(), allIncludeIds(includes)};
}
void PchCreator::generatePch(const V2::ProjectPartContainer &projectPart)
void PchCreator::generatePchDeprecated(const V2::ProjectPartContainer &projectPart)
{
m_projectIncludeIds = generateProjectPartPch(projectPart);
}
void PchCreator::generatePch(const PchTask &pchTask)
{
}
IdPaths PchCreator::takeProjectIncludes()
{
return std::move(m_projectIncludeIds);

View File

@@ -69,7 +69,8 @@ public:
{
}
void generatePch(const V2::ProjectPartContainer &projectsPart) override;
void generatePchDeprecated(const V2::ProjectPartContainer &projectsPart) override;
void generatePch(const PchTask &pchTask) override;
IdPaths takeProjectIncludes() override;
const ProjectPartPch &projectPartPch() override;
void setUnsavedFiles(const V2::FileContainers &fileContainers) override;

View File

@@ -26,6 +26,7 @@
#pragma once
#include "idpaths.h"
#include "pchtask.h"
#include "projectpartpch.h"
#include "processorinterface.h"
@@ -41,7 +42,8 @@ public:
PchCreatorInterface(const PchCreatorInterface &) = delete;
PchCreatorInterface &operator=(const PchCreatorInterface &) = delete;
virtual void generatePch(const V2::ProjectPartContainer &projectsPart) = 0;
virtual void generatePchDeprecated(const V2::ProjectPartContainer &projectsPart) = 0;
virtual void generatePch(const PchTask &pchTask) = 0;
virtual IdPaths takeProjectIncludes() = 0;
virtual const ProjectPartPch &projectPartPch() = 0;

View File

@@ -40,7 +40,17 @@ public:
FilePathIds &&includes,
CompilerMacros &&compilerMacros,
UsedMacros &&usedMacros)
: projectPartId(projectPartId)
: projectPartIds({projectPartId})
, includes(includes)
, compilerMacros(compilerMacros)
, usedMacros(usedMacros)
{}
PchTask(Utils::SmallStringVector &&projectPartIds,
FilePathIds &&includes,
CompilerMacros &&compilerMacros,
UsedMacros &&usedMacros)
: projectPartIds(std::move(projectPartIds))
, includes(includes)
, compilerMacros(compilerMacros)
, usedMacros(usedMacros)
@@ -48,15 +58,17 @@ public:
friend bool operator==(const PchTask &first, const PchTask &second)
{
return first.projectPartId == second.projectPartId
&& first.dependentIds == second.dependentIds && first.includes == second.includes
return first.systemPchPath == second.systemPchPath
&& first.projectPartIds == second.projectPartIds && first.includes == second.includes
&& first.compilerMacros == second.compilerMacros
&& first.usedMacros == second.usedMacros;
}
Utils::SmallStringView projectPartId() const { return projectPartIds.front(); }
public:
Utils::SmallString projectPartId;
Utils::SmallStringVector dependentIds;
Utils::PathString systemPchPath;
Utils::SmallStringVector projectPartIds;
FilePathIds includes;
CompilerMacros compilerMacros;
UsedMacros usedMacros;

View File

@@ -0,0 +1,205 @@
/****************************************************************************
**
** Copyright (C) 2018 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 "pchtaskqueue.h"
#include <pchcreatorinterface.h>
#include <precompiledheaderstorageinterface.h>
#include <progresscounter.h>
#include <sqlitetransaction.h>
namespace ClangBackEnd {
void PchTaskQueue::addPchTasks(PchTasks &&newPchTasks, PchTasks &destination)
{
auto compare = [](const PchTask &first, const PchTask &second) {
return first.projectPartIds < second.projectPartIds;
};
const std::size_t oldSize = destination.size();
PchTasks mergedPchTasks;
mergedPchTasks.reserve(destination.size() + newPchTasks.size());
std::set_union(std::make_move_iterator(newPchTasks.begin()),
std::make_move_iterator(newPchTasks.end()),
std::make_move_iterator(destination.begin()),
std::make_move_iterator(destination.end()),
std::back_inserter(mergedPchTasks),
compare);
destination = std::move(mergedPchTasks);
m_progressCounter.addTotal(int(destination.size() - oldSize));
processEntries();
}
void PchTaskQueue::removePchTasksByProjectPartId(const Utils::SmallStringVector &projectsPartIds,
PchTasks &destination)
{
class CompareDifference
{
public:
bool operator()(const PchTask &first, const Utils::SmallString &second)
{
return first.projectPartId() < second;
}
bool operator()(const Utils::SmallString &first, const PchTask &second)
{
return first < second.projectPartId();
}
};
const std::size_t oldSize = destination.size();
PchTasks notToBeRemovedProjectParts;
notToBeRemovedProjectParts.reserve(destination.size());
std::set_difference(std::make_move_iterator(destination.begin()),
std::make_move_iterator(destination.end()),
projectsPartIds.begin(),
projectsPartIds.end(),
std::back_inserter(notToBeRemovedProjectParts),
CompareDifference{});
destination = std::move(notToBeRemovedProjectParts);
m_progressCounter.removeTotal(int(oldSize - destination.size()));
}
void PchTaskQueue::addSystemPchTasks(PchTasks &&pchTasks)
{
addPchTasks(std::move(pchTasks), m_systemPchTasks);
}
void PchTaskQueue::addProjectPchTasks(PchTasks &&pchTasks)
{
addPchTasks(std::move(pchTasks), m_projectPchTasks);
}
void PchTaskQueue::removePchTasks(const Utils::SmallStringVector &projectsPartIds)
{
removePchTasksByProjectPartId(projectsPartIds, m_projectPchTasks);
}
void PchTaskQueue::processProjectPchTasks()
{
uint systemRunningTaskCount = m_systemPchTaskScheduler.slotUsage().used;
if (!systemRunningTaskCount) {
uint freeTaskCount = m_projectPchTaskScheduler.slotUsage().free;
auto newEnd = std::prev(m_projectPchTasks.end(),
std::min<int>(int(freeTaskCount), int(m_projectPchTasks.size())));
m_projectPchTaskScheduler.addTasks(createProjectTasks(
{std::make_move_iterator(newEnd), std::make_move_iterator(m_projectPchTasks.end())}));
m_projectPchTasks.erase(newEnd, m_projectPchTasks.end());
}
}
void PchTaskQueue::processSystemPchTasks()
{
uint freeTaskCount = m_systemPchTaskScheduler.slotUsage().free;
auto newEnd = std::prev(m_systemPchTasks.end(),
std::min<int>(int(freeTaskCount), int(m_systemPchTasks.size())));
m_systemPchTaskScheduler.addTasks(createSystemTasks(
{std::make_move_iterator(newEnd), std::make_move_iterator(m_systemPchTasks.end())}));
m_systemPchTasks.erase(newEnd, m_systemPchTasks.end());
}
void PchTaskQueue::processEntries()
{
processSystemPchTasks();
processProjectPchTasks();
}
std::vector<PchTaskQueue::Task> PchTaskQueue::createProjectTasks(PchTasks &&pchTasks) const
{
std::vector<Task> tasks;
tasks.reserve(pchTasks.size());
auto convert = [this](auto &&pchTask) {
return [pchTask = std::move(pchTask), this](PchCreatorInterface &pchCreator) mutable {
Sqlite::DeferredTransaction readTransaction(m_transactionsInterface);
pchTask.systemPchPath = m_precompiledHeaderStorage.fetchSystemPrecompiledHeaderPath(
pchTask.projectPartId());
readTransaction.commit();
pchCreator.generatePch(pchTask);
const auto &projectPartPch = pchCreator.projectPartPch();
Sqlite::ImmediateTransaction writeTransaction(m_transactionsInterface);
if (projectPartPch.pchPath.empty()) {
m_precompiledHeaderStorage.deleteProjectPrecompiledHeader(pchTask.projectPartId());
} else {
m_precompiledHeaderStorage
.insertProjectPrecompiledHeader(pchTask.projectPartId(),
projectPartPch.pchPath,
projectPartPch.lastModified);
}
writeTransaction.commit();
};
};
std::transform(std::make_move_iterator(pchTasks.begin()),
std::make_move_iterator(pchTasks.end()),
std::back_inserter(tasks),
convert);
return tasks;
}
std::vector<PchTaskQueue::Task> PchTaskQueue::createSystemTasks(PchTasks &&pchTasks) const
{
std::vector<Task> tasks;
tasks.reserve(pchTasks.size());
auto convert = [this](auto &&pchTask) {
return [pchTask = std::move(pchTask), this](PchCreatorInterface &pchCreator) {
pchCreator.generatePch(pchTask);
const auto &projectPartPch = pchCreator.projectPartPch();
Sqlite::ImmediateTransaction transaction(m_transactionsInterface);
for (Utils::SmallStringView projectPartId : pchTask.projectPartIds) {
if (projectPartPch.pchPath.empty()) {
m_precompiledHeaderStorage.deleteSystemPrecompiledHeader(projectPartId);
} else {
m_precompiledHeaderStorage
.insertSystemPrecompiledHeader(projectPartId,
projectPartPch.pchPath,
projectPartPch.lastModified);
}
}
transaction.commit();
};
};
std::transform(std::make_move_iterator(pchTasks.begin()),
std::make_move_iterator(pchTasks.end()),
std::back_inserter(tasks),
convert);
return tasks;
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2018 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 "pchtaskqueueinterface.h"
#include "taskschedulerinterface.h"
namespace Sqlite {
class TransactionInterface;
}
namespace ClangBackEnd {
class PchCreatorInterface;
class PrecompiledHeaderStorageInterface;
class ProgressCounter;
class PchTaskQueue final : public PchTaskQueueInterface
{
public:
using Task = std::function<void (PchCreatorInterface&)>;
PchTaskQueue(TaskSchedulerInterface<Task> &systemPchTaskScheduler,
TaskSchedulerInterface<Task> &projectPchTaskScheduler,
ProgressCounter &progressCounter,
PrecompiledHeaderStorageInterface &precompiledHeaderStorage,
Sqlite::TransactionInterface &transactionsInterface)
: m_systemPchTaskScheduler(systemPchTaskScheduler)
, m_projectPchTaskScheduler(projectPchTaskScheduler)
, m_precompiledHeaderStorage(precompiledHeaderStorage)
, m_transactionsInterface(transactionsInterface)
, m_progressCounter(progressCounter)
{}
void addSystemPchTasks(PchTasks &&pchTasks) override;
void addProjectPchTasks(PchTasks &&pchTasks) override;
void removePchTasks(const Utils::SmallStringVector &projectsPartIds) override;
void processEntries() override;
const PchTasks &systemPchTasks() const { return m_systemPchTasks; }
const PchTasks &projectPchTasks() const { return m_projectPchTasks; }
std::vector<Task> createProjectTasks(PchTasks &&pchTasks) const;
std::vector<Task> createSystemTasks(PchTasks &&pchTasks) const;
private:
void addPchTasks(PchTasks &&pchTasks, PchTasks &destination);
void removePchTasksByProjectPartId(const Utils::SmallStringVector &projectsPartIds,
PchTasks &destination);
void processProjectPchTasks();
void processSystemPchTasks();
private:
PchTasks m_systemPchTasks;
PchTasks m_projectPchTasks;
TaskSchedulerInterface<Task> &m_systemPchTaskScheduler;
TaskSchedulerInterface<Task> &m_projectPchTaskScheduler;
PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage;
Sqlite::TransactionInterface &m_transactionsInterface;
ProgressCounter &m_progressCounter;
};
} // namespace ClangBackEnd

View File

@@ -47,7 +47,7 @@ public:
m_transaction.commit();
}
void insertPrecompiledHeader(Utils::SmallStringView projectPartName,
void insertProjectPrecompiledHeader(Utils::SmallStringView projectPartName,
Utils::SmallStringView pchPath,
long long pchBuildTime) override
{
@@ -55,43 +55,104 @@ public:
Sqlite::ImmediateTransaction transaction{m_database};
m_insertProjectPartStatement.write(projectPartName);
m_insertPrecompiledHeaderStatement .write(projectPartName, pchPath, pchBuildTime);
m_insertProjectPrecompiledHeaderStatement.write(projectPartName, pchPath, pchBuildTime);
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
insertPrecompiledHeader(projectPartName, pchPath, pchBuildTime);
insertProjectPrecompiledHeader(projectPartName, pchPath, pchBuildTime);
}
}
void deletePrecompiledHeader(Utils::SmallStringView projectPartName) override
void deleteProjectPrecompiledHeader(Utils::SmallStringView projectPartName) override
{
try {
Sqlite::ImmediateTransaction transaction{m_database};
m_deletePrecompiledHeaderStatement.write(projectPartName);
m_deleteProjectPrecompiledHeaderStatement.write(projectPartName);
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
deletePrecompiledHeader(projectPartName);
deleteProjectPrecompiledHeader(projectPartName);
}
}
void insertSystemPrecompiledHeader(Utils::SmallStringView projectPartName,
Utils::SmallStringView pchPath,
long long pchBuildTime) override
{
try {
Sqlite::ImmediateTransaction transaction{m_database};
m_insertProjectPartStatement.write(projectPartName);
m_insertSystemPrecompiledHeaderStatement.write(projectPartName, pchPath, pchBuildTime);
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
insertSystemPrecompiledHeader(projectPartName, pchPath, pchBuildTime);
}
}
void deleteSystemPrecompiledHeader(Utils::SmallStringView projectPartName) override
{
try {
Sqlite::ImmediateTransaction transaction{m_database};
m_deleteSystemPrecompiledHeaderStatement.write(projectPartName);
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
deleteSystemPrecompiledHeader(projectPartName);
}
}
Utils::PathString fetchSystemPrecompiledHeaderPath(Utils::SmallStringView projectPartName) override
{
try {
Sqlite::DeferredTransaction transaction{m_database};
auto value = m_fetchSystemPrecompiledHeaderPathStatement
.template value<Utils::PathString>(projectPartName);
if (value)
return value.value();
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
return fetchSystemPrecompiledHeaderPath(projectPartName);
}
return Utils::SmallStringView("");
}
public:
Sqlite::ImmediateNonThrowingDestructorTransaction m_transaction;
Database &m_database;
WriteStatement m_insertPrecompiledHeaderStatement {
"INSERT OR REPLACE INTO precompiledHeaders(projectPartId, pchPath, pchBuildTime) VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?),?,?)",
m_database
};
WriteStatement m_insertProjectPrecompiledHeaderStatement{
"INSERT INTO precompiledHeaders(projectPartId, projectPchPath, projectPchBuildTime) "
"VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?001),?002,?003) "
"ON CONFLICT (projectPartId) DO UPDATE SET projectPchPath=?002,projectPchBuildTime=?003",
m_database};
WriteStatement m_insertSystemPrecompiledHeaderStatement{
"INSERT INTO precompiledHeaders(projectPartId, systemPchPath, systemPchBuildTime) "
"VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?001),?002,?003) "
"ON CONFLICT (projectPartId) DO UPDATE SET systemPchPath=?002,systemPchBuildTime=?003",
m_database};
WriteStatement m_insertProjectPartStatement{
"INSERT OR IGNORE INTO projectParts(projectPartName) VALUES (?)",
m_database
};
WriteStatement m_deletePrecompiledHeaderStatement{
"DELETE FROM precompiledHeaders WHERE projectPartId = (SELECT projectPartId FROM projectParts WHERE projectPartName = ?)",
m_database
};
"INSERT OR IGNORE INTO projectParts(projectPartName) VALUES (?)", m_database};
WriteStatement m_deleteProjectPrecompiledHeaderStatement{
"UPDATE OR IGNORE precompiledHeaders SET projectPchPath=NULL,projectPchBuildTime=NULL "
"WHERE projectPartId = (SELECT projectPartId FROM "
"projectParts WHERE projectPartName = ?)",
m_database};
WriteStatement m_deleteSystemPrecompiledHeaderStatement{
"UPDATE OR IGNORE precompiledHeaders SET systemPchPath=NULL,systemPchBuildTime=NULL "
"WHERE projectPartId = (SELECT projectPartId FROM "
"projectParts WHERE projectPartName = ?)",
m_database};
ReadStatement m_fetchSystemPrecompiledHeaderPathStatement{
"SELECT systemPchPath FROM precompiledHeaders WHERE projectPartId = (SELECT projectPartId "
"FROM projectParts WHERE projectPartName = ?)",
m_database};
};
}

View File

@@ -25,7 +25,7 @@
#pragma once
#include <utils/smallstringview.h>
#include <utils/smallstring.h>
namespace ClangBackEnd {
@@ -34,14 +34,21 @@ class PrecompiledHeaderStorageInterface
public:
PrecompiledHeaderStorageInterface() = default;
PrecompiledHeaderStorageInterface(const PrecompiledHeaderStorageInterface&) = delete;
PrecompiledHeaderStorageInterface &operator=(const PrecompiledHeaderStorageInterface&) = delete;
PrecompiledHeaderStorageInterface(const PrecompiledHeaderStorageInterface &) = delete;
PrecompiledHeaderStorageInterface &operator=(const PrecompiledHeaderStorageInterface &) = delete;
virtual void insertPrecompiledHeader(Utils::SmallStringView projectPartName,
virtual void insertProjectPrecompiledHeader(Utils::SmallStringView projectPartName,
Utils::SmallStringView pchPath,
long long pchBuildTime) = 0;
virtual void deletePrecompiledHeader(Utils::SmallStringView projectPartName) = 0;
long long pchBuildTime)
= 0;
virtual void deleteProjectPrecompiledHeader(Utils::SmallStringView projectPartName) = 0;
virtual void insertSystemPrecompiledHeader(Utils::SmallStringView projectPartName,
Utils::SmallStringView pchPath,
long long pchBuildTime)
= 0;
virtual void deleteSystemPrecompiledHeader(Utils::SmallStringView projectPartName) = 0;
virtual Utils::PathString fetchSystemPrecompiledHeaderPath(
Utils::SmallStringView projectPartName) = 0;
protected:
~PrecompiledHeaderStorageInterface() = default;

View File

@@ -90,7 +90,7 @@ void ProjectPartQueue::removeProjectParts(const Utils::SmallStringVector &projec
void ProjectPartQueue::processEntries()
{
uint taskCount = m_taskScheduler.freeSlots();
uint taskCount = m_taskScheduler.slotUsage().free;
auto newEnd = std::prev(m_projectParts.end(), std::min<int>(int(taskCount), int(m_projectParts.size())));
m_taskScheduler.addTasks(
@@ -112,13 +112,13 @@ std::vector<ProjectPartQueue::Task> ProjectPartQueue::createPchTasks(
auto convert = [this] (auto &&projectPart) {
return [projectPart=std::move(projectPart), this] (PchCreatorInterface &pchCreator) {
pchCreator.generatePch(projectPart);
pchCreator.generatePchDeprecated(projectPart);
const auto &projectPartPch = pchCreator.projectPartPch();
Sqlite::ImmediateTransaction transaction(m_transactionsInterface);
if (projectPartPch.pchPath.empty()) {
m_precompiledHeaderStorage.deletePrecompiledHeader(projectPartPch.projectPartId);
m_precompiledHeaderStorage.deleteProjectPrecompiledHeader(projectPartPch.projectPartId);
} else {
m_precompiledHeaderStorage.insertPrecompiledHeader(projectPartPch.projectPartId,
m_precompiledHeaderStorage.insertProjectPrecompiledHeader(projectPartPch.projectPartId,
projectPartPch.pchPath,
projectPartPch.lastModified);
}

View File

@@ -99,14 +99,15 @@ public:
return m_futures;
}
uint freeSlots()
SlotUsage slotUsage()
{
removeFinishedFutures();
if (m_isDisabled)
return 0;
return {};
return uint(std::max(int(m_hardwareConcurrency) - int(m_futures.size()), 0));
return {uint(std::max(int(m_hardwareConcurrency) - int(m_futures.size()), 0)),
uint(m_futures.size())};
}
void syncTasks()

View File

@@ -31,6 +31,12 @@ namespace ClangBackEnd {
using uint = unsigned int;
struct SlotUsage
{
uint free = 0;
uint used = 0;
};
template <typename Task>
class TaskSchedulerInterface
{
@@ -40,7 +46,7 @@ public:
TaskSchedulerInterface &operator=(const TaskSchedulerInterface &) = delete;
virtual void addTasks(std::vector<Task> &&tasks) = 0;
virtual uint freeSlots() = 0;
virtual SlotUsage slotUsage() = 0;
protected:
~TaskSchedulerInterface() = default;

View File

@@ -94,7 +94,7 @@ public:
void processEntries()
{
uint taskCount = m_symbolIndexerScheduler.freeSlots();
uint taskCount = m_symbolIndexerScheduler.slotUsage().free;
auto newEnd = std::prev(m_tasks.end(), std::min<int>(int(taskCount), int(m_tasks.size())));
m_symbolIndexerScheduler.addTasks({std::make_move_iterator(newEnd),

View File

@@ -105,7 +105,7 @@ public:
m_indexerScheduler.disable();
while (!m_indexerScheduler.futures().empty()) {
m_indexerScheduler.syncTasks();
m_indexerScheduler.freeSlots();
m_indexerScheduler.slotUsage();
}
}

View File

@@ -332,7 +332,7 @@ public:
m_database
};
mutable ReadStatement m_getPrecompiledHeader{
"SELECT pchPath, pchBuildTime FROM precompiledHeaders WHERE projectPartId = ?",
"SELECT projectPchPath, projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?",
m_database
};
};

View File

@@ -90,7 +90,7 @@ protected:
.Times(AnyNumber());
EXPECT_CALL(selectAllSources, valuesReturnStdVectorSource(_))
.Times(AnyNumber());
EXPECT_CALL(selectDirectoryPathFromDirectoriesByDirectoryId, valueReturnPathString(_))
EXPECT_CALL(selectDirectoryPathFromDirectoriesByDirectoryId, valueReturnPathString(An<int>()))
.Times(AnyNumber());
EXPECT_CALL(selectSourceNameAndDirectoryIdFromSourcesBySourceId, valueReturnSourceNameAndDirectoryId(_))
.Times(AnyNumber());

View File

@@ -1033,8 +1033,8 @@ std::ostream &operator<<(std::ostream &out, const PchCreatorIncludes &includes)
}
std::ostream &operator<<(std::ostream &out, const PchTask &task)
{
return out << "(" << task.projectPartId << ", " << task.dependentIds << ", " << task.includes
<< ", " << task.compilerMacros << ", " << task.usedMacros << ")";
return out << "(" << task.projectPartIds << ", " << task.includes << ", " << task.compilerMacros
<< ", " << task.usedMacros << ")";
}
std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency)
@@ -1048,6 +1048,11 @@ std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency)
<< ")";
}
std::ostream &operator<<(std::ostream &out, const SlotUsage &slotUsage)
{
return out << "(" << slotUsage.free << ", " << slotUsage.used << ")";
}
const char *sourceTypeString(SourceType sourceType)
{
using ClangBackEnd::SymbolTag;

View File

@@ -175,6 +175,7 @@ class PchTask;
class BuildDependency;
class SourceEntry;
class FilePathCaching;
class SlotUsage;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -259,6 +260,7 @@ std::ostream &operator<<(std::ostream &out, const PchCreatorIncludes &includes);
std::ostream &operator<<(std::ostream &out, const PchTask &task);
std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency);
std::ostream &operator<<(std::ostream &out, const SourceEntry &entry);
std::ostream &operator<<(std::ostream &out, const SlotUsage &slotUsage);
void PrintTo(const FilePath &filePath, ::std::ostream *os);
void PrintTo(const FilePathView &filePathView, ::std::ostream *os);

View File

@@ -35,21 +35,13 @@
class MockPchCreator : public ClangBackEnd::PchCreatorInterface
{
public:
MOCK_METHOD1(generatePch,
void(const ClangBackEnd::V2::ProjectPartContainer &projectPart));
MOCK_METHOD0(takeProjectIncludes,
ClangBackEnd::IdPaths());
MOCK_METHOD0(projectPartPch,
const ClangBackEnd::ProjectPartPch &());
MOCK_METHOD1(setUnsavedFiles,
void (const ClangBackEnd::V2::FileContainers &fileContainers));
MOCK_METHOD0(clear,
void());
MOCK_METHOD0(doInMainThreadAfterFinished,
void());
MOCK_CONST_METHOD0(isUsed,
bool());
MOCK_METHOD1(setIsUsed,
void(bool));
MOCK_METHOD1(generatePchDeprecated, void(const ClangBackEnd::V2::ProjectPartContainer &projectPart));
MOCK_METHOD1(generatePch, void(const ClangBackEnd::PchTask &pchTask));
MOCK_METHOD0(takeProjectIncludes, ClangBackEnd::IdPaths());
MOCK_METHOD0(projectPartPch, const ClangBackEnd::ProjectPartPch &());
MOCK_METHOD1(setUnsavedFiles, void(const ClangBackEnd::V2::FileContainers &fileContainers));
MOCK_METHOD0(clear, void());
MOCK_METHOD0(doInMainThreadAfterFinished, void());
MOCK_CONST_METHOD0(isUsed, bool());
MOCK_METHOD1(setIsUsed, void(bool));
};

View File

@@ -32,10 +32,16 @@
class MockPrecompiledHeaderStorage : public ClangBackEnd::PrecompiledHeaderStorageInterface
{
public:
MOCK_METHOD3(insertPrecompiledHeader,
void (Utils::SmallStringView projectPartName,
MOCK_METHOD3(insertProjectPrecompiledHeader,
void(Utils::SmallStringView projectPartName,
Utils::SmallStringView pchPath,
long long pchBuildTime));
MOCK_METHOD1(deletePrecompiledHeader, void (Utils::SmallStringView projectPartName));
MOCK_METHOD1(deleteProjectPrecompiledHeader, void(Utils::SmallStringView projectPartName));
MOCK_METHOD3(insertSystemPrecompiledHeader,
void(Utils::SmallStringView projectPartName,
Utils::SmallStringView pchPath,
long long pchBuildTime));
MOCK_METHOD1(deleteSystemPrecompiledHeader, void(Utils::SmallStringView projectPartName));
MOCK_METHOD1(fetchSystemPrecompiledHeaderPath,
Utils::PathString(Utils::SmallStringView projectPartName));
};

View File

@@ -137,6 +137,13 @@ MockSqliteReadStatement::value<Utils::PathString>(const int &directoryId)
return valueReturnPathString(directoryId);
}
template <>
Utils::optional<Utils::PathString>
MockSqliteReadStatement::value<Utils::PathString>(const Utils::SmallStringView &path)
{
return valueReturnPathString(path);
}
template <>
Utils::optional<ClangBackEnd::ProjectPartArtefact>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const int& sourceId)

View File

@@ -96,6 +96,9 @@ public:
MOCK_METHOD1(valueReturnPathString,
Utils::optional<Utils::PathString>(int));
MOCK_METHOD1(valueReturnPathString,
Utils::optional<Utils::PathString>(Utils::SmallStringView));
MOCK_METHOD1(valueReturnSmallString,
Utils::optional<Utils::SmallString>(int));
@@ -221,6 +224,10 @@ template <>
Utils::optional<Utils::PathString>
MockSqliteReadStatement::value<Utils::PathString>(const int&);
template <>
Utils::optional<Utils::PathString>
MockSqliteReadStatement::value<Utils::PathString>(const Utils::SmallStringView&);
template <>
Utils::optional<ClangBackEnd::ProjectPartArtefact>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const int&);

View File

@@ -36,8 +36,8 @@ class MockTaskScheduler : public ClangBackEnd::TaskSchedulerInterface<Task>
public:
MOCK_METHOD1_T(addTasks,
void (const std::vector<Task> &));
MOCK_METHOD0(freeSlots,
uint ());
MOCK_METHOD0(slotUsage,
ClangBackEnd::SlotUsage ());
void addTasks(std::vector<Task> &&tasks)
{

View File

@@ -223,14 +223,14 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArguments)
TEST_F(PchCreatorVerySlowTest, IncludesForCreatePchsForProjectParts)
{
creator.generatePch(projectPart1);
creator.generatePchDeprecated(projectPart1);
ASSERT_THAT(creator.takeProjectIncludes().id, "project1");
}
TEST_F(PchCreatorVerySlowTest, ProjectPartPchsSendToPchManagerClient)
{
creator.generatePch(projectPart1);
creator.generatePchDeprecated(projectPart1);
EXPECT_CALL(mockPchManagerClient,
precompiledHeadersUpdated(
@@ -242,7 +242,7 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchsSendToPchManagerClient)
TEST_F(PchCreatorVerySlowTest, UpdateFileWatcherIncludes)
{
creator.generatePch(projectPart1);
creator.generatePchDeprecated(projectPart1);
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(creator.projectIncludes())));
@@ -252,7 +252,7 @@ TEST_F(PchCreatorVerySlowTest, UpdateFileWatcherIncludes)
TEST_F(PchCreatorVerySlowTest, IdPathsForCreatePchsForProjectParts)
{
creator.generatePch(projectPart1);
creator.generatePchDeprecated(projectPart1);
ASSERT_THAT(creator.takeProjectIncludes(),
AllOf(Field(&IdPaths::id, "project1"),
@@ -263,7 +263,7 @@ TEST_F(PchCreatorVerySlowTest, IdPathsForCreatePchsForProjectParts)
TEST_F(PchCreatorVerySlowTest, ProjectPartPchForCreatesPchForProjectPart)
{
creator.generatePch(projectPart1);
creator.generatePchDeprecated(projectPart1);
ASSERT_THAT(creator.projectPartPch(),
AllOf(Field(&ProjectPartPch::projectPartId, Eq("project1")),
@@ -273,7 +273,7 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchForCreatesPchForProjectPart)
TEST_F(PchCreatorVerySlowTest, ProjectPartPchCleared)
{
creator.generatePch(projectPart1);
creator.generatePchDeprecated(projectPart1);
creator.clear();
@@ -283,7 +283,7 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchCleared)
TEST_F(PchCreatorVerySlowTest, ProjectIncludesCleared)
{
creator.generatePch(projectPart1);
creator.generatePchDeprecated(projectPart1);
creator.clear();
@@ -299,7 +299,7 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesNoPchForProjectPart
{},
{id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")}};
creator.generatePch(faultyProjectPart);
creator.generatePchDeprecated(faultyProjectPart);
ASSERT_THAT(creator.projectPartPch(),
AllOf(Field(&ProjectPartPch::projectPartId, Eq("faultyProject")),

View File

@@ -80,7 +80,7 @@ TEST_F(PchTaskGenerator, Create)
EXPECT_CALL(mockPchTaskMerger,
mergeTasks(ElementsAre(
AllOf(Field(&PchTaskSet::system,
AllOf(Field(&PchTask::projectPartId, Eq("ProjectPart1")),
AllOf(Field(&PchTask::projectPartIds, ElementsAre("ProjectPart1")),
Field(&PchTask::includes, ElementsAre(4, 5)),
Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"SE", "4", 4},
@@ -88,7 +88,8 @@ TEST_F(PchTaskGenerator, Create)
Field(&PchTask::usedMacros,
ElementsAre(UsedMacro{"SE", 4}, UsedMacro{"WU", 5})))),
AllOf(Field(&PchTaskSet::project,
AllOf(Field(&PchTask::projectPartId, Eq("ProjectPart1")),
AllOf(Field(&PchTask::projectPartIds,
ElementsAre("ProjectPart1")),
Field(&PchTask::includes, ElementsAre(1, 3)),
Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"YI", "1", 1},

View File

@@ -0,0 +1,343 @@
/****************************************************************************
**
** Copyright (C) 2018 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 "mockpchcreator.h"
#include "mockprecompiledheaderstorage.h"
#include "mocksqlitetransactionbackend.h"
#include "mocktaskscheduler.h"
#include <pchtaskqueue.h>
#include <progresscounter.h>
namespace {
using ClangBackEnd::PchTask;
using ClangBackEnd::SlotUsage;
class PchTaskQueue : public testing::Test
{
protected:
NiceMock<MockTaskScheduler<ClangBackEnd::PchTaskQueue::Task>> mockSytemPchTaskScheduler;
NiceMock<MockTaskScheduler<ClangBackEnd::PchTaskQueue::Task>> mockProjectPchTaskScheduler;
MockPrecompiledHeaderStorage mockPrecompiledHeaderStorage;
MockSqliteTransactionBackend mockSqliteTransactionBackend;
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};
ClangBackEnd::PchTaskQueue queue{mockSytemPchTaskScheduler,
mockProjectPchTaskScheduler,
progressCounter,
mockPrecompiledHeaderStorage,
mockSqliteTransactionBackend};
PchTask systemTask1{"ProjectPart1",
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}};
PchTask systemTask2{"ProjectPart2",
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}};
PchTask systemTask2b{"ProjectPart2",
{3, 4},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}};
PchTask systemTask3{"ProjectPart3",
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}};
PchTask projectTask1{"ProjectPart1",
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}}};
PchTask projectTask2{"ProjectPart2",
{11, 12},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}}};
PchTask projectTask2b{"ProjectPart2",
{21, 22},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}}};
PchTask projectTask3{"ProjectPart3",
{21, 22},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}}};
PchTask systemTask4{Utils::SmallStringVector{"ProjectPart1", "ProjectPart3"},
{1, 2},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}}};
};
TEST_F(PchTaskQueue, AddProjectPchTask)
{
queue.addProjectPchTasks({projectTask1});
queue.addProjectPchTasks({projectTask2});
ASSERT_THAT(queue.projectPchTasks(), ElementsAre(projectTask1, projectTask2));
}
TEST_F(PchTaskQueue, AddSystemPchTask)
{
queue.addSystemPchTasks({systemTask1});
queue.addSystemPchTasks({systemTask2});
ASSERT_THAT(queue.systemPchTasks(), ElementsAre(systemTask1, systemTask2));
}
TEST_F(PchTaskQueue, AddProjectPchTasksCallsProcessEntriesForSystemTaskSchedulerIsNotBusy)
{
InSequence s;
EXPECT_CALL(mockSytemPchTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 0}));
EXPECT_CALL(mockProjectPchTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 0}));
EXPECT_CALL(mockProjectPchTaskScheduler, addTasks(SizeIs(2)));
queue.addProjectPchTasks({projectTask1, projectTask2});
}
TEST_F(PchTaskQueue, AddProjectPchTasksCallsProcessEntriesForSystemTaskSchedulerIsBusy)
{
InSequence s;
EXPECT_CALL(mockSytemPchTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 1}));
EXPECT_CALL(mockProjectPchTaskScheduler, slotUsage()).Times(0);
EXPECT_CALL(mockProjectPchTaskScheduler, addTasks(_)).Times(0);
queue.addProjectPchTasks({projectTask1, projectTask2});
}
TEST_F(PchTaskQueue, AddSystemPchTasksCallsProcessEntries)
{
InSequence s;
EXPECT_CALL(mockSytemPchTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 0}));
EXPECT_CALL(mockSytemPchTaskScheduler, addTasks(SizeIs(2)));
EXPECT_CALL(mockSytemPchTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 1}));
EXPECT_CALL(mockProjectPchTaskScheduler, slotUsage()).Times(0);
EXPECT_CALL(mockProjectPchTaskScheduler, addTasks(_)).Times(0);
queue.addSystemPchTasks({projectTask1, projectTask2});
}
TEST_F(PchTaskQueue, AddProjectPchTasksCallsProgressCounter)
{
queue.addProjectPchTasks({projectTask1, projectTask2});
EXPECT_CALL(mockSetProgressCallback, Call(0, 3));
queue.addProjectPchTasks({projectTask2b, projectTask3});
}
TEST_F(PchTaskQueue, AddSystemPchTasksCallsProgressCounter)
{
queue.addSystemPchTasks({systemTask1, systemTask2});
EXPECT_CALL(mockSetProgressCallback, Call(0, 3));
queue.addSystemPchTasks({systemTask2b, systemTask3});
}
TEST_F(PchTaskQueue, AddPchCallsProgressCounter)
{
queue.addSystemPchTasks({systemTask1, systemTask2});
EXPECT_CALL(mockSetProgressCallback, Call(0, 3));
queue.addSystemPchTasks({systemTask2b, systemTask3});
}
TEST_F(PchTaskQueue, ReplaceIdenticalProjectPchTasks)
{
queue.addProjectPchTasks({projectTask1, projectTask2});
queue.addProjectPchTasks({projectTask1, projectTask2});
ASSERT_THAT(queue.projectPchTasks(), ElementsAre(projectTask1, projectTask2));
}
TEST_F(PchTaskQueue, ReplaceIdenticalSystemPchTasks)
{
queue.addSystemPchTasks({systemTask1, systemTask2});
queue.addSystemPchTasks({systemTask1, systemTask2});
ASSERT_THAT(queue.systemPchTasks(), ElementsAre(systemTask1, systemTask2));
}
TEST_F(PchTaskQueue, ReplaceProjectPchTasksWithSameId)
{
queue.addProjectPchTasks({projectTask1, projectTask2});
queue.addProjectPchTasks({projectTask1, projectTask2b, projectTask3});
ASSERT_THAT(queue.projectPchTasks(), ElementsAre(projectTask1, projectTask2b, projectTask3));
}
TEST_F(PchTaskQueue, ReplaceSystemPchTasksWithSameId)
{
queue.addSystemPchTasks({systemTask1, systemTask2});
queue.addSystemPchTasks({systemTask1, systemTask2b, systemTask3});
ASSERT_THAT(queue.systemPchTasks(), ElementsAre(systemTask1, systemTask2b, systemTask3));
}
TEST_F(PchTaskQueue, RemoveProjectPchTasksByProjectPartId)
{
queue.addProjectPchTasks({projectTask1, projectTask2, projectTask3});
queue.removePchTasks(projectTask2.projectPartIds);
ASSERT_THAT(queue.projectPchTasks(), ElementsAre(projectTask1, projectTask3));
}
TEST_F(PchTaskQueue, DontRemoveSystemPchTasksByProjectPartId)
{
queue.addSystemPchTasks({systemTask1, systemTask2, systemTask3});
queue.removePchTasks(systemTask2.projectPartIds);
ASSERT_THAT(queue.systemPchTasks(), ElementsAre(systemTask1, systemTask2, systemTask3));
}
TEST_F(PchTaskQueue, RemovePchTasksCallsProgressCounter)
{
queue.addSystemPchTasks({systemTask1, systemTask2, systemTask3});
queue.addProjectPchTasks({projectTask1, projectTask2, projectTask3});
EXPECT_CALL(mockSetProgressCallback, Call(0, 5));
queue.removePchTasks(systemTask2.projectPartIds);
}
TEST_F(PchTaskQueue, CreateProjectTasksSizeEqualsInputSize)
{
auto tasks = queue.createProjectTasks({projectTask1, projectTask1});
ASSERT_THAT(tasks, SizeIs(2));
}
TEST_F(PchTaskQueue, CreateProjectTaskFromPchTask)
{
InSequence s;
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{"", "/path/to/pch", 99};
auto tasks = queue.createProjectTasks({projectTask1});
auto projectTask = projectTask1;
projectTask.systemPchPath = "/path/to/pch";
EXPECT_CALL(mockSqliteTransactionBackend, lock());
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchSystemPrecompiledHeaderPath(Eq("ProjectPart1")))
.WillOnce(Return(Utils::PathString{"/path/to/pch"}));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockSqliteTransactionBackend, unlock());
EXPECT_CALL(mockPchCreator, generatePch(Eq(projectTask)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockSqliteTransactionBackend, lock());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockPrecompiledHeaderStorage,
insertProjectPrecompiledHeader(Eq("ProjectPart1"), Eq("/path/to/pch"), 99));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockSqliteTransactionBackend, unlock());
tasks.front()(mockPchCreator);
}
TEST_F(PchTaskQueue, DeleteProjectPchEntryInDatabaseIfNoPchIsGenerated)
{
InSequence s;
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{"", "", 0};
auto tasks = queue.createProjectTasks({projectTask1});
auto projectTask = projectTask1;
projectTask.systemPchPath = "/path/to/pch";
EXPECT_CALL(mockSqliteTransactionBackend, lock());
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchSystemPrecompiledHeaderPath(Eq("ProjectPart1")))
.WillOnce(Return(Utils::PathString{"/path/to/pch"}));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockSqliteTransactionBackend, unlock());
EXPECT_CALL(mockPchCreator, generatePch(Eq(projectTask)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockSqliteTransactionBackend, lock());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockPrecompiledHeaderStorage, deleteProjectPrecompiledHeader(Eq("ProjectPart1")));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockSqliteTransactionBackend, unlock());
tasks.front()(mockPchCreator);
}
TEST_F(PchTaskQueue, CreateSystemTasksSizeEqualsInputSize)
{
auto tasks = queue.createSystemTasks({systemTask1, systemTask2});
ASSERT_THAT(tasks, SizeIs(2));
}
TEST_F(PchTaskQueue, CreateSystemTaskFromPchTask)
{
InSequence s;
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{"", "/path/to/pch", 99};
auto tasks = queue.createSystemTasks({systemTask4});
EXPECT_CALL(mockPchCreator, generatePch(Eq(systemTask4)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockSqliteTransactionBackend, lock());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockPrecompiledHeaderStorage,
insertSystemPrecompiledHeader(Eq("ProjectPart1"), Eq("/path/to/pch"), 99));
EXPECT_CALL(mockPrecompiledHeaderStorage,
insertSystemPrecompiledHeader(Eq("ProjectPart3"), Eq("/path/to/pch"), 99));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockSqliteTransactionBackend, unlock());
tasks.front()(mockPchCreator);
}
TEST_F(PchTaskQueue, DeleteSystemPchEntryInDatabaseIfNoPchIsGenerated)
{
InSequence s;
MockPchCreator mockPchCreator;
ClangBackEnd::ProjectPartPch projectPartPch{"", "", 0};
auto tasks = queue.createSystemTasks({systemTask4});
EXPECT_CALL(mockPchCreator, generatePch(Eq(systemTask4)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockSqliteTransactionBackend, lock());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockPrecompiledHeaderStorage, deleteSystemPrecompiledHeader(Eq("ProjectPart1")));
EXPECT_CALL(mockPrecompiledHeaderStorage, deleteSystemPrecompiledHeader(Eq("ProjectPart3")));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockSqliteTransactionBackend, unlock());
tasks.front()(mockPchCreator);
}
} // namespace

View File

@@ -29,6 +29,7 @@
#include <precompiledheaderstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
#include <sqlitetransaction.h>
@@ -41,9 +42,17 @@ class PrecompiledHeaderStorage : public testing::Test
protected:
NiceMock<MockSqliteDatabase> database;
Storage storage{database};
MockSqliteWriteStatement &insertPrecompiledHeaderStatement = storage.m_insertPrecompiledHeaderStatement;
MockSqliteWriteStatement &insertProjectPartStatement = storage.m_insertProjectPartStatement;
MockSqliteWriteStatement &deletePrecompiledHeaderStatement = storage.m_deletePrecompiledHeaderStatement;
MockSqliteWriteStatement &insertProjectPrecompiledHeaderStatement
= storage.m_insertProjectPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteProjectPrecompiledHeaderStatement
= storage.m_deleteProjectPrecompiledHeaderStatement;
MockSqliteWriteStatement &insertSystemPrecompiledHeaderStatement
= storage.m_insertSystemPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteSystemPrecompiledHeaderStatement
= storage.m_deleteSystemPrecompiledHeaderStatement;
MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement
= storage.m_fetchSystemPrecompiledHeaderPathStatement;
};
TEST_F(PrecompiledHeaderStorage, UseTransaction)
@@ -56,76 +65,112 @@ TEST_F(PrecompiledHeaderStorage, UseTransaction)
Storage storage{database};
}
TEST_F(PrecompiledHeaderStorage, InsertPrecompiledHeader)
TEST_F(PrecompiledHeaderStorage, InsertProjectPrecompiledHeader)
{
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertPrecompiledHeaderStatement,
EXPECT_CALL(insertProjectPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(database, commit());
storage.insertPrecompiledHeader("project1", "/path/to/pch", 22);
storage.insertProjectPrecompiledHeader("project1", "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, InsertPrecompiledHeaderStatementIsBusy)
TEST_F(PrecompiledHeaderStorage, InsertProjectPrecompiledHeaderStatementIsBusy)
{
InSequence s;
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertPrecompiledHeaderStatement,
EXPECT_CALL(insertProjectPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(database, commit());
storage.insertPrecompiledHeader("project1", "/path/to/pch", 22);
storage.insertProjectPrecompiledHeader("project1", "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, DeletePrecompiledHeader)
TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeader)
{
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deletePrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(database, commit());
storage.deletePrecompiledHeader("project1");
storage.deleteProjectPrecompiledHeader("project1");
}
TEST_F(PrecompiledHeaderStorage, DeletePrecompiledHeaderStatementIsBusy)
TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeaderStatementIsBusy)
{
InSequence s;
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deletePrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(database, commit());
storage.deletePrecompiledHeader("project1");
storage.deleteProjectPrecompiledHeader("project1");
}
TEST_F(PrecompiledHeaderStorage, InsertPrecompiledHeaderStatement)
TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeader)
{
ASSERT_THAT(insertPrecompiledHeaderStatement.sqlStatement,
Eq("INSERT OR REPLACE INTO precompiledHeaders(projectPartId, pchPath, pchBuildTime) VALUES((SELECT projectPartId FROM projectParts WHERE projectPartName = ?),?,?)"));
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(database, commit());
storage.insertSystemPrecompiledHeader("project1", "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, InsertProjectPartStatement)
TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeaderStatementIsBusy)
{
ASSERT_THAT(insertProjectPartStatement.sqlStatement,
Eq("INSERT OR IGNORE INTO projectParts(projectPartName) VALUES (?)"));
InSequence s;
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(insertProjectPartStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(insertSystemPrecompiledHeaderStatement,
write(TypedEq<Utils::SmallStringView>("project1"),
TypedEq<Utils::SmallStringView>("/path/to/pch"),
TypedEq<long long>(22)));
EXPECT_CALL(database, commit());
storage.insertSystemPrecompiledHeader("project1", "/path/to/pch", 22);
}
TEST_F(PrecompiledHeaderStorage, DeletePrecompiledHeaderStatement)
TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeader)
{
ASSERT_THAT(deletePrecompiledHeaderStatement.sqlStatement,
Eq("DELETE FROM precompiledHeaders WHERE projectPartId = (SELECT projectPartId FROM projectParts WHERE projectPartName = ?)"));
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(database, commit());
storage.deleteSystemPrecompiledHeader("project1");
}
TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeaderStatementIsBusy)
{
InSequence s;
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(database, commit());
storage.deleteSystemPrecompiledHeader("project1");
}
TEST_F(PrecompiledHeaderStorage, CompilePrecompiledHeaderStatements)
@@ -136,4 +181,48 @@ TEST_F(PrecompiledHeaderStorage, CompilePrecompiledHeaderStatements)
ASSERT_NO_THROW(ClangBackEnd::PrecompiledHeaderStorage<>{database});
}
TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderCalls)
{
InSequence s;
EXPECT_CALL(database, deferredBegin());
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement,
valueReturnPathString(TypedEq<Utils::SmallStringView>("project1")));
EXPECT_CALL(database, commit());
storage.fetchSystemPrecompiledHeaderPath("project1");
}
TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeader)
{
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement,
valueReturnPathString(TypedEq<Utils::SmallStringView>("project1")))
.WillOnce(Return(Utils::PathString{"/path/to/pch"}));
auto path = storage.fetchSystemPrecompiledHeaderPath("project1");
ASSERT_THAT(path, "/path/to/pch");
}
TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsEmptyPath)
{
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement,
valueReturnPathString(TypedEq<Utils::SmallStringView>("project1")))
.WillOnce(Return(Utils::PathString{}));
auto path = storage.fetchSystemPrecompiledHeaderPath("project1");
ASSERT_THAT(path, IsEmpty());
}
TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsNullOptional)
{
EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement,
valueReturnPathString(TypedEq<Utils::SmallStringView>("project1")))
.WillOnce(Return(Utils::optional<Utils::PathString>{}));
auto path = storage.fetchSystemPrecompiledHeaderPath("project1");
ASSERT_THAT(path, IsEmpty());
}
}

View File

@@ -35,6 +35,9 @@
namespace {
using ClangBackEnd::SlotUsage;
using ClangBackEnd::V2::ProjectPartContainer;
class ProjectPartQueue : public testing::Test
{
protected:
@@ -83,7 +86,7 @@ TEST_F(ProjectPartQueue, AddProjectPartCallsProcessEntries)
{
InSequence s;
EXPECT_CALL(mockTaskScheduler, freeSlots()).WillRepeatedly(Return(2));
EXPECT_CALL(mockTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 0}));
EXPECT_CALL(mockTaskScheduler, addTasks(SizeIs(2)));
queue.addProjectParts({projectPart1, projectPart2});
@@ -148,11 +151,11 @@ TEST_F(ProjectPartQueue, CreateTaskFromProjectPart)
ClangBackEnd::ProjectPartPch projectPartPch{"project1", "/path/to/pch", 99};
auto tasks = queue.createPchTasks({projectPart1});
EXPECT_CALL(mockPchCreator, generatePch(Eq(projectPart1)));
EXPECT_CALL(mockPchCreator, generatePchDeprecated(Eq(projectPart1)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockSqliteTransactionBackend, lock());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockPrecompiledHeaderStorage, insertPrecompiledHeader(Eq("project1"), Eq("/path/to/pch"), 99));
EXPECT_CALL(mockPrecompiledHeaderStorage, insertProjectPrecompiledHeader(Eq("project1"), Eq("/path/to/pch"), 99));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockSqliteTransactionBackend, unlock());
@@ -166,24 +169,15 @@ TEST_F(ProjectPartQueue, DeletePchEntryInDatabaseIfNoPchIsGenerated)
ClangBackEnd::ProjectPartPch projectPartPch{"project1", "", 0};
auto tasks = queue.createPchTasks({projectPart1});
EXPECT_CALL(mockPchCreator, generatePch(Eq(projectPart1)));
EXPECT_CALL(mockPchCreator, generatePchDeprecated(Eq(projectPart1)));
EXPECT_CALL(mockPchCreator, projectPartPch()).WillOnce(ReturnRef(projectPartPch));
EXPECT_CALL(mockSqliteTransactionBackend, lock());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockPrecompiledHeaderStorage, deletePrecompiledHeader(Eq("project1")));
EXPECT_CALL(mockPrecompiledHeaderStorage, deleteProjectPrecompiledHeader(Eq("project1")));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockSqliteTransactionBackend, unlock());
tasks.front()(mockPchCreator);
}
//TEST_F(PchManagerClient, ProjectPartPchRemovedFromDatabase)
//{
// EXPECT_CALL(mockPrecompiledHeaderStorage, deletePrecompiledHeader(TypedEq<Utils::SmallStringView>(projectPartId)));
// projectUpdater.removeProjectParts({QString(projectPartId)});
//}
}

View File

@@ -139,7 +139,7 @@ TEST_F(RefactoringDatabaseInitializer, AddPrecompiledHeaderTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, pchPath TEXT, pchBuildTime INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, projectPchPath TEXT, projectPchBuildTime INTEGER, systemPchPath TEXT, systemPchBuildTime INTEGER)")));
initializer.createPrecompiledHeadersTable();
}
@@ -171,7 +171,7 @@ TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS fileStatuses(sourceId INTEGER PRIMARY KEY, size INTEGER, lastModified INTEGER, buildDependencyTimeStamp INTEGER, isInPrecompiledHeader INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sourceDependencies(sourceId INTEGER, dependencySourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sourceDependencies_sourceId_dependencySourceId ON sourceDependencies(sourceId, dependencySourceId)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, pchPath TEXT, pchBuildTime INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS precompiledHeaders(projectPartId INTEGER PRIMARY KEY, projectPchPath TEXT, projectPchBuildTime INTEGER, systemPchPath TEXT, systemPchBuildTime INTEGER)")));
EXPECT_CALL(mockDatabase, commit());
EXPECT_CALL(mockDatabase, setIsInitialized(true));

View File

@@ -35,6 +35,7 @@ using ClangBackEnd::FilePathId;
using ClangBackEnd::SymbolsCollectorInterface;
using ClangBackEnd::SymbolIndexerTask;
using ClangBackEnd::SymbolStorageInterface;
using ClangBackEnd::SlotUsage;
using Callable = ClangBackEnd::SymbolIndexerTask::Callable;
@@ -167,7 +168,7 @@ TEST_F(SymbolIndexerTaskQueue, ProcessTasksCallsFreeSlotsAndAddTasksInScheduler)
{3, 1, Callable{}},
{5, 1, Callable{}}});
EXPECT_CALL(mockTaskScheduler, freeSlots()).WillRepeatedly(Return(2));
EXPECT_CALL(mockTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 0}));
EXPECT_CALL(mockTaskScheduler, addTasks(SizeIs(2)));
queue.processEntries();
@@ -177,7 +178,7 @@ TEST_F(SymbolIndexerTaskQueue, ProcessTasksCallsFreeSlotsAndAddTasksWithNoTaskIn
{
InSequence s;
EXPECT_CALL(mockTaskScheduler, freeSlots()).WillRepeatedly(Return(2));
EXPECT_CALL(mockTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{2, 0}));
EXPECT_CALL(mockTaskScheduler, addTasks(IsEmpty()));
queue.processEntries();
@@ -190,7 +191,7 @@ TEST_F(SymbolIndexerTaskQueue, ProcessTasksCallsFreeSlotsAndMoveAllTasksInSchedu
{3, 1, Callable{}},
{5, 1, Callable{}}});
EXPECT_CALL(mockTaskScheduler, freeSlots()).WillRepeatedly(Return(4));
EXPECT_CALL(mockTaskScheduler, slotUsage()).WillRepeatedly(Return(SlotUsage{4, 0}));
EXPECT_CALL(mockTaskScheduler, addTasks(SizeIs(3)));
queue.processEntries();
@@ -201,7 +202,7 @@ TEST_F(SymbolIndexerTaskQueue, ProcessTasksRemovesProcessedTasks)
queue.addOrUpdateTasks({{1, 1, Callable{}},
{3, 1, Callable{}},
{5, 1, Callable{}}});
ON_CALL(mockTaskScheduler, freeSlots()).WillByDefault(Return(2));
ON_CALL(mockTaskScheduler, slotUsage()).WillByDefault(Return(SlotUsage{2, 0}));
queue.processEntries();

View File

@@ -40,6 +40,7 @@ using Task = std::function<void(ClangBackEnd::ProcessorInterface&)>;
using ClangBackEnd::ProcessorInterface;
using ClangBackEnd::SymbolsCollectorInterface;
using ClangBackEnd::SymbolStorageInterface;
using ClangBackEnd::SlotUsage;
using NiceMockProcessorManager = NiceMock<MockProcessorManager>;
using Scheduler = ClangBackEnd::TaskScheduler<NiceMockProcessorManager, Task>;
@@ -95,18 +96,18 @@ TEST_F(TaskScheduler, FreeSlots)
{
deferredScheduler.addTasks({nocall, nocall});
auto count = deferredScheduler.freeSlots();
auto slotUsage = deferredScheduler.slotUsage();
ASSERT_THAT(count, 2);
ASSERT_THAT(slotUsage, AllOf(Field(&SlotUsage::free, 2), Field(&SlotUsage::used, 2)));
}
TEST_F(TaskScheduler, ReturnZeroFreeSlotsIfMoreCallsThanCores)
{
deferredScheduler.addTasks({nocall, nocall, nocall, nocall, nocall, nocall});
auto count = deferredScheduler.freeSlots();
auto slotUsage = deferredScheduler.slotUsage();
ASSERT_THAT(count, 0);
ASSERT_THAT(slotUsage, AllOf(Field(&SlotUsage::free, 0), Field(&SlotUsage::used, 6)));
}
TEST_F(TaskScheduler, FreeSlotsAfterFinishing)
@@ -114,9 +115,9 @@ TEST_F(TaskScheduler, FreeSlotsAfterFinishing)
scheduler.addTasks({nocall, nocall});
scheduler.syncTasks();
auto count = scheduler.freeSlots();
auto slotUsage = scheduler.slotUsage();
ASSERT_THAT(count, 4);
ASSERT_THAT(slotUsage, AllOf(Field(&SlotUsage::free, 4), Field(&SlotUsage::used, 0)));
}
TEST_F(TaskScheduler, NoFuturesAfterFreeSlots)
@@ -124,7 +125,7 @@ TEST_F(TaskScheduler, NoFuturesAfterFreeSlots)
scheduler.addTasks({nocall, nocall});
scheduler.syncTasks();
scheduler.freeSlots();
scheduler.slotUsage();
ASSERT_THAT(scheduler.futures(), IsEmpty());
}
@@ -142,7 +143,7 @@ TEST_F(TaskScheduler, FreeSlotsCallsCleanupMethodsAfterTheWorkIsDone)
EXPECT_CALL(mockSymbolsCollector, setIsUsed(false));
EXPECT_CALL(mockSymbolsCollector, clear());
scheduler.freeSlots();
scheduler.slotUsage();
}
TEST_F(TaskScheduler, FreeSlotsCallsProgressMethodsAfterTheWorkIsDone)
@@ -153,7 +154,7 @@ TEST_F(TaskScheduler, FreeSlotsCallsProgressMethodsAfterTheWorkIsDone)
EXPECT_CALL(mockSetProgressCallback, Call(2, 100));
scheduler.freeSlots();
scheduler.slotUsage();
}
TEST_F(TaskScheduler, AddTaskCallSymbolsCollectorManagerUnusedSymbolsCollector)

View File

@@ -109,7 +109,8 @@ SOURCES += \
builddependenciesprovider-test.cpp \
builddependenciesstorage-test.cpp \
usedmacrofilter-test.cpp \
pchtasksmerger-test.cpp
pchtasksmerger-test.cpp \
pchtaskqueue-test.cpp
!isEmpty(LIBCLANG_LIBS) {
SOURCES += \