summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2018-12-04 19:03:48 +0100
committerMarco Bubke <marco.bubke@qt.io>2018-12-10 17:09:31 +0000
commit390a227df672a227de4539ad44da46cf773d5810 (patch)
tree885de011d48c96b4db0071afd275f546eccfd728
parent96eb40726604201aa8afe7f0c12e16e0814279af (diff)
downloadqt-creator-390a227df672a227de4539ad44da46cf773d5810.tar.gz
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>
-rw-r--r--src/libs/clangsupport/refactoringdatabaseinitializer.h7
-rw-r--r--src/libs/sqlite/sqlitebasestatement.cpp4
-rw-r--r--src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri6
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreator.cpp7
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreator.h3
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h4
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchtask.h22
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp205
-rw-r--r--src/tools/clangpchmanagerbackend/source/pchtaskqueue.h86
-rw-r--r--src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h95
-rw-r--r--src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h25
-rw-r--r--src/tools/clangpchmanagerbackend/source/projectpartqueue.cpp8
-rw-r--r--src/tools/clangpchmanagerbackend/source/taskscheduler.h7
-rw-r--r--src/tools/clangpchmanagerbackend/source/taskschedulerinterface.h8
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h2
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolindexing.h2
-rw-r--r--src/tools/clangrefactoringbackend/source/symbolstorage.h2
-rw-r--r--tests/unit/unittest/filepathstorage-test.cpp2
-rw-r--r--tests/unit/unittest/gtest-creator-printing.cpp9
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h2
-rw-r--r--tests/unit/unittest/mockpchcreator.h26
-rw-r--r--tests/unit/unittest/mockprecompiledheaderstorage.h18
-rw-r--r--tests/unit/unittest/mocksqlitereadstatement.cpp7
-rw-r--r--tests/unit/unittest/mocksqlitereadstatement.h7
-rw-r--r--tests/unit/unittest/mocktaskscheduler.h4
-rw-r--r--tests/unit/unittest/pchcreator-test.cpp16
-rw-r--r--tests/unit/unittest/pchtaskgenerator-test.cpp5
-rw-r--r--tests/unit/unittest/pchtaskqueue-test.cpp343
-rw-r--r--tests/unit/unittest/precompiledheaderstorage-test.cpp135
-rw-r--r--tests/unit/unittest/projectpartqueue-test.cpp22
-rw-r--r--tests/unit/unittest/refactoringdatabaseinitializer-test.cpp4
-rw-r--r--tests/unit/unittest/symbolindexertaskqueue-test.cpp9
-rw-r--r--tests/unit/unittest/taskscheduler-test.cpp19
-rw-r--r--tests/unit/unittest/unittest.pro3
34 files changed, 980 insertions, 144 deletions
diff --git a/src/libs/clangsupport/refactoringdatabaseinitializer.h b/src/libs/clangsupport/refactoringdatabaseinitializer.h
index cba56475c8..94665409fe 100644
--- a/src/libs/clangsupport/refactoringdatabaseinitializer.h
+++ b/src/libs/clangsupport/refactoringdatabaseinitializer.h
@@ -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);
}
diff --git a/src/libs/sqlite/sqlitebasestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp
index 01cd43facb..87aa3f68b3 100644
--- a/src/libs/sqlite/sqlitebasestatement.cpp
+++ b/src/libs/sqlite/sqlitebasestatement.cpp
@@ -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
diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
index f5a8068b6b..693e110402 100644
--- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
+++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri
@@ -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 += \
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
index 0e58621792..79062b5e2d 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.cpp
@@ -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);
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreator.h b/src/tools/clangpchmanagerbackend/source/pchcreator.h
index 34461dc16b..34170e2bb5 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreator.h
+++ b/src/tools/clangpchmanagerbackend/source/pchcreator.h
@@ -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;
diff --git a/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h b/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h
index c3098577f7..caa2d67649 100644
--- a/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h
+++ b/src/tools/clangpchmanagerbackend/source/pchcreatorinterface.h
@@ -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;
diff --git a/src/tools/clangpchmanagerbackend/source/pchtask.h b/src/tools/clangpchmanagerbackend/source/pchtask.h
index e1439d2ec9..a78b199215 100644
--- a/src/tools/clangpchmanagerbackend/source/pchtask.h
+++ b/src/tools/clangpchmanagerbackend/source/pchtask.h
@@ -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;
diff --git a/src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp b/src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp
new file mode 100644
index 0000000000..6b82290ef1
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchtaskqueue.cpp
@@ -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
diff --git a/src/tools/clangpchmanagerbackend/source/pchtaskqueue.h b/src/tools/clangpchmanagerbackend/source/pchtaskqueue.h
new file mode 100644
index 0000000000..5d00419817
--- /dev/null
+++ b/src/tools/clangpchmanagerbackend/source/pchtaskqueue.h
@@ -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
diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h
index 94c454231e..67ee9b4fe6 100644
--- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h
+++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h
@@ -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};
};
}
diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h
index 9ff6e1efe2..2ade4e885a 100644
--- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h
+++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorageinterface.h
@@ -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;
-
- virtual void insertPrecompiledHeader(Utils::SmallStringView projectPartName,
- Utils::SmallStringView pchPath,
- long long pchBuildTime) = 0;
-
- virtual void deletePrecompiledHeader(Utils::SmallStringView projectPartName) = 0;
+ PrecompiledHeaderStorageInterface(const PrecompiledHeaderStorageInterface &) = delete;
+ PrecompiledHeaderStorageInterface &operator=(const PrecompiledHeaderStorageInterface &) = delete;
+
+ virtual void insertProjectPrecompiledHeader(Utils::SmallStringView projectPartName,
+ Utils::SmallStringView pchPath,
+ 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;
diff --git a/src/tools/clangpchmanagerbackend/source/projectpartqueue.cpp b/src/tools/clangpchmanagerbackend/source/projectpartqueue.cpp
index 07229c23ee..48f133f7d7 100644
--- a/src/tools/clangpchmanagerbackend/source/projectpartqueue.cpp
+++ b/src/tools/clangpchmanagerbackend/source/projectpartqueue.cpp
@@ -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);
}
diff --git a/src/tools/clangpchmanagerbackend/source/taskscheduler.h b/src/tools/clangpchmanagerbackend/source/taskscheduler.h
index c58c867db5..e2891a1163 100644
--- a/src/tools/clangpchmanagerbackend/source/taskscheduler.h
+++ b/src/tools/clangpchmanagerbackend/source/taskscheduler.h
@@ -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()
diff --git a/src/tools/clangpchmanagerbackend/source/taskschedulerinterface.h b/src/tools/clangpchmanagerbackend/source/taskschedulerinterface.h
index a79a3ed8d2..daff16cff8 100644
--- a/src/tools/clangpchmanagerbackend/source/taskschedulerinterface.h
+++ b/src/tools/clangpchmanagerbackend/source/taskschedulerinterface.h
@@ -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;
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h
index c0379b2c29..7ca3513284 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h
+++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h
@@ -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),
diff --git a/src/tools/clangrefactoringbackend/source/symbolindexing.h b/src/tools/clangrefactoringbackend/source/symbolindexing.h
index d20142870e..10e1be0358 100644
--- a/src/tools/clangrefactoringbackend/source/symbolindexing.h
+++ b/src/tools/clangrefactoringbackend/source/symbolindexing.h
@@ -105,7 +105,7 @@ public:
m_indexerScheduler.disable();
while (!m_indexerScheduler.futures().empty()) {
m_indexerScheduler.syncTasks();
- m_indexerScheduler.freeSlots();
+ m_indexerScheduler.slotUsage();
}
}
diff --git a/src/tools/clangrefactoringbackend/source/symbolstorage.h b/src/tools/clangrefactoringbackend/source/symbolstorage.h
index 4aae17c599..02d52bfb50 100644
--- a/src/tools/clangrefactoringbackend/source/symbolstorage.h
+++ b/src/tools/clangrefactoringbackend/source/symbolstorage.h
@@ -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
};
};
diff --git a/tests/unit/unittest/filepathstorage-test.cpp b/tests/unit/unittest/filepathstorage-test.cpp
index f94f3dfad2..be689b44f3 100644
--- a/tests/unit/unittest/filepathstorage-test.cpp
+++ b/tests/unit/unittest/filepathstorage-test.cpp
@@ -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());
diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp
index 072455ab76..098b1b658d 100644
--- a/tests/unit/unittest/gtest-creator-printing.cpp
+++ b/tests/unit/unittest/gtest-creator-printing.cpp
@@ -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;
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 8dd07c4795..db52d584d9 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -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);
diff --git a/tests/unit/unittest/mockpchcreator.h b/tests/unit/unittest/mockpchcreator.h
index 4d1fd24707..992976d4de 100644
--- a/tests/unit/unittest/mockpchcreator.h
+++ b/tests/unit/unittest/mockpchcreator.h
@@ -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));
};
diff --git a/tests/unit/unittest/mockprecompiledheaderstorage.h b/tests/unit/unittest/mockprecompiledheaderstorage.h
index 11493a5560..c267ecb535 100644
--- a/tests/unit/unittest/mockprecompiledheaderstorage.h
+++ b/tests/unit/unittest/mockprecompiledheaderstorage.h
@@ -32,10 +32,16 @@
class MockPrecompiledHeaderStorage : public ClangBackEnd::PrecompiledHeaderStorageInterface
{
public:
- MOCK_METHOD3(insertPrecompiledHeader,
- void (Utils::SmallStringView projectPartName,
- Utils::SmallStringView pchPath,
- long long pchBuildTime));
-
- MOCK_METHOD1(deletePrecompiledHeader, void (Utils::SmallStringView projectPartName));
+ MOCK_METHOD3(insertProjectPrecompiledHeader,
+ void(Utils::SmallStringView projectPartName,
+ Utils::SmallStringView pchPath,
+ long long pchBuildTime));
+ 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));
};
diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp
index 66406f09fa..128b3d899f 100644
--- a/tests/unit/unittest/mocksqlitereadstatement.cpp
+++ b/tests/unit/unittest/mocksqlitereadstatement.cpp
@@ -138,6 +138,13 @@ MockSqliteReadStatement::value<Utils::PathString>(const int &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)
{
diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h
index e5926d2d17..4fbdda2a6d 100644
--- a/tests/unit/unittest/mocksqlitereadstatement.h
+++ b/tests/unit/unittest/mocksqlitereadstatement.h
@@ -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));
@@ -222,6 +225,10 @@ 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&);
diff --git a/tests/unit/unittest/mocktaskscheduler.h b/tests/unit/unittest/mocktaskscheduler.h
index 647e8aefc0..dde6211828 100644
--- a/tests/unit/unittest/mocktaskscheduler.h
+++ b/tests/unit/unittest/mocktaskscheduler.h
@@ -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)
{
diff --git a/tests/unit/unittest/pchcreator-test.cpp b/tests/unit/unittest/pchcreator-test.cpp
index 0b4685891c..8b556af6b7 100644
--- a/tests/unit/unittest/pchcreator-test.cpp
+++ b/tests/unit/unittest/pchcreator-test.cpp
@@ -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")),
diff --git a/tests/unit/unittest/pchtaskgenerator-test.cpp b/tests/unit/unittest/pchtaskgenerator-test.cpp
index 9fb9038012..0cb4c93583 100644
--- a/tests/unit/unittest/pchtaskgenerator-test.cpp
+++ b/tests/unit/unittest/pchtaskgenerator-test.cpp
@@ -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},
diff --git a/tests/unit/unittest/pchtaskqueue-test.cpp b/tests/unit/unittest/pchtaskqueue-test.cpp
new file mode 100644
index 0000000000..2ee1bf3cad
--- /dev/null
+++ b/tests/unit/unittest/pchtaskqueue-test.cpp
@@ -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
diff --git a/tests/unit/unittest/precompiledheaderstorage-test.cpp b/tests/unit/unittest/precompiledheaderstorage-test.cpp
index 3910b9a370..61fdfb5a88 100644
--- a/tests/unit/unittest/precompiledheaderstorage-test.cpp
+++ b/tests/unit/unittest/precompiledheaderstorage-test.cpp
@@ -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, DeleteSystemPrecompiledHeader)
+{
+ InSequence s;
+
+ EXPECT_CALL(database, immediateBegin());
+ EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq<Utils::SmallStringView>("project1")));
+ EXPECT_CALL(database, commit());
+
+ storage.deleteSystemPrecompiledHeader("project1");
}
-TEST_F(PrecompiledHeaderStorage, DeletePrecompiledHeaderStatement)
+TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeaderStatementIsBusy)
{
- ASSERT_THAT(deletePrecompiledHeaderStatement.sqlStatement,
- Eq("DELETE FROM precompiledHeaders WHERE projectPartId = (SELECT projectPartId FROM projectParts WHERE projectPartName = ?)"));
+ 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());
+}
}
diff --git a/tests/unit/unittest/projectpartqueue-test.cpp b/tests/unit/unittest/projectpartqueue-test.cpp
index 0c06a48cd6..65318a3e91 100644
--- a/tests/unit/unittest/projectpartqueue-test.cpp
+++ b/tests/unit/unittest/projectpartqueue-test.cpp
@@ -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)});
-//}
-
-
}
diff --git a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
index ba7d62ddb9..555d742a60 100644
--- a/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
+++ b/tests/unit/unittest/refactoringdatabaseinitializer-test.cpp
@@ -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));
diff --git a/tests/unit/unittest/symbolindexertaskqueue-test.cpp b/tests/unit/unittest/symbolindexertaskqueue-test.cpp
index 83d722cbad..2932310eb0 100644
--- a/tests/unit/unittest/symbolindexertaskqueue-test.cpp
+++ b/tests/unit/unittest/symbolindexertaskqueue-test.cpp
@@ -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();
diff --git a/tests/unit/unittest/taskscheduler-test.cpp b/tests/unit/unittest/taskscheduler-test.cpp
index 337436aeb8..9afc52a724 100644
--- a/tests/unit/unittest/taskscheduler-test.cpp
+++ b/tests/unit/unittest/taskscheduler-test.cpp
@@ -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)
diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro
index 043c7ff0b2..969a8bc6df 100644
--- a/tests/unit/unittest/unittest.pro
+++ b/tests/unit/unittest/unittest.pro
@@ -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 += \