ClangPchManager: Update PCHs if time stamps of dependencies changed

If there is a newer file than the last indexing or if a file is added or
removed from the project or system PCH we have to reindex the project and
maybe the system PCH.

Change-Id: Ibce2a244190a79b5c422c469c065ddc11e44b2cb
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-07-31 16:54:39 +02:00
parent f1be7793c4
commit 56d611e0a3
15 changed files with 788 additions and 132 deletions

View File

@@ -945,8 +945,8 @@ clone(const std::unordered_map<Key, Value, Hash, KeyEqual, Allocator> &map)
return clonedMap;
}
template <typename Type>
std::vector<Type> clone(const std::vector<Type> &vector)
template<typename Type>
Type clone(const Type &vector)
{
return vector;
}

View File

@@ -117,16 +117,7 @@ public:
push_back(std::move(string));
}
BasicSmallStringVector clone() const
{
BasicSmallStringVector clonedVector;
clonedVector.reserve(Base::size());
for (auto &&entry : *this)
clonedVector.push_back(entry.clone());
return clonedVector;
}
BasicSmallStringVector clone() const { return *this; }
operator std::vector<std::string>() const
{

View File

@@ -185,8 +185,12 @@ struct Data // because we have a cycle dependency
ApplicationEnvironment environment;
ProjectPartsStorage<> projectPartsStorage{database};
PrecompiledHeaderStorage<> preCompiledHeaderStorage{database};
ProjectPartsManager projectParts{projectPartsStorage, preCompiledHeaderStorage};
GeneratedFiles generatedFiles;
ProjectPartsManager projectParts{projectPartsStorage,
preCompiledHeaderStorage,
buildDependencyProvider,
filePathCache,
generatedFiles};
PchCreatorManager pchCreatorManager{generatedFiles,
environment,
database,
@@ -227,7 +231,9 @@ struct Data // because we have a cycle dependency
pchTaskGenerator,
projectParts,
generatedFiles,
buildDependencyStorage};
buildDependencyStorage/*,
buildDependencyProvider,
filePathCache*/};
TaskScheduler systemTaskScheduler{pchCreatorManager,
pchTaskQueue,
pchCreationProgressCounter,

View File

@@ -26,6 +26,7 @@
#include "pchmanagerserver.h"
#include <builddependenciesstorage.h>
#include <filepathcachinginterface.h>
#include <pchmanagerclientinterface.h>
#include <pchtaskgeneratorinterface.h>
#include <precompiledheadersupdatedmessage.h>
@@ -54,6 +55,7 @@ PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
, m_projectPartsManager(projectParts)
, m_generatedFiles(generatedFiles)
, m_buildDependenciesStorage(buildDependenciesStorage)
{
m_fileSystemWatcher.setNotifier(this);
}
@@ -79,10 +81,13 @@ void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)
auto upToDateProjectParts = m_projectPartsManager.update(message.takeProjectsParts());
if (m_generatedFiles.isValid()) {
m_pchTaskGenerator.addProjectParts(std::move(upToDateProjectParts.notUpToDate),
std::move(message.toolChainArguments));
m_pchTaskGenerator.addProjectParts(std::move(upToDateProjectParts.updateSystem),
message.toolChainArguments.clone());
m_pchTaskGenerator.addNonSystemProjectParts(std::move(upToDateProjectParts.updateProject),
std::move(message.toolChainArguments));
} else {
m_projectPartsManager.updateDeferred(upToDateProjectParts.notUpToDate);
m_projectPartsManager.updateDeferred(std::move(upToDateProjectParts.updateSystem),
std::move(upToDateProjectParts.updateProject));
}
client()->precompiledHeadersUpdated(toProjectPartIds(upToDateProjectParts.upToDate));
@@ -119,13 +124,21 @@ void PchManagerServer::updateGeneratedFiles(UpdateGeneratedFilesMessage &&messag
m_generatedFiles.update(message.takeGeneratedFiles());
if (m_generatedFiles.isValid()) {
ProjectPartContainers deferredProjectParts = m_projectPartsManager.deferredUpdates();
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(
projectPartIds(deferredProjectParts));
ProjectPartContainers deferredSystems = m_projectPartsManager.deferredSystemUpdates();
ArgumentsEntries systemEntries = m_toolChainsArgumentsCache.arguments(
projectPartIds(deferredSystems));
for (ArgumentsEntry &entry : entries) {
m_pchTaskGenerator.addProjectParts(std::move(deferredProjectParts),
std::move(entry.arguments));
for (ArgumentsEntry &entry : systemEntries) {
m_pchTaskGenerator.addProjectParts(std::move(deferredSystems), std::move(entry.arguments));
}
ProjectPartContainers deferredProjects = m_projectPartsManager.deferredProjectUpdates();
ArgumentsEntries projectEntries = m_toolChainsArgumentsCache.arguments(
projectPartIds(deferredProjects));
for (ArgumentsEntry &entry : projectEntries) {
m_pchTaskGenerator.addNonSystemProjectParts(std::move(deferredProjects),
std::move(entry.arguments));
}
}
}

View File

@@ -125,6 +125,20 @@ public:
}
}
void deleteSystemAndProjectPrecompiledHeaders(const ProjectPartIds &projectPartIds) override
{
try {
Sqlite::ImmediateTransaction transaction{database};
for (ProjectPartId projectPartId : projectPartIds)
deleteSystemAndProjectPrecompiledHeaderStatement.write(projectPartId.projectPathId);
transaction.commit();
} catch (const Sqlite::StatementIsBusy) {
deleteSystemAndProjectPrecompiledHeaders(projectPartIds);
}
}
FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) override
{
try {
@@ -230,6 +244,11 @@ public:
"UPDATE OR IGNORE precompiledHeaders SET systemPchPath=NULL,systemPchBuildTime=NULL "
"WHERE projectPartId = ?",
database};
WriteStatement deleteSystemAndProjectPrecompiledHeaderStatement{
"UPDATE OR IGNORE precompiledHeaders SET "
"systemPchPath=NULL,systemPchBuildTime=NULL,projectPchPath=NULL,projectPchBuildTime=NULL "
"WHERE projectPartId = ?",
database};
ReadStatement fetchSystemPrecompiledHeaderPathStatement{
"SELECT systemPchPath FROM precompiledHeaders WHERE projectPartId = ?", database};
mutable ReadStatement fetchPrecompiledHeaderStatement{

View File

@@ -55,6 +55,7 @@ public:
TimeStamp pchBuildTime)
= 0;
virtual void deleteSystemPrecompiledHeaders(const ProjectPartIds &projectPartIds) = 0;
virtual void deleteSystemAndProjectPrecompiledHeaders(const ProjectPartIds &projectPartIds) = 0;
virtual FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) = 0;
virtual FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0;
virtual PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const = 0;

