diff options
author | Marco Bubke <marco.bubke@qt.io> | 2018-12-04 19:03:48 +0100 |
---|---|---|
committer | Marco Bubke <marco.bubke@qt.io> | 2018-12-10 17:09:31 +0000 |
commit | 390a227df672a227de4539ad44da46cf773d5810 (patch) | |
tree | 885de011d48c96b4db0071afd275f546eccfd728 | |
parent | 96eb40726604201aa8afe7f0c12e16e0814279af (diff) | |
download | qt-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>
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 += \ |