diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesgeneratorinterface.h b/src/tools/clangpchmanagerbackend/source/builddependenciesgeneratorinterface.h new file mode 100644 index 00000000000..f3863d8027b --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/builddependenciesgeneratorinterface.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 "builddependency.h" + +#include "projectpartcontainerv2.h" + +namespace ClangBackEnd { + +class BuildDependenciesGeneratorInterface +{ +public: + virtual BuildDependency create(const V2::ProjectPartContainer &projectPart) = 0; + +protected: + ~BuildDependenciesGeneratorInterface() = default; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.cpp b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.cpp new file mode 100644 index 00000000000..5044f9e294a --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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 "builddependenciesprovider.h" + +#include "builddependenciesstorageinterface.h" +#include "modifiedtimecheckerinterface.h" +#include "builddependenciesgeneratorinterface.h" + +#include + +namespace ClangBackEnd { + +template +OutputContainer setUnion(InputContainer1 &&input1, + InputContainer2 &&input2) +{ + OutputContainer results; + results.reserve(input1.size() + input2.size()); + + std::set_union(std::begin(input1), + std::end(input1), + std::begin(input2), + std::end(input2), + std::back_inserter(results)); + + return results; +} + +BuildDependency BuildDependenciesProvider::create(const V2::ProjectPartContainer &projectPart) const +{ + SourceEntries includes = createSourceEntriesFromStorage(projectPart.sourcePathIds); + + if (!m_modifiedTimeChecker.isUpToDate(includes)) + return m_buildDependenciesGenerator.create(projectPart); + + return createBuildDependencyFromStorage(std::move(includes)); + +} + +BuildDependency BuildDependenciesProvider::createBuildDependencyFromStorage(SourceEntries &&includes) const +{ + BuildDependency buildDependency; + + buildDependency.usedMacros = createUsedMacrosFromStorage(includes); + buildDependency.includes = std::move(includes); + + return buildDependency; +} + +UsedMacros BuildDependenciesProvider::createUsedMacrosFromStorage(const SourceEntries &includes) const +{ + UsedMacros usedMacros; + usedMacros.reserve(1024); + + for (const SourceEntry &entry : includes) { + UsedMacros macros = m_buildDependenciesStorage.fetchUsedMacros(entry.sourceId); + std::sort(macros.begin(), macros.end()); + usedMacros.insert(usedMacros.end(), + std::make_move_iterator(macros.begin()), + std::make_move_iterator(macros.end())); + } + + return usedMacros; +} + +SourceEntries BuildDependenciesProvider::createSourceEntriesFromStorage( + const FilePathIds &sourcePathIds) const +{ + SourceEntries includes; + + for (FilePathId sourcePathId : sourcePathIds) { + SourceEntries entries = m_buildDependenciesStorage.fetchDependSources(sourcePathId); + SourceEntries mergedEntries = setUnion(includes, entries); + + includes = std::move(mergedEntries); + } + + return includes; +} + +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h new file mode 100644 index 00000000000..c9aab60de4e --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/builddependenciesprovider.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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 "builddependenciesproviderinterface.h" + +namespace ClangBackEnd { + +class BuildDependenciesStorageInterface; +class ModifiedTimeCheckerInterface; +class BuildDependenciesGeneratorInterface; + +class BuildDependenciesProvider : public BuildDependenciesProviderInterface +{ +public: + BuildDependenciesProvider(BuildDependenciesStorageInterface &buildDependenciesStorage, + ModifiedTimeCheckerInterface &modifiedTimeChecker, + BuildDependenciesGeneratorInterface &buildDependenciesGenerator) + : m_buildDependenciesStorage(buildDependenciesStorage), + m_modifiedTimeChecker(modifiedTimeChecker), + m_buildDependenciesGenerator(buildDependenciesGenerator) + { + } + + BuildDependency create(const V2::ProjectPartContainer &projectPart) const override; + +private: + BuildDependency createBuildDependencyFromStorage(SourceEntries &&includes) const; + UsedMacros createUsedMacrosFromStorage(const SourceEntries &includes) const; + SourceEntries createSourceEntriesFromStorage(const FilePathIds &sourcePathIds) const; + +private: + BuildDependenciesStorageInterface &m_buildDependenciesStorage; + ModifiedTimeCheckerInterface &m_modifiedTimeChecker; + BuildDependenciesGeneratorInterface &m_buildDependenciesGenerator; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesproviderinterface.h b/src/tools/clangpchmanagerbackend/source/builddependenciesproviderinterface.h index b02831a7bae..f596b83da9b 100644 --- a/src/tools/clangpchmanagerbackend/source/builddependenciesproviderinterface.h +++ b/src/tools/clangpchmanagerbackend/source/builddependenciesproviderinterface.h @@ -25,7 +25,7 @@ #pragma once -#include "builddependencies.h" +#include "builddependency.h" #include "projectpartcontainerv2.h" @@ -34,7 +34,7 @@ namespace ClangBackEnd { class BuildDependenciesProviderInterface { public: - virtual BuildDependency create(const V2::ProjectPartContainer &projectPart) = 0; + virtual BuildDependency create(const V2::ProjectPartContainer &projectPart) const = 0; protected: ~BuildDependenciesProviderInterface() = default; diff --git a/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h b/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h new file mode 100644 index 00000000000..265065b0d0b --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/builddependenciesstorageinterface.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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 +#include +#include + +namespace ClangBackEnd { + +class BuildDependenciesStorageInterface +{ +public: + BuildDependenciesStorageInterface() = default; + BuildDependenciesStorageInterface(const BuildDependenciesStorageInterface &) = delete; + BuildDependenciesStorageInterface &operator=(const BuildDependenciesStorageInterface &) = delete; + + virtual void updateSources(const SourceEntries &sourceIds) = 0; + virtual void insertOrUpdateUsedMacros(const UsedMacros &usedMacros) = 0; + virtual void insertFileStatuses(const FileStatuses &fileStatuses) = 0; + virtual void insertOrUpdateSourceDependencies(const SourceDependencies &sourceDependencies) = 0; + virtual long long fetchLowestLastModifiedTime(FilePathId sourceId) const = 0; + virtual SourceEntries fetchDependSources(FilePathId sourceId) const = 0; + virtual UsedMacros fetchUsedMacros(FilePathId sourceId) const = 0; + +protected: + ~BuildDependenciesStorageInterface() = default; +}; + +} // namespace ClangBackEnd diff --git a/src/tools/clangpchmanagerbackend/source/builddependencies.h b/src/tools/clangpchmanagerbackend/source/builddependency.h similarity index 93% rename from src/tools/clangpchmanagerbackend/source/builddependencies.h rename to src/tools/clangpchmanagerbackend/source/builddependency.h index 9e0eb3f6293..8821b0162c0 100644 --- a/src/tools/clangpchmanagerbackend/source/builddependencies.h +++ b/src/tools/clangpchmanagerbackend/source/builddependency.h @@ -25,18 +25,18 @@ #pragma once -#include - -#include +#include "sourceentry.h" +#include "usedmacro.h" namespace ClangBackEnd { class BuildDependency { public: - FilePathIds includeIds; + SourceEntries includes; FilePathIds topIncludeIds; FilePathIds topsSystemIncludeIds; + UsedMacros usedMacros; }; using BuildDependencies = std::vector; diff --git a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri index ad17b98f18e..4b5ac43a7e0 100644 --- a/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri +++ b/src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri @@ -4,7 +4,8 @@ SOURCES += \ $$PWD/pchmanagerserver.cpp \ $$PWD/projectparts.cpp \ $$PWD/projectpartqueue.cpp \ - $$PWD/pchtaskgenerator.cpp + $$PWD/pchtaskgenerator.cpp \ + $$PWD/builddependenciesprovider.cpp HEADERS += \ $$PWD/pchmanagerserver.h \ @@ -28,7 +29,12 @@ HEADERS += \ $$PWD/pchtaskgenerator.h \ $$PWD/pchtask.h \ $$PWD/builddependenciesproviderinterface.h \ - $$PWD/builddependencies.h + $$PWD/builddependenciesprovider.h \ + $$PWD/builddependenciesstorageinterface.h \ + $$PWD/builddependency.h \ + $$PWD/modifiedtimecheckerinterface.h \ + $$PWD/sourceentry.h \ + $$PWD/builddependenciesgeneratorinterface.h !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ diff --git a/src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h b/src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h new file mode 100644 index 00000000000..c0cae1cf4bb --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/modifiedtimecheckerinterface.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** 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 "sourceentry.h" + +namespace ClangBackEnd { + +class ModifiedTimeCheckerInterface +{ +public: + ModifiedTimeCheckerInterface() = default; + ModifiedTimeCheckerInterface(const ModifiedTimeCheckerInterface &) = delete; + ModifiedTimeCheckerInterface &operator=(const ModifiedTimeCheckerInterface &) = delete; + + virtual bool isUpToDate(const SourceEntries &sourceEntries) const = 0; + +protected: + ~ModifiedTimeCheckerInterface() = default; +}; + +} // namespace ClangBackEnd + diff --git a/src/tools/clangpchmanagerbackend/source/pchtask.h b/src/tools/clangpchmanagerbackend/source/pchtask.h index 39c7bbf01a6..48ae6864ea4 100644 --- a/src/tools/clangpchmanagerbackend/source/pchtask.h +++ b/src/tools/clangpchmanagerbackend/source/pchtask.h @@ -25,7 +25,7 @@ #pragma once -#include "builddependencies.h" +#include "builddependency.h" #include diff --git a/src/tools/clangpchmanagerbackend/source/sourceentry.h b/src/tools/clangpchmanagerbackend/source/sourceentry.h new file mode 100644 index 00000000000..2e0646b987d --- /dev/null +++ b/src/tools/clangpchmanagerbackend/source/sourceentry.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 + +namespace ClangBackEnd { + +enum SourceType : unsigned char +{ + Any, + TopInclude, + TopSystemInclude +}; + +class TimeStamp +{ + using int64 = long long; +public: + TimeStamp(int64 value) + : value(value) + {} + + operator int64() const + { + return value; + } + + int64 value = -1; +}; + +class SourceEntry +{ +public: + friend + bool operator<(SourceEntry first, SourceEntry second) + { + return first.sourceId < second.sourceId; + } + + friend + bool operator==(SourceEntry first, SourceEntry second) + { + return first.sourceId == second.sourceId; + } + +public: + FilePathId sourceId; + SourceType sourceType = SourceType::Any; + TimeStamp lastModified; +}; + +using SourceEntries = std::vector; + +} diff --git a/tests/unit/unittest/builddependenciesprovider-test.cpp b/tests/unit/unittest/builddependenciesprovider-test.cpp new file mode 100644 index 00000000000..c9e29c0ad37 --- /dev/null +++ b/tests/unit/unittest/builddependenciesprovider-test.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** 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 "mockbuilddependencystorage.h" +#include "mockmodifiedtimechecker.h" +#include "mockbuilddependenciesgenerator.h" + +#include + +namespace { + +using ClangBackEnd::BuildDependency; +using ClangBackEnd::BuildDependencies; +using ClangBackEnd::FilePathId; +using ClangBackEnd::FilePathIds; +using ClangBackEnd::SourceEntry; +using ClangBackEnd::SourceEntries; +using ClangBackEnd::SourceType; +using ClangBackEnd::UsedMacro; +using ClangBackEnd::UsedMacros; + +MATCHER_P(HasSourceId, sourceId, std::string(negation ? "hasn't" : "has") + + " sourceId " + PrintToString(sourceId)) +{ + const SourceEntry & sourceEntry = arg; + + return sourceEntry.sourceId.filePathId == sourceId; +} + +class BuildDependenciesProvider : public testing::Test +{ +protected: + NiceMock mockBuildDependenciesStorage; + NiceMock mockModifiedTimeChecker; + NiceMock mockBuildDependenciesGenerator; + ClangBackEnd::BuildDependenciesProvider provider{mockBuildDependenciesStorage, mockModifiedTimeChecker, mockBuildDependenciesGenerator}; + ClangBackEnd::V2::ProjectPartContainer projectPart1{"ProjectPart1", + {"--yi"}, + {{"YI","1"}}, + {"/yi"}, + {{1, 1}}, + {{1, 2}}}; + ClangBackEnd::V2::ProjectPartContainer projectPart2{"ProjectPart2", + {"--er"}, + {{"ER","2"}}, + {"/er"}, + {{1, 1}}, + {{1, 2}, {1, 3}, {1, 4}}}; + SourceEntries firstSources{{{1, 1}, SourceType::Any, 1}, {{1, 2}, SourceType::Any, 1}, {{1, 10}, SourceType::Any, 1}}; + SourceEntries secondSources{{{1, 1}, SourceType::Any, 1}, {{1, 3}, SourceType::Any, 1}, {{1, 8}, SourceType::Any, 1}}; + SourceEntries thirdSources{{{1, 4}, SourceType::Any, 1}, {{1, 8}, SourceType::Any, 1}, {{1, 10}, SourceType::Any, 1}}; + UsedMacros firstUsedMacros{{"YI", {1, 1}}}; + UsedMacros secondUsedMacros{{"LIANG", {1, 2}}, {"ER", {1, 2}}}; + UsedMacros thirdUsedMacros{{"SAN", {1, 10}}}; + BuildDependency buildDependency{secondSources, {}, {}, {}}; +}; + +TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromStorageIfTimeStampsAreUpToDate) +{ + InSequence s; + + EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources(FilePathId{1, 2})).WillRepeatedly(Return(firstSources)); + EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(firstSources)).WillRepeatedly(Return(true)); + EXPECT_CALL(mockBuildDependenciesGenerator, create(projectPart1)).Times(0); + + provider.create(projectPart1); +} + +TEST_F(BuildDependenciesProvider, FetchDependSourcesFromStorage) +{ + ON_CALL(mockBuildDependenciesStorage, fetchDependSources(FilePathId{1, 2})).WillByDefault(Return(firstSources)); + ON_CALL(mockBuildDependenciesStorage, fetchDependSources(FilePathId{1, 3})).WillByDefault(Return(secondSources)); + ON_CALL(mockBuildDependenciesStorage, fetchDependSources(FilePathId{1, 4})).WillByDefault(Return(thirdSources)); + ON_CALL(mockModifiedTimeChecker, isUpToDate(_)).WillByDefault(Return(true)); + + auto buildDependency = provider.create(projectPart2); + + ASSERT_THAT(buildDependency.includes, ElementsAre(HasSourceId(1), HasSourceId(2), HasSourceId(3), HasSourceId(4), HasSourceId(8), HasSourceId(10))); +} + +TEST_F(BuildDependenciesProvider, CreateCallsFetchDependSourcesFromGeneratorIfTimeStampsAreNotUpToDate) +{ + InSequence s; + + EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources(FilePathId{1, 2})).WillRepeatedly(Return(firstSources)); + EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(firstSources)).WillRepeatedly(Return(false)); + EXPECT_CALL(mockBuildDependenciesGenerator, create(projectPart1)); + + provider.create(projectPart1); +} + +TEST_F(BuildDependenciesProvider, FetchDependSourcesFromGenerator) +{ + ON_CALL(mockBuildDependenciesStorage, fetchDependSources(FilePathId{1, 2})).WillByDefault(Return(firstSources)); + ON_CALL(mockModifiedTimeChecker, isUpToDate(_)).WillByDefault(Return(false)); + ON_CALL(mockBuildDependenciesGenerator, create(projectPart1)).WillByDefault(Return(buildDependency)); + + auto buildDependency = provider.create(projectPart1); + + ASSERT_THAT(buildDependency.includes, ElementsAre(HasSourceId(1), HasSourceId(3), HasSourceId(8))); +} + +TEST_F(BuildDependenciesProvider, CreateCallsFetchUsedMacrosFromStorageIfTimeStampsAreUpToDate) +{ + InSequence s; + + EXPECT_CALL(mockBuildDependenciesStorage, fetchDependSources(FilePathId{1, 2})).WillRepeatedly(Return(firstSources)); + EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(firstSources)).WillRepeatedly(Return(true)); + EXPECT_CALL(mockBuildDependenciesStorage, fetchUsedMacros(FilePathId{1, 1})); + EXPECT_CALL(mockBuildDependenciesStorage, fetchUsedMacros(FilePathId{1, 2})); + EXPECT_CALL(mockBuildDependenciesStorage, fetchUsedMacros(FilePathId{1, 10})); + + provider.create(projectPart1); +} + +TEST_F(BuildDependenciesProvider, FetchUsedMacrosFromStorageIfDependSourcesAreUpToDate) +{ + ON_CALL(mockBuildDependenciesStorage, fetchDependSources(FilePathId{1, 2})).WillByDefault(Return(firstSources)); + ON_CALL(mockModifiedTimeChecker, isUpToDate(firstSources)).WillByDefault(Return(true)); + ON_CALL(mockBuildDependenciesStorage, fetchUsedMacros(FilePathId{1, 1})).WillByDefault(Return(firstUsedMacros)); + ON_CALL(mockBuildDependenciesStorage, fetchUsedMacros(FilePathId{1, 2})).WillByDefault(Return(secondUsedMacros)); + ON_CALL(mockBuildDependenciesStorage, fetchUsedMacros(FilePathId{1, 10})).WillByDefault(Return(thirdUsedMacros)); + + auto buildDependency = provider.create(projectPart1); + + ASSERT_THAT(buildDependency.usedMacros, ElementsAre(UsedMacro{"YI", {1, 1}}, UsedMacro{"ER", {1, 2}}, UsedMacro{"LIANG", {1, 2}}, UsedMacro{"SAN", {1, 10}})); +} +} diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 89fbab64d90..33bfe0de58f 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -32,7 +32,7 @@ #include -#include +#include #include #include #include @@ -1015,11 +1015,29 @@ std::ostream &operator<<(std::ostream &out, const PchTask &task) std::ostream &operator<<(std::ostream &out, const BuildDependency &dependency) { return out << "(" - << dependency.includeIds << ", " + << dependency.includes << ", " << dependency.topsSystemIncludeIds << ", " << dependency.topIncludeIds << ")"; } +const char *sourceTypeString(SourceType sourceType) +{ + using ClangBackEnd::SymbolTag; + + switch (sourceType) { + case SourceType::Any: return "Any"; + case SourceType::TopInclude: return "TopInclude"; + case SourceType::TopSystemInclude: return "TopSystemInclude"; + } + + return ""; +} + +std::ostream &operator<<(std::ostream &out, const SourceEntry &entry) +{ + return out << "(" << entry.sourceId << ", " << sourceTypeString(entry.sourceType) << ")"; +} + void PrintTo(const FilePath &filePath, ::std::ostream *os) { *os << filePath; diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index ee968c1378d..7eca6cf9a19 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -172,6 +172,7 @@ class SymbolIndexerTask; class PchCreatorIncludes; class PchTask; class BuildDependency; +class SourceEntry; std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry); std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths); @@ -254,6 +255,7 @@ std::ostream &operator<<(std::ostream &out, const SymbolIndexerTask &task); 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); void PrintTo(const FilePath &filePath, ::std::ostream *os); void PrintTo(const FilePathView &filePathView, ::std::ostream *os); diff --git a/tests/unit/unittest/mockbuilddependenciesgenerator.h b/tests/unit/unittest/mockbuilddependenciesgenerator.h new file mode 100644 index 00000000000..832c37f0bf9 --- /dev/null +++ b/tests/unit/unittest/mockbuilddependenciesgenerator.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 MockBuildDependenciesGenerator : public ClangBackEnd::BuildDependenciesGeneratorInterface +{ +public: + MOCK_METHOD1(create, + ClangBackEnd::BuildDependency (const ClangBackEnd::V2::ProjectPartContainer &projectPart)); +}; + diff --git a/tests/unit/unittest/mockbuilddependenciesprovider.h b/tests/unit/unittest/mockbuilddependenciesprovider.h index 9bd8175a5f2..8bb048bd248 100644 --- a/tests/unit/unittest/mockbuilddependenciesprovider.h +++ b/tests/unit/unittest/mockbuilddependenciesprovider.h @@ -32,6 +32,6 @@ class MockBuildDependenciesProvider : public ClangBackEnd::BuildDependenciesProviderInterface { public: - MOCK_METHOD1(create, - ClangBackEnd::BuildDependency (const ClangBackEnd::V2::ProjectPartContainer &projectPart)); + MOCK_CONST_METHOD1(create, + ClangBackEnd::BuildDependency (const ClangBackEnd::V2::ProjectPartContainer &projectPart)); }; diff --git a/tests/unit/unittest/mockbuilddependencystorage.h b/tests/unit/unittest/mockbuilddependencystorage.h new file mode 100644 index 00000000000..9a043880d83 --- /dev/null +++ b/tests/unit/unittest/mockbuilddependencystorage.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** 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 MockBuildDependenciesStorage : public ClangBackEnd::BuildDependenciesStorageInterface +{ +public: + MOCK_METHOD1(updateSources, + void (const ClangBackEnd::SourceEntries &sources)); + MOCK_METHOD1(insertOrUpdateUsedMacros, + void (const ClangBackEnd::UsedMacros &usedMacros)); + MOCK_METHOD1(insertFileStatuses, + void (const ClangBackEnd::FileStatuses &fileStatuses)); + MOCK_METHOD1(insertOrUpdateSourceDependencies, + void (const ClangBackEnd::SourceDependencies &sourceDependencies)); + MOCK_CONST_METHOD1(fetchLowestLastModifiedTime, + long long (ClangBackEnd::FilePathId sourceId)); + MOCK_CONST_METHOD1(fetchDependSources, + ClangBackEnd::SourceEntries (ClangBackEnd::FilePathId sourceId)); + MOCK_CONST_METHOD1(fetchUsedMacros, + ClangBackEnd::UsedMacros (ClangBackEnd::FilePathId sourceId)); +}; + diff --git a/tests/unit/unittest/mockmodifiedtimechecker.h b/tests/unit/unittest/mockmodifiedtimechecker.h new file mode 100644 index 00000000000..5f0559f6824 --- /dev/null +++ b/tests/unit/unittest/mockmodifiedtimechecker.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** 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 MockModifiedTimeChecker : public ClangBackEnd::ModifiedTimeCheckerInterface +{ +public: + MOCK_CONST_METHOD1(isUpToDate, + bool (const ClangBackEnd::SourceEntries &sourceEntries)); +}; diff --git a/tests/unit/unittest/pchtaskgenerator-test.cpp b/tests/unit/unittest/pchtaskgenerator-test.cpp index cfb34f4c5db..ac5ed89cef0 100644 --- a/tests/unit/unittest/pchtaskgenerator-test.cpp +++ b/tests/unit/unittest/pchtaskgenerator-test.cpp @@ -35,6 +35,8 @@ using ClangBackEnd::BuildDependency; using ClangBackEnd::BuildDependencies; using ClangBackEnd::FilePathId; using ClangBackEnd::PchTask; +using ClangBackEnd::SourceEntries; +using ClangBackEnd::SourceType; class PchTaskGenerator : public testing::Test { @@ -47,7 +49,8 @@ protected: {"/yi"}, {{1, 1}}, {{1, 2}}}; - BuildDependency buildDependency{{{1, 1}}, {}, {}}; + SourceEntries firstSources{{{1, 1}, SourceType::Any, 1}, {{1, 2}, SourceType::Any, 1}, {{1, 10}, SourceType::Any, 1}}; + BuildDependency buildDependency{firstSources, {}, {}, {}}; }; TEST_F(PchTaskGenerator, Create) @@ -60,7 +63,7 @@ TEST_F(PchTaskGenerator, Create) ElementsAre( AllOf(Field(&PchTask::ids, ElementsAre("ProjectPart1")), Field(&PchTask::buildDependency, - Field(&BuildDependency::includeIds, ElementsAre(FilePathId{1, 1})))))); + Field(&BuildDependency::includes, firstSources))))); } } diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index f4cdc4c495a..de9c647099d 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -105,7 +105,8 @@ SOURCES += \ compileroptionsbuilder-test.cpp \ usedmacroandsourcestorage-test.cpp \ pchtaskgenerator-test.cpp \ - compilationdatabaseutils-test.cpp + compilationdatabaseutils-test.cpp \ + builddependenciesprovider-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -250,7 +251,10 @@ HEADERS += \ mockprocessormanager.h \ mocktaskscheduler.h \ mockusedmacroandsourcestorage.h \ - mockbuilddependenciesprovider.h + mockbuilddependenciesprovider.h \ + mockbuilddependencystorage.h \ + mockmodifiedtimechecker.h \ + mockbuilddependenciesgenerator.h !isEmpty(LIBCLANG_LIBS) { HEADERS += \