View File

@@ -25,7 +25,11 @@
#include "projectpartsmanager.h"
#include <builddependenciesproviderinterface.h>
#include <filecontainerv2.h>
#include <filepathcachinginterface.h>
#include <projectpartcontainer.h>
#include <set_algorithm.h>
#include <algorithm>
@@ -44,38 +48,171 @@ ProjectPartIds toProjectPartIds(const ProjectPartContainers &projectsParts)
return ids;
}
ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
namespace {
enum class Change { System, Project, No };
Change changedSourceType(const SourceEntries &sources)
{
auto notUpToDateProjectParts = filterProjectParts(projectsParts, m_projectParts);
if (notUpToDateProjectParts.empty())
return {std::move(projectsParts), {}};
auto persistentProjectParts = m_projectPartsStorage.fetchProjectParts(
toProjectPartIds(notUpToDateProjectParts));
if (persistentProjectParts.size() > 0) {
mergeProjectParts(persistentProjectParts);
notUpToDateProjectParts = filterProjectParts(notUpToDateProjectParts, persistentProjectParts);
if (notUpToDateProjectParts.empty())
return {};
Change change = Change::No;
for (SourceEntry sourceEntry : sources) {
switch (sourceEntry.sourceType) {
case SourceType::SystemInclude:
case SourceType::TopSystemInclude:
return Change::System;
case SourceType::ProjectInclude:
case SourceType::TopProjectInclude:
change = Change::Project;
break;
case SourceType::Source:
case SourceType::UserInclude:
break;
}
}
m_projectPartsStorage.updateProjectParts(notUpToDateProjectParts);
m_projectPartsStorage.resetIndexingTimeStamps(notUpToDateProjectParts);
m_precompiledHeaderStorage.deleteProjectPrecompiledHeaders(
toProjectPartIds(notUpToDateProjectParts));
mergeProjectParts(notUpToDateProjectParts);
auto upToDateProjectParts = filterProjectParts(projectsParts, notUpToDateProjectParts);
return {upToDateProjectParts, notUpToDateProjectParts};
return change;
}
void ProjectPartsManager::remove(const ProjectPartIds &projectPartIds)
} // namespace
ProjectPartsManager::UpToDataProjectParts ProjectPartsManager::update(ProjectPartContainers &&projectsParts)
{
auto updateSystemProjectParts = filterProjectParts(projectsParts, m_projectParts);
if (!updateSystemProjectParts.empty()) {
auto persistentProjectParts = m_projectPartsStorage.fetchProjectParts(
toProjectPartIds(updateSystemProjectParts));
if (persistentProjectParts.size() > 0) {
mergeProjectParts(persistentProjectParts);
updateSystemProjectParts = filterProjectParts(updateSystemProjectParts,
persistentProjectParts);
}
if (updateSystemProjectParts.size()) {
m_projectPartsStorage.updateProjectParts(updateSystemProjectParts);
mergeProjectParts(updateSystemProjectParts);
}
}
auto upToDateProjectParts = filterProjectParts(projectsParts, updateSystemProjectParts);
auto updates = checkDependeciesAndTime(std::move(upToDateProjectParts),
std::move(updateSystemProjectParts));
if (updates.updateSystem.size()) {
m_projectPartsStorage.resetIndexingTimeStamps(updates.updateSystem);
m_precompiledHeaderStorage.deleteSystemAndProjectPrecompiledHeaders(
toProjectPartIds(updates.updateSystem));
}
if (updates.updateProject.size()) {
m_projectPartsStorage.resetIndexingTimeStamps(updates.updateProject);
m_precompiledHeaderStorage.deleteProjectPrecompiledHeaders(
toProjectPartIds(updates.updateProject));
}
return updates;
}
ProjectPartsManagerInterface::UpToDataProjectParts ProjectPartsManager::checkDependeciesAndTime(
ProjectPartContainers &&upToDateProjectParts, ProjectPartContainers &&updateSystemProjectParts)
{
ProjectPartContainerReferences changeProjectParts;
changeProjectParts.reserve(upToDateProjectParts.size());
ProjectPartContainers updateProjectProjectParts;
updateProjectProjectParts.reserve(upToDateProjectParts.size());
updateSystemProjectParts.reserve(updateProjectProjectParts.size() + upToDateProjectParts.size());
auto systemSplit = updateSystemProjectParts.end();
for (ProjectPartContainer &projectPart : upToDateProjectParts) {
auto oldSources = m_buildDependenciesProvider.createSourceEntriesFromStorage(
projectPart.sourcePathIds, projectPart.projectPartId);
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart,
Utils::clone(oldSources));
auto newSources = buildDependency.sources;
SourceEntries updatedSourceTyes;
updatedSourceTyes.reserve(newSources.size());
std::set_symmetric_difference(newSources.begin(),
newSources.end(),
oldSources.begin(),
oldSources.end(),
std::back_inserter(updatedSourceTyes),
[](SourceEntry first, SourceEntry second) {
return std::tie(first.sourceId, first.sourceType)
< std::tie(second.sourceId, second.sourceType);
});
auto change = changedSourceType(updatedSourceTyes);
switch (change) {
case Change::Project:
updateProjectProjectParts.emplace_back(std::move(projectPart));
projectPart.projectPartId = -1;
break;
case Change::System:
updateSystemProjectParts.emplace_back(std::move(projectPart));
projectPart.projectPartId = -1;
break;
case Change::No:
break;
}
if (change == Change::No) {
SourceEntries updatedTimeStamps;
updatedTimeStamps.reserve(newSources.size());
std::set_difference(newSources.begin(),
newSources.end(),
oldSources.begin(),
oldSources.end(),
std::back_inserter(updatedTimeStamps),
[](SourceEntry first, SourceEntry second) {
return std::tie(first.sourceId, first.timeStamp)
< std::tie(second.sourceId, second.timeStamp);
});
auto change = changedSourceType(updatedTimeStamps);
switch (change) {
case Change::Project:
updateProjectProjectParts.emplace_back(std::move(projectPart));
projectPart.projectPartId = -1;
break;
case Change::System:
updateSystemProjectParts.emplace_back(std::move(projectPart));
projectPart.projectPartId = -1;
break;
case Change::No:
break;
}
}
}
std::inplace_merge(updateSystemProjectParts.begin(), systemSplit, updateSystemProjectParts.end());
upToDateProjectParts.erase(std::remove_if(upToDateProjectParts.begin(),
upToDateProjectParts.end(),
[](const ProjectPartContainer &projectPart) {
return !projectPart.projectPartId.isValid();
}),
upToDateProjectParts.end());
return {std::move(upToDateProjectParts),
std::move(updateSystemProjectParts),
updateProjectProjectParts};
}
namespace {
ProjectPartContainers removed(ProjectPartContainers &&projectParts,
const ProjectPartIds &projectPartIds)
{
ProjectPartContainers projectPartsWithoutIds;
@@ -99,14 +236,22 @@ void ProjectPartsManager::remove(const ProjectPartIds &projectPartIds)
}
};
std::set_difference(std::make_move_iterator(m_projectParts.begin()),
std::make_move_iterator(m_projectParts.end()),
std::set_difference(std::make_move_iterator(projectParts.begin()),
std::make_move_iterator(projectParts.end()),
projectPartIds.begin(),
projectPartIds.end(),
std::back_inserter(projectPartsWithoutIds),
Compare{});
m_projectParts = std::move(projectPartsWithoutIds);
return projectPartsWithoutIds;
}
} // namespace
void ProjectPartsManager::remove(const ProjectPartIds &projectPartIds)
{
m_projectParts = removed(std::move(m_projectParts), projectPartIds);
m_systemDeferredProjectParts = removed(std::move(m_systemDeferredProjectParts), projectPartIds);
m_projectDeferredProjectParts = removed(std::move(m_projectDeferredProjectParts), projectPartIds);
}
ProjectPartContainers ProjectPartsManager::projects(const ProjectPartIds &projectPartIds) const
@@ -143,38 +288,42 @@ ProjectPartContainers ProjectPartsManager::projects(const ProjectPartIds &projec
return projectPartsWithIds;
}
void ProjectPartsManager::updateDeferred(const ProjectPartContainers &deferredProjectsParts)
namespace {
ProjectPartContainers merge(ProjectPartContainers &&newProjectParts,
ProjectPartContainers &&oldProjectParts)
{
ProjectPartContainerReferences deferredProjectPartPointers;
deferredProjectPartPointers.reserve(deferredProjectsParts.size());
ProjectPartContainers mergedProjectParts;
mergedProjectParts.reserve(newProjectParts.size() + oldProjectParts.size());
std::set_intersection(m_projectParts.begin(),
m_projectParts.end(),
deferredProjectsParts.begin(),
deferredProjectsParts.end(),
std::back_inserter(deferredProjectPartPointers),
[](const ProjectPartContainer &first, const ProjectPartContainer &second) {
return first.projectPartId < second.projectPartId;
});
std::set_union(std::make_move_iterator(newProjectParts.begin()),
std::make_move_iterator(newProjectParts.end()),
std::make_move_iterator(oldProjectParts.begin()),
std::make_move_iterator(oldProjectParts.end()),
std::back_inserter(mergedProjectParts),
[](const ProjectPartContainer &first, const ProjectPartContainer &second) {
return first.projectPartId < second.projectPartId;
});
for (ProjectPartContainer &projectPart : deferredProjectPartPointers)
projectPart.updateIsDeferred = true;
return mergedProjectParts;
}
} // namespace
void ProjectPartsManager::updateDeferred(ProjectPartContainers &&system,
ProjectPartContainers &&project)
{
m_systemDeferredProjectParts = merge(std::move(system), std::move(m_systemDeferredProjectParts));
m_projectDeferredProjectParts = merge(std::move(project),
std::move(m_projectDeferredProjectParts));
}
ProjectPartContainers ProjectPartsManager::deferredUpdates()
ProjectPartContainers ProjectPartsManager::deferredSystemUpdates()
{
ProjectPartContainers deferredProjectParts;
deferredProjectParts.reserve(m_projectParts.size());
return std::move(m_systemDeferredProjectParts);
}
std::copy_if(m_projectParts.cbegin(),
m_projectParts.cend(),
std::back_inserter(deferredProjectParts),
[](const ProjectPartContainer &projectPart) { return projectPart.updateIsDeferred; });
for (ProjectPartContainer &projectPart : m_projectParts)
projectPart.updateIsDeferred = false;
return deferredProjectParts;
ProjectPartContainers ProjectPartsManager::deferredProjectUpdates()
{
return std::move(m_projectDeferredProjectParts);
}
ProjectPartContainers ProjectPartsManager::filterProjectParts(

View File

@@ -35,32 +35,42 @@
namespace ClangBackEnd {
class BuildDependenciesProviderInterface;
inline namespace Pch {
class ProjectPartsManager final : public ProjectPartsManagerInterface
{
public:
ProjectPartsManager(ProjectPartsStorageInterface &projectPartsStorage,
PrecompiledHeaderStorageInterface &precompiledHeaderStorage)
PrecompiledHeaderStorageInterface &precompiledHeaderStorage,
BuildDependenciesProviderInterface &buildDependenciesProvider)
: m_projectPartsStorage(projectPartsStorage)
, m_precompiledHeaderStorage(precompiledHeaderStorage)
, m_buildDependenciesProvider(buildDependenciesProvider)
{}
UpToDataProjectParts update(ProjectPartContainers &&projectsParts) override;
void remove(const ProjectPartIds &projectPartIds) override;
ProjectPartContainers projects(const ProjectPartIds &projectPartIds) const override;
void updateDeferred(const ProjectPartContainers &projectsParts) override;
ProjectPartContainers deferredUpdates() override;
void updateDeferred(ProjectPartContainers &&system, ProjectPartContainers &&project) override;
ProjectPartContainers deferredSystemUpdates() override;
ProjectPartContainers deferredProjectUpdates() override;
static ProjectPartContainers filterProjectParts(const ProjectPartContainers &newProjectsParts,
const ProjectPartContainers &oldProjectParts);
void mergeProjectParts(const ProjectPartContainers &projectsParts);
const ProjectPartContainers &projectParts() const;
UpToDataProjectParts checkDependeciesAndTime(ProjectPartContainers &&upToDateProjectParts,
ProjectPartContainers &&updateSystemProjectParts);
private:
ProjectPartContainers m_projectParts;
ProjectPartContainers m_systemDeferredProjectParts;
ProjectPartContainers m_projectDeferredProjectParts;
ProjectPartsStorageInterface &m_projectPartsStorage;
PrecompiledHeaderStorageInterface &m_precompiledHeaderStorage;
BuildDependenciesProviderInterface &m_buildDependenciesProvider;
};
} // namespace Pch

View File

@@ -36,7 +36,8 @@ public:
{
public:
ProjectPartContainers upToDate;
ProjectPartContainers notUpToDate;
ProjectPartContainers updateSystem;
ProjectPartContainers updateProject;
};
ProjectPartsManagerInterface() = default;
@@ -46,8 +47,9 @@ public:
virtual UpToDataProjectParts update(ProjectPartContainers &&projectsParts) = 0;
virtual void remove(const ProjectPartIds &projectPartIds) = 0;
virtual ProjectPartContainers projects(const ProjectPartIds &projectPartIds) const = 0;
virtual void updateDeferred(const ProjectPartContainers &projectsParts) = 0;
virtual ProjectPartContainers deferredUpdates() = 0;
virtual void updateDeferred(ProjectPartContainers &&system, ProjectPartContainers &&project) = 0;
virtual ProjectPartContainers deferredSystemUpdates() = 0;
virtual ProjectPartContainers deferredProjectUpdates() = 0;
protected:
~ProjectPartsManagerInterface() = default;

View File

@@ -46,6 +46,8 @@ public:
ClangBackEnd::TimeStamp pchBuildTime));
MOCK_METHOD1(deleteSystemPrecompiledHeaders,
void(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_METHOD1(deleteSystemAndProjectPrecompiledHeaders,
void(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_METHOD1(fetchSystemPrecompiledHeaderPath,
ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(fetchPrecompiledHeader,

View File

@@ -39,12 +39,21 @@ public:
MOCK_CONST_METHOD1(
projects,
ClangBackEnd::ProjectPartContainers(const ClangBackEnd::ProjectPartIds &projectPartIds));
MOCK_METHOD1(updateDeferred, void(const ClangBackEnd::ProjectPartContainers &projectsParts));
MOCK_METHOD0(deferredUpdates, ClangBackEnd::ProjectPartContainers());
MOCK_METHOD2(updateDeferred,
void(const ClangBackEnd::ProjectPartContainers &system,
const ClangBackEnd::ProjectPartContainers &project));
MOCK_METHOD0(deferredSystemUpdates, ClangBackEnd::ProjectPartContainers());
MOCK_METHOD0(deferredProjectUpdates, ClangBackEnd::ProjectPartContainers());
ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts update(
ClangBackEnd::ProjectPartContainers &&projectsParts) override
{
return update(projectsParts);
}
void updateDeferred(ClangBackEnd::ProjectPartContainers &&system,
ClangBackEnd::ProjectPartContainers &&project) override
{
return updateDeferred(system, project);
}
};

View File

@@ -59,7 +59,7 @@ class PchManagerServer : public ::testing::Test
server.setClient(&mockPchManagerClient);
ON_CALL(mockProjectPartsManager, update(projectParts))
.WillByDefault(Return(UpToDataProjectParts{{}, projectParts}));
.WillByDefault(Return(UpToDataProjectParts{{}, projectParts, projectParts4}));
ON_CALL(mockGeneratedFiles, isValid()).WillByDefault(Return(true));
}
@@ -163,6 +163,8 @@ protected:
std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2};
std::vector<ProjectPartContainer> projectParts1{projectPart1};
std::vector<ProjectPartContainer> projectParts2{projectPart2};
std::vector<ProjectPartContainer> projectParts3{projectPart3};
std::vector<ProjectPartContainer> projectParts4{projectPart3, projectPart4};
FileContainer generatedFile{{"/path/to/", "file"}, "content", {}};
ClangBackEnd::UpdateProjectPartsMessage updateProjectPartsMessage{
Utils::clone(projectParts), {"toolChainArgument"}};
@@ -175,9 +177,11 @@ TEST_F(PchManagerServer, FilterProjectPartsAndSendThemToQueue)
InSequence s;
EXPECT_CALL(mockProjectPartsManager, update(updateProjectPartsMessage.projectsParts))
.WillOnce(Return(UpToDataProjectParts{{}, projectParts2}));
.WillOnce(Return(UpToDataProjectParts{{}, projectParts2, projectParts4}));
EXPECT_CALL(
mockPchTaskGenerator, addProjectParts(Eq(projectParts2), ElementsAre("toolChainArgument")));
EXPECT_CALL(mockPchTaskGenerator,
addNonSystemProjectParts(Eq(projectParts4), ElementsAre("toolChainArgument")));
server.updateProjectParts(updateProjectPartsMessage.clone());
}
@@ -267,6 +271,7 @@ TEST_F(PchManagerServer, DontUpdateProjectPartQueueByPathIdsIfItUserFile)
EXPECT_CALL(mockProjectPartsManager, projects(_)).Times(0);
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
EXPECT_CALL(mockPchTaskGenerator, addNonSystemProjectParts(_, _)).Times(0);
server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::Source}, {}}});
@@ -323,6 +328,7 @@ TEST_F(PchManagerServer, RemoveToolChainsArguments)
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
EXPECT_CALL(mockPchTaskGenerator, addNonSystemProjectParts(_, _)).Times(0);
server.removeProjectParts(removeProjectPartsMessage.clone());
server.pathsWithIdsChanged({{{projectPart1.projectPartId, ClangBackEnd::SourceType::Source}, {}}});
@@ -333,10 +339,12 @@ TEST_F(PchManagerServer, DontGeneratePchIfGeneratedFilesAreNotValid)
InSequence s;
EXPECT_CALL(mockProjectPartsManager, update(ElementsAre(projectPart1)))
.WillOnce(Return(UpToDataProjectParts{{}, ProjectPartContainers{projectPart1}}));
.WillOnce(Return(UpToDataProjectParts{{}, {projectPart1}, {projectPart2}}));
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(false));
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
EXPECT_CALL(mockProjectPartsManager, updateDeferred(ElementsAre(projectPart1)));
EXPECT_CALL(mockPchTaskGenerator, addNonSystemProjectParts(_, _)).Times(0);
EXPECT_CALL(mockProjectPartsManager,
updateDeferred(ElementsAre(projectPart1), ElementsAre(projectPart2)));
server.updateProjectParts(
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
@@ -347,10 +355,11 @@ TEST_F(PchManagerServer, GeneratePchIfGeneratedFilesAreValid)
InSequence s;
EXPECT_CALL(mockProjectPartsManager, update(ElementsAre(projectPart1)))
.WillOnce(Return(UpToDataProjectParts{{}, ProjectPartContainers{projectPart1}}));
.WillOnce(Return(UpToDataProjectParts{{}, {projectPart1}, {projectPart2}}));
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(true));
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _));
EXPECT_CALL(mockProjectPartsManager, updateDeferred(_)).Times(0);
EXPECT_CALL(mockPchTaskGenerator, addNonSystemProjectParts(_, _));
EXPECT_CALL(mockProjectPartsManager, updateDeferred(_, _)).Times(0);
server.updateProjectParts(
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
@@ -361,15 +370,19 @@ TEST_F(PchManagerServer, AfterUpdatingGeneratedFilesAreValidSoGeneratePchs)
InSequence s;
ClangBackEnd::UpdateGeneratedFilesMessage updateGeneratedFilesMessage{{generatedFile}};
ON_CALL(mockGeneratedFiles, isValid()).WillByDefault(Return(false));
server.updateProjectParts(
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{{projectPart1, projectPart2},
{"toolChainArgument"}});
EXPECT_CALL(mockGeneratedFiles, update(updateGeneratedFilesMessage.generatedFiles));
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(true));
EXPECT_CALL(mockProjectPartsManager, deferredUpdates())
EXPECT_CALL(mockProjectPartsManager, deferredSystemUpdates())
.WillOnce(Return(ClangBackEnd::ProjectPartContainers{projectPart1}));
EXPECT_CALL(mockPchTaskGenerator,
addProjectParts(ElementsAre(projectPart1), ElementsAre("toolChainArgument")));
EXPECT_CALL(mockProjectPartsManager, deferredProjectUpdates())
.WillOnce(Return(ClangBackEnd::ProjectPartContainers{projectPart2}));
EXPECT_CALL(mockPchTaskGenerator,
addNonSystemProjectParts(ElementsAre(projectPart2), ElementsAre("toolChainArgument")));
server.updateGeneratedFiles(updateGeneratedFilesMessage.clone());
}
@@ -379,13 +392,14 @@ TEST_F(PchManagerServer, AfterUpdatingGeneratedFilesAreStillInvalidSoNoPchsGener
InSequence s;
ClangBackEnd::UpdateGeneratedFilesMessage updateGeneratedFilesMessage{{generatedFile}};
ON_CALL(mockGeneratedFiles, isValid()).WillByDefault(Return(false));
server.updateProjectParts(
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{{projectPart1, projectPart2},
{"toolChainArgument"}});
EXPECT_CALL(mockGeneratedFiles, update(updateGeneratedFilesMessage.generatedFiles));
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(false));
EXPECT_CALL(mockProjectPartsManager, deferredUpdates()).Times(0);
EXPECT_CALL(mockProjectPartsManager, deferredSystemUpdates()).Times(0);
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
EXPECT_CALL(mockPchTaskGenerator, addNonSystemProjectParts(_, _)).Times(0);
server.updateGeneratedFiles(updateGeneratedFilesMessage.clone());
}
@@ -395,7 +409,7 @@ TEST_F(PchManagerServer, SentUpToDateProjectPartIdsToClient)
InSequence s;
EXPECT_CALL(mockProjectPartsManager, update(updateProjectPartsMessage.projectsParts))
.WillOnce(Return(UpToDataProjectParts{projectParts1, projectParts2}));
.WillOnce(Return(UpToDataProjectParts{projectParts1, projectParts2, projectParts3}));
EXPECT_CALL(mockPchTaskGenerator,
addProjectParts(Eq(projectParts2), ElementsAre("toolChainArgument")));
EXPECT_CALL(mockPchManagerClient,

View File

@@ -47,7 +47,7 @@ class PchTaskQueue : public testing::Test
protected:
NiceMock<MockTaskScheduler<ClangBackEnd::PchTaskQueue::Task>> mockSytemPchTaskScheduler;
NiceMock<MockTaskScheduler<ClangBackEnd::PchTaskQueue::Task>> mockProjectPchTaskScheduler;
MockPrecompiledHeaderStorage mockPrecompiledHeaderStorage;
NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage;
MockSqliteTransactionBackend mockSqliteTransactionBackend;
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};

