From b2c3e683cffd41faf0c16175924ecaa1da68a781 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 22 Aug 2018 21:13:05 +0200 Subject: [PATCH] ClangRefactoring: Add SymbolIndexerTaskScheduler The scheduler is managing the asynchronous tasks by using the symbols collector manager. Every symbols collector can be used by only one thread, so the we have to pass the symbols collector around by the future interface to make the available again after a task is finished. Change-Id: Ic2eeaa986c2d93978d043216c46e8cb38cea769f Reviewed-by: Ivan Donchevskii --- .../source/clangrefactoringbackend-source.pri | 7 +- .../source/symbolindexertaskqueue.h | 10 +- .../source/symbolindexertaskscheduler.cpp | 86 ++++++++++++ .../source/symbolindexertaskscheduler.h | 75 ++++++++++ .../source/symbolscollector.cpp | 10 ++ .../source/symbolscollector.h | 6 +- .../source/symbolscollectorinterface.h | 3 + .../source/symbolscollectormanagerinterface.h | 43 ++++++ tests/unit/unittest/mocksymbolscollector.h | 6 + .../unittest/mocksymbolscollectormanager.h | 38 +++++ .../unittest/symbolindexertaskqueue-test.cpp | 56 ++++---- .../symbolindexertaskscheduler-test.cpp | 131 ++++++++++++++++++ tests/unit/unittest/unittest.pro | 6 +- 13 files changed, 443 insertions(+), 34 deletions(-) create mode 100644 src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.cpp create mode 100644 src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.h create mode 100644 src/tools/clangrefactoringbackend/source/symbolscollectormanagerinterface.h create mode 100644 tests/unit/unittest/mocksymbolscollectormanager.h create mode 100644 tests/unit/unittest/symbolindexertaskscheduler-test.cpp diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri index 9acad5b394e..9e26d66c38c 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri @@ -24,7 +24,9 @@ HEADERS += \ $$PWD/indexdataconsumer.h \ $$PWD/projectpartqueue.h \ $$PWD/sourcesmanager.h \ - $$PWD/symbolindexertaskqueue.h + $$PWD/symbolindexertaskqueue.h \ + $$PWD/symbolindexertaskscheduler.h \ + $$PWD/symbolscollectormanagerinterface.h !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ @@ -71,4 +73,5 @@ SOURCES += \ $$PWD/projectpartartefact.cpp \ $$PWD/filestatuscache.cpp \ $$PWD/projectpartqueue.cpp \ - $$PWD/symbolindexertaskqueue.cpp + $$PWD/symbolindexertaskqueue.cpp \ + $$PWD/symbolindexertaskscheduler.cpp diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h index 0f5fee1c74c..c1386b98d35 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h +++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskqueue.h @@ -34,14 +34,18 @@ namespace ClangBackEnd { +class SymbolsCollectorInterface; +class SymbolStorageInterface; + class SymbolIndexerTask { public: - using CallableType = std::function; + using Callable = std::function; SymbolIndexerTask(FilePathId filePathId, std::size_t projectPartId, - CallableType &&callable) + Callable &&callable) : callable(std::move(callable)), filePathId(filePathId), projectPartId(projectPartId) @@ -67,7 +71,7 @@ public: } public: - CallableType callable; + Callable callable; FilePathId filePathId; std::size_t projectPartId; }; diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.cpp b/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.cpp new file mode 100644 index 00000000000..bccbd2fe783 --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.cpp @@ -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. +** +****************************************************************************/ + +#include "symbolindexertaskscheduler.h" + +#include +#include + +#include +#include + +namespace ClangBackEnd { + +void SymbolIndexerTaskScheduler::addTasks(std::vector &&tasks) +{ + for (auto &task : tasks) { + auto callWrapper = [task=std::move(task)] ( + std::reference_wrapper symbolsCollector, + std::reference_wrapper symbolStorage) + -> SymbolsCollectorInterface& { + task(symbolsCollector.get(), symbolStorage.get()); + return symbolsCollector; + }; + m_futures.emplace_back(std::async(m_launchPolicy, + std::move(callWrapper), + std::ref(m_symbolsCollectorManager.unusedSymbolsCollector()), + std::ref(m_symbolStorage))); + } +} + +const std::vector &SymbolIndexerTaskScheduler::futures() const +{ + return m_futures; +} + +int SymbolIndexerTaskScheduler::freeSlots() +{ + removeFinishedFutures(); + + return std::max(m_hardware_concurrency - int(m_futures.size()), 0); +} + +void SymbolIndexerTaskScheduler::syncTasks() +{ + for (auto &future : m_futures) + future.wait(); +} + +void SymbolIndexerTaskScheduler::removeFinishedFutures() +{ + auto notReady = [] (Future &future) { + return future.wait_for(std::chrono::duration::zero()) != std::future_status::ready; + }; + + auto split = std::partition(m_futures.begin(), m_futures.end(), notReady); + + std::for_each(split, m_futures.end(), [] (Future &future) { + future.get().setIsUsed(false); + }); + + m_futures.erase(split, m_futures.end()); +} + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.h b/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.h new file mode 100644 index 00000000000..b85dfbb88ef --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/symbolindexertaskscheduler.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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 +#include +#include + +namespace ClangBackEnd { + +class FilePathCachingInterface; +class SymbolsCollectorInterface; +class SymbolsCollectorManagerInterface; +class SymbolStorageInterface; + +class SymbolIndexerTaskScheduler +{ +public: + using Task = std::function; + using Future = std::future; + + SymbolIndexerTaskScheduler(SymbolsCollectorManagerInterface &symbolsCollectorManager, + SymbolStorageInterface &symbolStorage, + int hardware_concurrency, + std::launch launchPolicy = std::launch::async) + : m_symbolsCollectorManager(symbolsCollectorManager), + m_symbolStorage(symbolStorage), + m_hardware_concurrency(hardware_concurrency), + m_launchPolicy(launchPolicy) + {} + + void addTasks(std::vector &&tasks); + + const std::vector &futures() const; + + int freeSlots(); + + void syncTasks(); + +private: + void removeFinishedFutures(); + +private: + std::vector m_futures; + SymbolsCollectorManagerInterface &m_symbolsCollectorManager; + SymbolStorageInterface &m_symbolStorage; + int m_hardware_concurrency; + std::launch m_launchPolicy; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp index b727834523c..490c0745fa2 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollector.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolscollector.cpp @@ -154,4 +154,14 @@ const SourceDependencies &SymbolsCollector::sourceDependencies() const return m_collectMacrosSourceFileCallbacks.sourceDependencies(); } +bool SymbolsCollector::isUsed() const +{ + return m_isUsed; +} + +void SymbolsCollector::setIsUsed(bool isUsed) +{ + m_isUsed = isUsed; +} + } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolscollector.h b/src/tools/clangrefactoringbackend/source/symbolscollector.h index 59d552f0551..d14fef53fe4 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollector.h +++ b/src/tools/clangrefactoringbackend/source/symbolscollector.h @@ -35,7 +35,7 @@ namespace ClangBackEnd { -class SymbolsCollector : public SymbolsCollectorInterface +class SymbolsCollector final : public SymbolsCollectorInterface { public: SymbolsCollector(FilePathCachingInterface &filePathCache); @@ -56,6 +56,9 @@ public: const FileStatuses &fileStatuses() const override; const SourceDependencies &sourceDependencies() const override; + bool isUsed() const override; + void setIsUsed(bool isUsed) override; + private: ClangTool m_clangTool; SymbolEntries m_symbolEntries; @@ -65,6 +68,7 @@ private: CollectMacrosSourceFileCallbacks m_collectMacrosSourceFileCallbacks; SourcesManager m_sourcesManager; FilePathCachingInterface &m_filePathCache; + bool m_isUsed = false; }; } // namespace ClangBackEnd diff --git a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h index 5f5e5bf15da..715e26be1cc 100644 --- a/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h +++ b/src/tools/clangrefactoringbackend/source/symbolscollectorinterface.h @@ -63,6 +63,9 @@ public: virtual const FileStatuses &fileStatuses() const = 0; virtual const SourceDependencies &sourceDependencies() const = 0; + virtual bool isUsed() const = 0; + virtual void setIsUsed(bool isUsed) = 0; + protected: ~SymbolsCollectorInterface() = default; }; diff --git a/src/tools/clangrefactoringbackend/source/symbolscollectormanagerinterface.h b/src/tools/clangrefactoringbackend/source/symbolscollectormanagerinterface.h new file mode 100644 index 00000000000..82a169ff0c3 --- /dev/null +++ b/src/tools/clangrefactoringbackend/source/symbolscollectormanagerinterface.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** 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 + +namespace ClangBackEnd { + +class SymbolsCollectorInterface; + +class SymbolsCollectorManagerInterface +{ +public: + virtual SymbolsCollectorInterface &unusedSymbolsCollector() = 0; + +protected: + ~SymbolsCollectorManagerInterface() = default; +}; + +} // namespace ClangBackEnd diff --git a/tests/unit/unittest/mocksymbolscollector.h b/tests/unit/unittest/mocksymbolscollector.h index 9d8edb4bc30..1eb5eb03cb6 100644 --- a/tests/unit/unittest/mocksymbolscollector.h +++ b/tests/unit/unittest/mocksymbolscollector.h @@ -62,4 +62,10 @@ public: MOCK_CONST_METHOD0(sourceDependencies, const ClangBackEnd::SourceDependencies &()); + + MOCK_CONST_METHOD0(isUsed, + bool()); + + MOCK_METHOD1(setIsUsed, + void(bool)); }; diff --git a/tests/unit/unittest/mocksymbolscollectormanager.h b/tests/unit/unittest/mocksymbolscollectormanager.h new file mode 100644 index 00000000000..aedd196c60a --- /dev/null +++ b/tests/unit/unittest/mocksymbolscollectormanager.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** 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 "googletest.h" + +#include + +class MockSymbolsCollectorManager : public ClangBackEnd::SymbolsCollectorManagerInterface +{ +public: + MOCK_METHOD0(unusedSymbolsCollector, + ClangBackEnd::SymbolsCollectorInterface & ()); + +}; diff --git a/tests/unit/unittest/symbolindexertaskqueue-test.cpp b/tests/unit/unittest/symbolindexertaskqueue-test.cpp index 215acc80bbb..17b9f370c4b 100644 --- a/tests/unit/unittest/symbolindexertaskqueue-test.cpp +++ b/tests/unit/unittest/symbolindexertaskqueue-test.cpp @@ -29,12 +29,16 @@ namespace { -using ClangBackEnd::SymbolIndexerTask; using ClangBackEnd::FilePathId; +using ClangBackEnd::SymbolsCollectorInterface; +using ClangBackEnd::SymbolIndexerTask; +using ClangBackEnd::SymbolStorageInterface; + +using Callable = ClangBackEnd::SymbolIndexerTask::Callable; MATCHER_P2(IsTask, filePathId, projectPartId, std::string(negation ? "is't" : "is") - + PrintToString(SymbolIndexerTask(filePathId, projectPartId, []{}))) + + PrintToString(SymbolIndexerTask(filePathId, projectPartId, Callable{}))) { const SymbolIndexerTask &task = arg; @@ -54,12 +58,12 @@ protected: TEST_F(SymbolIndexerTaskQueue, AddTasks) { - queue.addOrUpdateTasks({{{1, 2}, projectPartId("foo"), [] {}}, - {{1, 4}, projectPartId("foo"), [] {}}}); + queue.addOrUpdateTasks({{{1, 2}, projectPartId("foo"), Callable{}}, + {{1, 4}, projectPartId("foo"), Callable{}}}); - queue.addOrUpdateTasks({{{1, 1}, projectPartId("foo"), [] {}}, - {{1, 3}, projectPartId("foo"), [] {}}, - {{1, 5}, projectPartId("foo"), [] {}}}); + queue.addOrUpdateTasks({{{1, 1}, projectPartId("foo"), Callable{}}, + {{1, 3}, projectPartId("foo"), Callable{}}, + {{1, 5}, projectPartId("foo"), Callable{}}}); ASSERT_THAT(queue.tasks(), ElementsAre(IsTask(FilePathId{1, 1}, projectPartId("foo")), @@ -71,12 +75,12 @@ TEST_F(SymbolIndexerTaskQueue, AddTasks) TEST_F(SymbolIndexerTaskQueue, ReplaceTask) { - queue.addOrUpdateTasks({{{1, 1}, projectPartId("foo"), [] {}}, - {{1, 3}, projectPartId("foo"), [] {}}, - {{1, 5}, projectPartId("foo"), [] {}}}); + queue.addOrUpdateTasks({{{1, 1}, projectPartId("foo"), Callable{}}, + {{1, 3}, projectPartId("foo"), Callable{}}, + {{1, 5}, projectPartId("foo"), Callable{}}}); - queue.addOrUpdateTasks({{{1, 2}, projectPartId("foo"), [] {}}, - {{1, 3}, projectPartId("foo"), [] {}}}); + queue.addOrUpdateTasks({{{1, 2}, projectPartId("foo"), Callable{}}, + {{1, 3}, projectPartId("foo"), Callable{}}}); ASSERT_THAT(queue.tasks(), ElementsAre(IsTask(FilePathId{1, 1}, projectPartId("foo")), @@ -87,12 +91,12 @@ TEST_F(SymbolIndexerTaskQueue, ReplaceTask) TEST_F(SymbolIndexerTaskQueue, AddTaskWithDifferentProjectId) { - queue.addOrUpdateTasks({{{1, 1}, projectPartId("foo"), [] {}}, - {{1, 3}, projectPartId("foo"), [] {}}, - {{1, 5}, projectPartId("foo"), [] {}}}); + queue.addOrUpdateTasks({{{1, 1}, projectPartId("foo"), Callable{}}, + {{1, 3}, projectPartId("foo"), Callable{}}, + {{1, 5}, projectPartId("foo"), Callable{}}}); - queue.addOrUpdateTasks({{{1, 2}, projectPartId("bar"), [] {}}, - {{1, 3}, projectPartId("bar"), [] {}}}); + queue.addOrUpdateTasks({{{1, 2}, projectPartId("bar"), Callable{}}, + {{1, 3}, projectPartId("bar"), Callable{}}}); ASSERT_THAT(queue.tasks(), ElementsAre(IsTask(FilePathId{1, 1}, projectPartId("foo")), @@ -104,15 +108,15 @@ TEST_F(SymbolIndexerTaskQueue, AddTaskWithDifferentProjectId) TEST_F(SymbolIndexerTaskQueue, RemoveTaskByProjectParts) { - queue.addOrUpdateTasks({{{1, 1}, projectPartId("yi"), [] {}}, - {{1, 3}, projectPartId("yi"), [] {}}, - {{1, 5}, projectPartId("yi"), [] {}}}); - queue.addOrUpdateTasks({{{1, 2}, projectPartId("er"), [] {}}, - {{1, 3}, projectPartId("er"), [] {}}}); - queue.addOrUpdateTasks({{{1, 2}, projectPartId("san"), [] {}}, - {{1, 3}, projectPartId("san"), [] {}}}); - queue.addOrUpdateTasks({{{1, 2}, projectPartId("se"), [] {}}, - {{1, 3}, projectPartId("se"), [] {}}}); + queue.addOrUpdateTasks({{{1, 1}, projectPartId("yi"), Callable{}}, + {{1, 3}, projectPartId("yi"), Callable{}}, + {{1, 5}, projectPartId("yi"), Callable{}}}); + queue.addOrUpdateTasks({{{1, 2}, projectPartId("er"), Callable{}}, + {{1, 3}, projectPartId("er"), Callable{}}}); + queue.addOrUpdateTasks({{{1, 2}, projectPartId("san"), Callable{}}, + {{1, 3}, projectPartId("san"), Callable{}}}); + queue.addOrUpdateTasks({{{1, 2}, projectPartId("se"), Callable{}}, + {{1, 3}, projectPartId("se"), Callable{}}}); queue.removeTasks({"er", "san"}); diff --git a/tests/unit/unittest/symbolindexertaskscheduler-test.cpp b/tests/unit/unittest/symbolindexertaskscheduler-test.cpp new file mode 100644 index 00000000000..f7d4be201a7 --- /dev/null +++ b/tests/unit/unittest/symbolindexertaskscheduler-test.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 "mocksymbolscollectormanager.h" +#include "mocksymbolscollector.h" +#include "mocksymbolstorage.h" + +#include + +namespace { + +using ClangBackEnd::SymbolsCollectorInterface; +using ClangBackEnd::SymbolStorageInterface; + +class SymbolIndexerTaskScheduler : public testing::Test +{ +protected: + void SetUp() + { + ON_CALL(mockSymbolsCollectorManager, unusedSymbolsCollector()).WillByDefault(ReturnRef(mockSymbolsCollector)); + } + +protected: + MockFunction mock; + ClangBackEnd::SymbolIndexerTaskScheduler::Task call{ + [&] (SymbolsCollectorInterface &symbolsCollector, + SymbolStorageInterface &symbolStorage) { + mock.Call(); }}; + ClangBackEnd::SymbolIndexerTaskScheduler::Task nocall{ + [&] (SymbolsCollectorInterface &symbolsCollector, + SymbolStorageInterface &symbolStorage) {}}; + NiceMock mockSymbolsCollectorManager; + NiceMock mockSymbolsCollector; + MockSymbolStorage mockSymbolStorage; + ClangBackEnd::SymbolIndexerTaskScheduler scheduler{mockSymbolsCollectorManager, mockSymbolStorage, 4}; + ClangBackEnd::SymbolIndexerTaskScheduler deferedScheduler{mockSymbolsCollectorManager, mockSymbolStorage, 4, std::launch::deferred}; +}; + +TEST_F(SymbolIndexerTaskScheduler, AddTasks) +{ + deferedScheduler.addTasks({nocall}); + + ASSERT_THAT(deferedScheduler.futures(), SizeIs(1)); +} + +TEST_F(SymbolIndexerTaskScheduler, AddTasksCallsFunction) +{ + EXPECT_CALL(mock, Call()).Times(2); + + scheduler.addTasks({call, call}); +} + +TEST_F(SymbolIndexerTaskScheduler, FreeSlots) +{ + deferedScheduler.addTasks({nocall, nocall}); + + auto count = deferedScheduler.freeSlots(); + + ASSERT_THAT(count, 2); +} + +TEST_F(SymbolIndexerTaskScheduler, ReturnZeroFreeSlotsIfMoreCallsThanCores) +{ + deferedScheduler.addTasks({nocall, nocall, nocall, nocall, nocall, nocall}); + + auto count = deferedScheduler.freeSlots(); + + ASSERT_THAT(count, 0); +} + +TEST_F(SymbolIndexerTaskScheduler, FreeSlotsAfterFinishing) +{ + scheduler.addTasks({nocall, nocall}); + scheduler.syncTasks(); + + auto count = scheduler.freeSlots(); + + ASSERT_THAT(count, 4); +} + +TEST_F(SymbolIndexerTaskScheduler, NoFuturesAfterFreeSlots) +{ + scheduler.addTasks({nocall, nocall}); + scheduler.syncTasks(); + + scheduler.freeSlots(); + + ASSERT_THAT(scheduler.futures(), IsEmpty()); +} + +TEST_F(SymbolIndexerTaskScheduler, FreeSlotsCallSymbolsCollectorSetIsUnused) +{ + scheduler.addTasks({nocall, nocall}); + scheduler.syncTasks(); + + EXPECT_CALL(mockSymbolsCollector, setIsUsed(false)).Times(2); + + scheduler.freeSlots(); +} + +TEST_F(SymbolIndexerTaskScheduler, AddTaskCallSymbolsCollectorManagerUnusedSymbolsCollector) +{ + EXPECT_CALL(mockSymbolsCollectorManager, unusedSymbolsCollector()).Times(2); + + scheduler.addTasks({nocall, nocall}); +} +} diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 2cc46876c29..6dd27b53ddc 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -96,7 +96,8 @@ SOURCES += \ projectpartqueue-test.cpp \ generatedfiles-test.cpp \ sourcesmanager-test.cpp \ - symbolindexertaskqueue-test.cpp + symbolindexertaskqueue-test.cpp \ + symbolindexertaskscheduler-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -232,7 +233,8 @@ HEADERS += \ mocksqlitetransactionbackend.h \ mockprojectpartprovider.h \ mockprecompiledheaderstorage.h \ - mockeditormanager.h + mockeditormanager.h \ + mocksymbolscollectormanager.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \ chunksreportedmonitor.h \