View File

@@ -48,6 +48,7 @@ protected:
= storage.deleteProjectPrecompiledHeaderPathAndSetBuildTimeStatement;
MockSqliteWriteStatement &insertSystemPrecompiledHeaderStatement = storage.insertSystemPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteSystemPrecompiledHeaderStatement = storage.deleteSystemPrecompiledHeaderStatement;
MockSqliteWriteStatement &deleteSystemAndProjectPrecompiledHeaderStatement = storage.deleteSystemAndProjectPrecompiledHeaderStatement;
MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.fetchSystemPrecompiledHeaderPathStatement;
MockSqliteReadStatement &fetchPrecompiledHeaderStatement = storage.fetchPrecompiledHeaderStatement;
MockSqliteReadStatement &fetchPrecompiledHeadersStatement = storage.fetchPrecompiledHeadersStatement;
@@ -205,6 +206,31 @@ TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeadersStatementIsBusy)
storage.deleteSystemPrecompiledHeaders({1, 2});
}
TEST_F(PrecompiledHeaderStorage, DeleteSystemAndProjectPrecompiledHeaders)
{
InSequence s;
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deleteSystemAndProjectPrecompiledHeaderStatement, write(TypedEq<int>(1)));
EXPECT_CALL(deleteSystemAndProjectPrecompiledHeaderStatement, write(TypedEq<int>(2)));
EXPECT_CALL(database, commit());
storage.deleteSystemAndProjectPrecompiledHeaders({1, 2});
}
TEST_F(PrecompiledHeaderStorage, DeleteSystemAndProjectPrecompiledHeadersStatementIsBusy)
{
InSequence s;
EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(database, immediateBegin());
EXPECT_CALL(deleteSystemAndProjectPrecompiledHeaderStatement, write(TypedEq<int>(1)));
EXPECT_CALL(deleteSystemAndProjectPrecompiledHeaderStatement, write(TypedEq<int>(2)));
EXPECT_CALL(database, commit());
storage.deleteSystemAndProjectPrecompiledHeaders({1, 2});
}
TEST_F(PrecompiledHeaderStorage, CompilePrecompiledHeaderStatements)
{
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};

View File

@@ -24,6 +24,9 @@
****************************************************************************/
#include "googletest.h"
#include "mockbuilddependenciesprovider.h"
#include "mockfilepathcaching.h"
#include "mockgeneratedfiles.h"
#include "mockprecompiledheaderstorage.h"
#include "mockprojectpartsstorage.h"
@@ -37,6 +40,8 @@ using ClangBackEnd::FilePathId;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartContainers;
using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceType;
class ProjectPartsManager : public testing::Test
{
@@ -47,8 +52,10 @@ protected:
}
NiceMock<MockProjectPartsStorage> mockProjectPartsStorage;
NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage;
ClangBackEnd::ProjectPartsManager manager{mockProjectPartsStorage, mockPrecompiledHeaderStorage};
NiceMock<MockBuildDependenciesProvider> mockBuildDependenciesProvider;
ClangBackEnd::ProjectPartsManager manager{mockProjectPartsStorage,
mockPrecompiledHeaderStorage,
mockBuildDependenciesProvider};
FilePathId firstHeader{1};
FilePathId secondHeader{2};
FilePathId firstSource{11};
@@ -101,13 +108,36 @@ protected:
2,
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::System}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{firstHeader, secondHeader},
{firstSource, secondSource},
Utils::Language::C,
Utils::LanguageVersion::C11,
{firstHeader},
{firstSource},
Utils::Language::Cxx,
Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::All};
ProjectPartContainer projectPartContainer3{
3,
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::Framework}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{secondHeader},
{firstSource},
Utils::Language::C,
Utils::LanguageVersion::C18,
Utils::LanguageExtension::All};
ProjectPartContainer projectPartContainer4{
4,
{"-DUNIX", "-O2"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{firstHeader},
{firstSource},
Utils::Language::Cxx,
Utils::LanguageVersion::CXX03,
Utils::LanguageExtension::All};
ClangBackEnd::V2::FileContainers generatedFiles;
};
TEST_F(ProjectPartsManager, GetNoProjectPartsForAddingEmptyProjectParts)
@@ -116,7 +146,7 @@ TEST_F(ProjectPartsManager, GetNoProjectPartsForAddingEmptyProjectParts)
ASSERT_THAT(projectParts,
AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
Field(&UpToDataProjectParts::notUpToDate, IsEmpty())));
Field(&UpToDataProjectParts::updateSystem, IsEmpty())));
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPart)
@@ -125,7 +155,7 @@ TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPart)
ASSERT_THAT(projectParts,
AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
Field(&UpToDataProjectParts::notUpToDate, ElementsAre(projectPartContainer1))));
Field(&UpToDataProjectParts::updateSystem, ElementsAre(projectPartContainer1))));
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithProjectPartAlreadyInTheDatabase)
@@ -137,7 +167,7 @@ TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithProjectPartAlr
ASSERT_THAT(projectParts,
AllOf(Field(&UpToDataProjectParts::upToDate, ElementsAre(projectPartContainer1)),
Field(&UpToDataProjectParts::notUpToDate, ElementsAre(projectPartContainer2))));
Field(&UpToDataProjectParts::updateSystem, ElementsAre(projectPartContainer2))));
}
TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithOlderProjectPartAlreadyInTheDatabase)
@@ -149,7 +179,7 @@ TEST_F(ProjectPartsManager, GetProjectPartForAddingProjectPartWithOlderProjectPa
ASSERT_THAT(projectParts,
AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
Field(&UpToDataProjectParts::notUpToDate,
Field(&UpToDataProjectParts::updateSystem,
ElementsAre(updatedProjectPartContainer1, projectPartContainer2))));
}
@@ -198,7 +228,7 @@ TEST_F(ProjectPartsManager, DoNotUpdateNotNewProjectPart)
ASSERT_THAT(projectParts,
AllOf(Field(&UpToDataProjectParts::upToDate, ElementsAre(projectPartContainer1)),
Field(&UpToDataProjectParts::notUpToDate, IsEmpty())));
Field(&UpToDataProjectParts::updateSystem, IsEmpty())));
}
TEST_F(ProjectPartsManager, NoDuplicateProjectPartAfterUpdatingWithNotNewProjectPart)
@@ -242,7 +272,7 @@ TEST_F(ProjectPartsManager, GetUpdatedProjectPart)
ASSERT_THAT(projectParts,
AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
Field(&UpToDataProjectParts::notUpToDate,
Field(&UpToDataProjectParts::updateSystem,
ElementsAre(updatedProjectPartContainer1))));
}
@@ -265,6 +295,24 @@ TEST_F(ProjectPartsManager, Remove)
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer2));
}
TEST_F(ProjectPartsManager, RemoveSystemDeferred)
{
manager.updateDeferred({projectPartContainer1, projectPartContainer2}, {});
manager.remove({projectPartContainer1.projectPartId});
ASSERT_THAT(manager.deferredSystemUpdates(), ElementsAre(projectPartContainer2));
}
TEST_F(ProjectPartsManager, RemoveProjectDeferred)
{
manager.updateDeferred({}, {projectPartContainer1, projectPartContainer2});
manager.remove({projectPartContainer1.projectPartId});
ASSERT_THAT(manager.deferredProjectUpdates(), ElementsAre(projectPartContainer2));
}
TEST_F(ProjectPartsManager, GetProjectById)
{
manager.update({projectPartContainer1, projectPartContainer2});
@@ -284,40 +332,84 @@ TEST_F(ProjectPartsManager, GetProjectsByIds)
ASSERT_THAT(projectPartContainers, UnorderedElementsAre(projectPartContainer1, projectPartContainer2));
}
TEST_F(ProjectPartsManager, UpdateDeferred)
TEST_F(ProjectPartsManager, UpdateSystemDeferred)
{
auto projectPartContainers = manager.update({projectPartContainer1, projectPartContainer2});
manager.updateDeferred({projectPartContainer1}, {});
manager.updateDeferred({projectPartContainer1});
ASSERT_THAT(manager.deferredUpdates(), ElementsAre(projectPartContainer1));
ASSERT_THAT(manager.deferredSystemUpdates(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, NotUpdateDeferred)
TEST_F(ProjectPartsManager, UpdateProjectDeferred)
{
manager.update({projectPartContainer1, projectPartContainer2});
manager.updateDeferred({}, {projectPartContainer1});
ASSERT_THAT(manager.deferredUpdates(), IsEmpty());
ASSERT_THAT(manager.deferredProjectUpdates(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, UpdateDeferredCleansDeferredUpdates)
TEST_F(ProjectPartsManager, NotUpdateSystemDeferred)
{
manager.update({projectPartContainer1, projectPartContainer2});
manager.updateDeferred({projectPartContainer1});
manager.deferredUpdates();
ASSERT_THAT(manager.deferredUpdates(), IsEmpty());
ASSERT_THAT(manager.deferredSystemUpdates(), IsEmpty());
}
TEST_F(ProjectPartsManager, NotUpdateProjectDeferred)
{
ASSERT_THAT(manager.deferredProjectUpdates(), IsEmpty());
}
TEST_F(ProjectPartsManager, UpdateSystemDeferredCleansDeferredUpdates)
{
manager.updateDeferred({projectPartContainer1}, {});
manager.deferredSystemUpdates();
ASSERT_THAT(manager.deferredSystemUpdates(), IsEmpty());
}
TEST_F(ProjectPartsManager, UpdateProjectDeferredCleansDeferredUpdates)
{
manager.updateDeferred({}, {projectPartContainer1});
manager.deferredProjectUpdates();
ASSERT_THAT(manager.deferredProjectUpdates(), IsEmpty());
}
TEST_F(ProjectPartsManager, UpdateSystemDeferredMultiple)
{
manager.updateDeferred({projectPartContainer1, projectPartContainer3}, {});
manager.updateDeferred({updatedProjectPartContainer1, projectPartContainer2, projectPartContainer4},
{});
ASSERT_THAT(manager.deferredSystemUpdates(),
ElementsAre(updatedProjectPartContainer1,
projectPartContainer2,
projectPartContainer3,
projectPartContainer4));
}
TEST_F(ProjectPartsManager, UpdateProjectDeferredMultiple)
{
manager.updateDeferred({}, {projectPartContainer1, projectPartContainer3});
manager.updateDeferred({},
{updatedProjectPartContainer1, projectPartContainer2, projectPartContainer4});
ASSERT_THAT(manager.deferredProjectUpdates(),
ElementsAre(updatedProjectPartContainer1,
projectPartContainer2,
projectPartContainer3,
projectPartContainer4));
}
TEST_F(ProjectPartsManager, UpdateCallsIfNewProjectPartIsAdded)
{
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectParts(ElementsAre(Eq(projectPartContainer1.projectPartId))));
EXPECT_CALL(mockProjectPartsStorage, updateProjectParts(ElementsAre(projectPartContainer1)));
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)));
EXPECT_CALL(mockProjectPartsStorage, resetIndexingTimeStamps(ElementsAre(projectPartContainer1)));
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteSystemAndProjectPrecompiledHeaders(
ElementsAre(projectPartContainer1.projectPartId)));
manager.update({projectPartContainer1});
}
@@ -353,6 +445,19 @@ TEST_F(ProjectPartsManager, UpdateCallsNotDeleteProjectPrecompiledHeadersIfNoNew
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager,
UpdateCallsNotDeleteSystemAndProjectPrecompiledHeadersIfNoNewerProjectPartsExists)
{
manager.update({projectPartContainer1});
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteSystemAndProjectPrecompiledHeaders(
ElementsAre(projectPartContainer1.projectPartId)))
.Times(0);
manager.update({projectPartContainer1});
}
TEST_F(ProjectPartsManager, UpdateCallsNotResetIndexingTimeStampsIfNoNewerProjectPartsExists)
{
manager.update({projectPartContainer1});
@@ -388,7 +493,8 @@ TEST_F(ProjectPartsManager, UpdateCallsIfUpdatedProjectPartIsAdded)
EXPECT_CALL(mockProjectPartsStorage,
updateProjectParts(ElementsAre(updatedProjectPartContainer1)));
EXPECT_CALL(mockPrecompiledHeaderStorage,
deleteProjectPrecompiledHeaders(ElementsAre(projectPartContainer1.projectPartId)));
deleteSystemAndProjectPrecompiledHeaders(
ElementsAre(projectPartContainer1.projectPartId)));
EXPECT_CALL(mockProjectPartsStorage,
resetIndexingTimeStamps(ElementsAre(updatedProjectPartContainer1)));
@@ -405,7 +511,7 @@ TEST_F(ProjectPartsManager,
ASSERT_THAT(projectParts,
AllOf(Field(&UpToDataProjectParts::upToDate, IsEmpty()),
Field(&UpToDataProjectParts::notUpToDate, ElementsAre(projectPartContainer1))));
Field(&UpToDataProjectParts::updateSystem, ElementsAre(projectPartContainer1))));
}
TEST_F(ProjectPartsManager, ProjectPartAddedWithProjectPartAlreadyInTheDatabaseButWithoutEntries)
@@ -418,4 +524,312 @@ TEST_F(ProjectPartsManager, ProjectPartAddedWithProjectPartAlreadyInTheDatabaseB
ASSERT_THAT(manager.projectParts(), ElementsAre(projectPartContainer1));
}
TEST_F(ProjectPartsManager, SystemSourcesTimeChanged)
{
SourceEntries oldSources{{1, SourceType::SystemInclude, 100},
{2, SourceType::ProjectInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 101},
{2, SourceType::ProjectInclude, 101}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateSystem, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateProject, IsEmpty());
ASSERT_THAT(upToDate.upToDate, IsEmpty());
}
TEST_F(ProjectPartsManager, TopSystemSourcesTimeChanged)
{
SourceEntries oldSources{{1, SourceType::TopSystemInclude, 100},
{2, SourceType::ProjectInclude, 100}};
SourceEntries newSources{{1, SourceType::TopSystemInclude, 101},
{2, SourceType::ProjectInclude, 101}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateSystem, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateProject, IsEmpty());
ASSERT_THAT(upToDate.upToDate, IsEmpty());
}
TEST_F(ProjectPartsManager, ProjectSourcesTimeChanged)
{
SourceEntries oldSources{{1, SourceType::SystemInclude, 100},
{2, SourceType::ProjectInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 100},
{2, SourceType::ProjectInclude, 101}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateProject, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateSystem, IsEmpty());
ASSERT_THAT(upToDate.upToDate, IsEmpty());
}
TEST_F(ProjectPartsManager, TopProjectSourcesTimeChanged)
{
SourceEntries oldSources{{1, SourceType::SystemInclude, 100},
{2, SourceType::TopProjectInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 100},
{2, SourceType::TopProjectInclude, 101}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateProject, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateSystem, IsEmpty());
ASSERT_THAT(upToDate.upToDate, IsEmpty());
}
TEST_F(ProjectPartsManager, UserIncludeSourcesTimeChanged)
{
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}, {2, SourceType::UserInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 100}, {2, SourceType::UserInclude, 101}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.upToDate, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateProject, IsEmpty());
ASSERT_THAT(upToDate.updateSystem, IsEmpty());
}
TEST_F(ProjectPartsManager, SourcesTimeChanged)
{
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}, {2, SourceType::Source, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 100}, {2, SourceType::Source, 101}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.upToDate, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateProject, IsEmpty());
ASSERT_THAT(upToDate.updateSystem, IsEmpty());
}
TEST_F(ProjectPartsManager, SourcesTimeNotChanged)
{
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 100}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.upToDate, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateSystem, IsEmpty());
ASSERT_THAT(upToDate.updateProject, IsEmpty());
}
TEST_F(ProjectPartsManager, TimeChangedForOneProject)
{
manager.update({projectPartContainer1, projectPartContainer2});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(SourceEntries{{1, SourceType::SystemInclude, 100}}));
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer2.sourcePathIds),
Eq(projectPartContainer2.projectPartId)))
.WillByDefault(Return(SourceEntries{{4, SourceType::SystemInclude, 100}}));
ON_CALL(mockBuildDependenciesProvider,
create(Eq(projectPartContainer1), Eq(SourceEntries{{1, SourceType::SystemInclude, 100}})))
.WillByDefault(Return(
ClangBackEnd::BuildDependency{{{1, SourceType::SystemInclude, 101}}, {}, {}, {}, {}}));
ON_CALL(mockBuildDependenciesProvider,
create(Eq(projectPartContainer2), Eq(SourceEntries{{4, SourceType::SystemInclude, 100}})))
.WillByDefault(Return(
ClangBackEnd::BuildDependency{{{4, SourceType::SystemInclude, 100}}, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1, projectPartContainer2});
ASSERT_THAT(upToDate.updateSystem, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateProject, IsEmpty());
ASSERT_THAT(upToDate.upToDate, ElementsAre(projectPartContainer2));
}
TEST_F(ProjectPartsManager, AddSystemInclude)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 100}, {2, SourceType::SystemInclude, 100}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateSystem, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateProject, IsEmpty());
ASSERT_THAT(upToDate.upToDate, IsEmpty());
}
TEST_F(ProjectPartsManager, ChangeFromProjectToSystemInclude)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::ProjectInclude, 100}};
SourceEntries newSources{{1, SourceType::SystemInclude, 100}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateSystem, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateProject, IsEmpty());
ASSERT_THAT(upToDate.upToDate, IsEmpty());
}
TEST_F(ProjectPartsManager, ChangeFromSystemToProjectInclude)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
SourceEntries newSources{{1, SourceType::ProjectInclude, 100}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateSystem, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateProject, IsEmpty());
ASSERT_THAT(upToDate.upToDate, IsEmpty());
}
TEST_F(ProjectPartsManager, ChangeFromProjectToUserInclude)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::ProjectInclude, 100}};
SourceEntries newSources{{1, SourceType::UserInclude, 100}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateProject, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.upToDate, IsEmpty());
ASSERT_THAT(upToDate.updateSystem, IsEmpty());
}
TEST_F(ProjectPartsManager, ChangeFromSystemToUserInclude)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::SystemInclude, 100}};
SourceEntries newSources{{1, SourceType::UserInclude, 100}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.updateSystem, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.upToDate, IsEmpty());
ASSERT_THAT(upToDate.updateProject, IsEmpty());
}
TEST_F(ProjectPartsManager, ChangeFromSourceToUserInclude)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::Source, 100}};
SourceEntries newSources{{1, SourceType::UserInclude, 100}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.upToDate, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateSystem, IsEmpty());
ASSERT_THAT(upToDate.updateProject, IsEmpty());
}
TEST_F(ProjectPartsManager, ChangeFromUserIncludeToSource)
{
manager.update({projectPartContainer1});
SourceEntries oldSources{{1, SourceType::UserInclude, 100}};
SourceEntries newSources{{1, SourceType::Source, 100}};
manager.update({projectPartContainer1});
ON_CALL(mockBuildDependenciesProvider,
createSourceEntriesFromStorage(Eq(projectPartContainer1.sourcePathIds),
Eq(projectPartContainer1.projectPartId)))
.WillByDefault(Return(oldSources));
ON_CALL(mockBuildDependenciesProvider, create(Eq(projectPartContainer1), Eq(oldSources)))
.WillByDefault(Return(ClangBackEnd::BuildDependency{newSources, {}, {}, {}, {}}));
auto upToDate = manager.update({projectPartContainer1});
ASSERT_THAT(upToDate.upToDate, ElementsAre(projectPartContainer1));
ASSERT_THAT(upToDate.updateSystem, IsEmpty());
ASSERT_THAT(upToDate.updateProject, IsEmpty());
}
} // namespace