Clang: Differentiate between user and non user includes for updating

We don't want to recreate a PCH if the include or source is not
contained by a PCH.

Change-Id: If52fc1aed92054b4165cdc634656147fbe8baa47
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-06-20 18:34:02 +02:00
parent c4b80a2ec0
commit cc87615fcd
37 changed files with 909 additions and 1105 deletions

View File

@@ -1,4 +1,4 @@
; /****************************************************************************
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
@@ -57,7 +57,7 @@ void set_greedy_intersection_call(
class WatcherEntry
{
public:
ProjectPartId id;
ProjectChunkId id;
DirectoryPathId directoryPathId;
FilePathId filePathId;
long long lastModified = -1;
@@ -140,25 +140,6 @@ public:
m_notifier = notifier;
}
static std::vector<uint> idsFromIdPaths(const std::vector<IdPaths> &idPaths)
{
std::vector<uint> ids;
ids.reserve(idPaths.size());
auto extractId = [] (const IdPaths &idPath) {
return idPath.id;
};
std::transform(idPaths.begin(),
idPaths.end(),
std::back_inserter(ids),
extractId);
std::sort(ids.begin(), ids.end());
return ids;
}
std::size_t sizeOfIdPaths(const std::vector<IdPaths> &idPaths)
{
auto sumSize = [] (std::size_t size, const IdPaths &idPath) {
@@ -168,19 +149,19 @@ public:
return std::accumulate(idPaths.begin(), idPaths.end(), std::size_t(0), sumSize);
}
std::pair<WatcherEntries, ProjectPartIds> convertIdPathsToWatcherEntriesAndIds(
std::pair<WatcherEntries, ProjectChunkIds> convertIdPathsToWatcherEntriesAndIds(
const std::vector<IdPaths> &idPaths)
{
WatcherEntries entries;
entries.reserve(sizeOfIdPaths(idPaths));
ProjectPartIds ids;
ProjectChunkIds ids;
ids.reserve(ids.size());
auto outputIterator = std::back_inserter(entries);
for (const IdPaths &idPath : idPaths)
{
ProjectPartId id = idPath.id;
ProjectChunkId id = idPath.id;
ids.push_back(id);
@@ -214,7 +195,7 @@ public:
m_fileSystemWatcher.addPaths(convertWatcherEntriesToDirectoryPathList(filteredPaths));
}
void removeUnusedEntries(const WatcherEntries &entries, const ProjectPartIds &ids)
void removeUnusedEntries(const WatcherEntries &entries, const ProjectChunkIds &ids)
{
auto oldEntries = notAnymoreWatchedEntriesWithIds(entries, ids);
@@ -294,7 +275,7 @@ public:
}
WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries,
const ProjectPartIds &ids) const
const ProjectChunkIds &ids) const
{
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
@@ -420,25 +401,22 @@ public:
return filePathIds;
}
ProjectPartIds idsForWatcherEntries(const WatcherEntries &foundEntries)
std::vector<IdPaths> idPathsForWatcherEntries(WatcherEntries &&foundEntries)
{
ProjectPartIds ids;
ids.reserve(foundEntries.size());
std::sort(foundEntries.begin(), foundEntries.end(), [](WatcherEntry first, WatcherEntry second) {
return std::tie(first.id, first.filePathId) < std::tie(second.id, second.filePathId);
});
std::transform(foundEntries.begin(),
foundEntries.end(),
std::back_inserter(ids),
[&](WatcherEntry entry) { return entry.id; });
std::vector<IdPaths> idPaths;
idPaths.reserve(foundEntries.size());
return ids;
}
for (WatcherEntry entry : foundEntries) {
if (idPaths.empty() || idPaths.back().id != entry.id)
idPaths.push_back({entry.id, {}});
idPaths.back().filePathIds.push_back(entry.filePathId);
}
ProjectPartIds uniqueIds(ProjectPartIds &&ids)
{
std::sort(ids.begin(), ids.end());
ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
return std::move(ids);
return idPaths;
}
void addChangedPathForFilePath(DirectoryPathIds &&directoryPathIds)
@@ -446,10 +424,12 @@ public:
if (m_notifier) {
WatcherEntries foundEntries = watchedEntriesForPaths(std::move(directoryPathIds));
ProjectPartIds changedIds = idsForWatcherEntries(foundEntries);
FilePathIds watchedFilePathIds = watchedPaths(foundEntries);
m_notifier->pathsWithIdsChanged(uniqueIds(std::move(changedIds)));
m_notifier->pathsChanged(watchedPaths(foundEntries));
std::vector<IdPaths> changedIdPaths = idPathsForWatcherEntries(std::move(foundEntries));
m_notifier->pathsChanged(watchedFilePathIds);
m_notifier->pathsWithIdsChanged(changedIdPaths);
}
}

View File

@@ -26,9 +26,8 @@
#pragma once
#include "clangsupport_global.h"
#include <filepathid.h>
#include <projectpartid.h>
#include "filepathid.h"
#include "idpaths.h"
#include <utils/smallstringvector.h>
@@ -41,7 +40,7 @@ public:
ClangPathWatcherNotifier(const ClangPathWatcherNotifier &) = delete;
ClangPathWatcherNotifier &operator=(const ClangPathWatcherNotifier &) = delete;
virtual void pathsWithIdsChanged(const ProjectPartIds &ids) = 0;
virtual void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) = 0;
virtual void pathsChanged(const FilePathIds &filePathIds) = 0;
protected:

View File

@@ -120,6 +120,7 @@ HEADERS += \
$$PWD/projectpartid.h \
$$PWD/projectpartsstorage.h \
$$PWD/projectpartsstorageinterface.h \
$$PWD/projectsourcechunk.h \
$$PWD/requestcompletionsmessage.h \
$$PWD/echomessage.h \
$$PWD/endmessage.h \

View File

@@ -25,21 +25,60 @@
#pragma once
#include "projectpartid.h"
#include "filepathid.h"
#include "projectpartid.h"
#include "sourceentry.h"
namespace ClangBackEnd {
class ProjectChunkId
{
public:
ProjectPartId id;
SourceType sourceType;
friend bool operator==(ProjectChunkId first, ProjectChunkId second)
{
return first.id == second.id && first.sourceType == second.sourceType;
}
friend bool operator==(ProjectChunkId first, ProjectPartId second)
{
return first.id == second;
}
friend bool operator==(ProjectPartId first, ProjectChunkId second)
{
return first == second.id;
}
friend bool operator!=(ProjectChunkId first, ProjectChunkId second)
{
return !(first == second);
}
friend bool operator<(ProjectChunkId first, ProjectChunkId second)
{
return std::tie(first.id, first.sourceType) < std::tie(second.id, second.sourceType);
}
friend bool operator<(ProjectChunkId first, ProjectPartId second) { return first.id < second; }
friend bool operator<(ProjectPartId first, ProjectChunkId second) { return first < second.id; }
};
class IdPaths
{
public:
ProjectPartId id;
ProjectChunkId id;
FilePathIds filePathIds;
friend bool operator==(const IdPaths &first, const IdPaths &second)
friend bool operator==(IdPaths first, IdPaths second)
{
return first.id == second.id && first.filePathIds == second.filePathIds;
}
};
using ProjectChunkIds = std::vector<ProjectChunkId>;
} // namespace ClangBackEnd

View File

@@ -26,6 +26,7 @@
#pragma once
#include "clangsupport_global.h"
#include "filepathid.h"
#include "projectpartid.h"
#include <utils/smallstringio.h>
@@ -37,6 +38,7 @@ class PrecompiledHeadersUpdatedMessage
public:
PrecompiledHeadersUpdatedMessage() = default;
PrecompiledHeadersUpdatedMessage(ProjectPartId projectPartId)
{
projectPartIds.push_back(projectPartId);
}

View File

@@ -225,7 +225,8 @@ struct Data // because we have a cycle dependency
PchManagerServer clangPchManagerServer{includeWatcher,
pchTaskGenerator,
projectParts,
generatedFiles};
generatedFiles,
buildDependencyStorage};
TaskScheduler systemTaskScheduler{pchCreatorManager,
pchTaskQueue,
pchCreationProgressCounter,

View File

@@ -71,6 +71,11 @@ public:
return fetchPchSourcesStatement.template values<FilePathId>(1024, projectPartId.projectPathId);
}
FilePathIds fetchSources(ProjectPartId projectPartId) const override
{
return fetchSourcesStatement.template values<FilePathId>(1024, projectPartId.projectPathId);
}
void insertOrUpdateFileStatuses(const FileStatuses &fileStatuses) override
{
WriteStatement &statement = insertOrUpdateFileStatusesStatement;
@@ -144,6 +149,94 @@ public:
transaction.commit();
}
void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds,
TimeStamp indexingTimeStamp) override
{
try {
Sqlite::ImmediateTransaction transaction{database};
for (FilePathId filePathId : filePathIds) {
inserOrUpdateIndexingTimesStampStatement.write(filePathId.filePathId,
indexingTimeStamp.value);
}
transaction.commit();
} catch (const Sqlite::StatementIsBusy &) {
insertOrUpdateIndexingTimeStamps(filePathIds, indexingTimeStamp);
}
}
void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) override
{
for (FileStatus fileStatus : fileStatuses) {
inserOrUpdateIndexingTimesStampStatement.write(fileStatus.filePathId.filePathId,
fileStatus.lastModified);
}
}
SourceTimeStamps fetchIndexingTimeStamps() const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto timeStamps = fetchIndexingTimeStampsStatement.template values<SourceTimeStamp, 2>(
1024);
transaction.commit();
return timeStamps;
} catch (const Sqlite::StatementIsBusy &) {
return fetchIndexingTimeStamps();
}
}
SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto timeStamps = fetchIncludedIndexingTimeStampsStatement
.template values<SourceTimeStamp, 2>(1024, sourcePathId.filePathId);
transaction.commit();
return timeStamps;
} catch (const Sqlite::StatementIsBusy &) {
return fetchIncludedIndexingTimeStamps(sourcePathId);
}
}
FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const override
{
try {
FilePathIds dependentSourceIds;
Sqlite::DeferredTransaction transaction{database};
for (FilePathId sourcePathId : sourcePathIds) {
FilePathIds newDependentSourceIds;
newDependentSourceIds.reserve(dependentSourceIds.size() + 1024);
auto newIds = fetchDependentSourceIdsStatement
.template values<FilePathId>(1024, sourcePathId.filePathId);
std::set_union(dependentSourceIds.begin(),
dependentSourceIds.end(),
newIds.begin(),
newIds.end(),
std::back_inserter(newDependentSourceIds));
dependentSourceIds = std::move(newDependentSourceIds);
}
transaction.commit();
return dependentSourceIds;
} catch (const Sqlite::StatementIsBusy &) {
return fetchDependentSourceIds(sourcePathIds);
}
}
static Utils::SmallString toJson(const Utils::SmallStringVector &strings)
{
QJsonDocument document;
@@ -255,6 +348,8 @@ public:
"SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? AND sourceType IN (0, 1, "
"3, 4) ORDER BY sourceId",
database};
mutable ReadStatement fetchSourcesStatement{
"SELECT sourceId FROM projectPartsFiles WHERE projectPartId = ? ORDER BY sourceId", database};
mutable ReadStatement fetchSourceDependenciesStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION "
"SELECT dependencySourceId FROM sourceDependencies, "
@@ -279,5 +374,24 @@ public:
database};
WriteStatement deleteAllProjectPartsFilesWithProjectPartNameStatement{
"DELETE FROM projectPartsFiles WHERE projectPartId = ?", database};
WriteStatement inserOrUpdateIndexingTimesStampStatement{
"INSERT INTO fileStatuses(sourceId, indexingTimeStamp) VALUES (?001, ?002) ON "
"CONFLICT(sourceId) DO UPDATE SET indexingTimeStamp = ?002",
database};
mutable ReadStatement fetchIncludedIndexingTimeStampsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"dependencySourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.sourceId == collectedDependencies.sourceId) SELECT DISTINCT sourceId, "
"indexingTimeStamp FROM collectedDependencies NATURAL JOIN fileStatuses ORDER BY sourceId",
database};
mutable ReadStatement fetchIndexingTimeStampsStatement{
"SELECT sourceId, indexingTimeStamp FROM fileStatuses", database};
mutable ReadStatement fetchDependentSourceIdsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"sourceDependencies.sourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.dependencySourceId == collectedDependencies.sourceId) SELECT sourceId "
"FROM collectedDependencies WHERE sourceId NOT IN (SELECT dependencySourceId FROM "
"sourceDependencies) ORDER BY sourceId",
database};
};
}

View File

@@ -57,6 +57,12 @@ public:
virtual ProjectPartId fetchProjectPartId(Utils::SmallStringView projectPartName) = 0;
virtual void updatePchCreationTimeStamp(long long pchCreationTimeStamp, ProjectPartId projectPartId) = 0;
virtual FilePathIds fetchPchSources(ProjectPartId projectPartId) const = 0;
virtual FilePathIds fetchSources(ProjectPartId projectPartId) const = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0;
virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0;
virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0;
virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0;
protected:
~BuildDependenciesStorageInterface() = default;

View File

@@ -45,6 +45,8 @@
#include <QProcess>
#include <QTemporaryFile>
#include <iostream>
namespace ClangBackEnd {
namespace {
@@ -110,11 +112,28 @@ Utils::SmallStringVector PchCreator::generateClangCompilerArguments(const PchTas
return builder.commandLine;
}
FilePathIds PchCreator::existingSources(FilePathIds sources) const
{
FilePathIds existingSources;
existingSources.reserve(sources.size());
std::set_difference(sources.begin(),
sources.end(),
m_generatedFilePathIds.begin(),
m_generatedFilePathIds.end(),
std::back_inserter(existingSources));
return existingSources;
}
void PchCreator::generatePch(PchTask &&pchTask)
{
m_projectPartPch.projectPartId = pchTask.projectPartId();
m_projectPartPch.lastModified = QDateTime::currentSecsSinceEpoch();
m_sources = std::move(pchTask.sources);
m_watchedSystemIncludes = std::move(pchTask.watchedSystemIncludes);
m_watchedProjectIncludes = std::move(pchTask.watchedProjectIncludes);
m_watchedUserIncludes = std::move(pchTask.watchedUserIncludes);
m_watchedSources = std::move(pchTask.watchedUserSources);
if (pchTask.includes.empty())
return;
@@ -166,23 +185,26 @@ void PchCreator::clear()
{
m_clangTool = ClangTool{};
m_projectPartPch = {};
m_sources.clear();
m_watchedSystemIncludes.clear();
m_watchedProjectIncludes.clear();
m_watchedUserIncludes.clear();
m_watchedSources.clear();
}
void PchCreator::doInMainThreadAfterFinished()
{
if (m_projectPartPch.projectPartId.isValid()) {
FilePathIds existingSources;
existingSources.reserve(m_sources.size());
std::set_difference(m_sources.begin(),
m_sources.end(),
m_generatedFilePathIds.begin(),
m_generatedFilePathIds.end(),
std::back_inserter(existingSources));
m_buildDependenciesStorage.updatePchCreationTimeStamp(m_projectPartPch.lastModified,
m_projectPartPch.projectPartId);
m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, existingSources}});
m_pchManagerClient.precompiledHeadersUpdated({m_projectPartPch.projectPartId});
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::Source},
existingSources(m_watchedSources)}});
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::UserInclude},
existingSources(m_watchedUserIncludes)}});
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::ProjectInclude},
existingSources(m_watchedProjectIncludes)}});
m_clangPathwatcher.updateIdPaths({{{m_projectPartPch.projectPartId, SourceType::SystemInclude},
existingSources(m_watchedSystemIncludes)}});
m_pchManagerClient.precompiledHeadersUpdated(m_projectPartPch.projectPartId);
}
}

View File

@@ -80,19 +80,24 @@ public:
static Utils::SmallStringVector generateClangCompilerArguments(const PchTask &pchTask,
FilePathView pchPath);
const ClangTool &clangTool() const
{
return m_clangTool;
}
const ClangTool &clangTool() const { return m_clangTool; }
const FilePathIds &sources() const { return m_sources; }
FilePathIds existingSources(FilePathIds sources) const;
const FilePathIds &watchedSystemIncludes() const { return m_watchedSystemIncludes; }
const FilePathIds &watchedProjectIncludes() const { return m_watchedProjectIncludes; }
const FilePathIds &watchedUserIncludes() const { return m_watchedUserIncludes; }
const FilePathIds &watchedSources() const { return m_watchedSources; }
private:
mutable std::mt19937_64 randomNumberGenator{std::random_device{}()};
ClangTool m_clangTool;
ProjectPartPch m_projectPartPch;
FilePathCaching m_filePathCache;
FilePathIds m_sources;
FilePathIds m_watchedSystemIncludes;
FilePathIds m_watchedProjectIncludes;
FilePathIds m_watchedUserIncludes;
FilePathIds m_watchedSources;
FilePathIds m_generatedFilePathIds;
Environment &m_environment;
PchManagerClientInterface &m_pchManagerClient;

View File

@@ -25,10 +25,11 @@
#include "pchmanagerserver.h"
#include <builddependenciesstorage.h>
#include <pchmanagerclientinterface.h>
#include <pchtaskgeneratorinterface.h>
#include <precompiledheadersupdatedmessage.h>
#include <progressmessage.h>
#include <pchtaskgeneratorinterface.h>
#include <removegeneratedfilesmessage.h>
#include <removeprojectpartsmessage.h>
#include <updategeneratedfilesmessage.h>
@@ -39,16 +40,20 @@
#include <QApplication>
#include <algorithm>
namespace ClangBackEnd {
PchManagerServer::PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
PchTaskGeneratorInterface &pchTaskGenerator,
ProjectPartsManagerInterface &projectParts,
GeneratedFilesInterface &generatedFiles)
GeneratedFilesInterface &generatedFiles,
BuildDependenciesStorageInterface &buildDependenciesStorage)
: m_fileSystemWatcher(fileSystemWatcher)
, m_pchTaskGenerator(pchTaskGenerator)
, m_projectPartsManager(projectParts)
, m_generatedFiles(generatedFiles)
, m_buildDependenciesStorage(buildDependenciesStorage)
{
m_fileSystemWatcher.setNotifier(this);
}
@@ -130,18 +135,74 @@ void PchManagerServer::removeGeneratedFiles(RemoveGeneratedFilesMessage &&messag
m_generatedFiles.remove(message.takeGeneratedFiles());
}
void PchManagerServer::pathsWithIdsChanged(const ProjectPartIds &ids)
namespace {
struct FilterResults
{
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(ids);
ProjectPartIds systemIds;
ProjectPartIds projectIds;
ProjectPartIds userIds;
};
std::pair<ProjectPartIds, ProjectPartIds> pchProjectPartIds(const std::vector<IdPaths> &idPaths)
{
ProjectPartIds changedProjectPartIds;
changedProjectPartIds.reserve(idPaths.size());
ProjectPartIds changedPchProjectPartIds;
changedPchProjectPartIds.reserve(idPaths.size());
for (const IdPaths &idPath : idPaths) {
switch (idPath.id.sourceType) {
case SourceType::TopSystemInclude:
case SourceType::SystemInclude:
case SourceType::TopProjectInclude:
case SourceType::ProjectInclude:
changedPchProjectPartIds.push_back(idPath.id.id);
break;
case SourceType::UserInclude:
case SourceType::Source:
changedProjectPartIds.push_back(idPath.id.id);
break;
}
}
changedPchProjectPartIds.erase(std::unique(changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end()),
changedPchProjectPartIds.end());
changedPchProjectPartIds.erase(std::unique(changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end()),
changedPchProjectPartIds.end());
ProjectPartIds changedUserProjectPartIds;
changedProjectPartIds.reserve(changedProjectPartIds.size());
std::set_difference(changedProjectPartIds.begin(),
changedProjectPartIds.end(),
changedPchProjectPartIds.begin(),
changedPchProjectPartIds.end(),
std::back_inserter(changedUserProjectPartIds));
return {changedPchProjectPartIds, changedUserProjectPartIds};
}
} // namespace
void PchManagerServer::pathsWithIdsChanged(const std::vector<IdPaths> &idPaths)
{
auto changedProjectPartIds = pchProjectPartIds(idPaths);
ArgumentsEntries entries = m_toolChainsArgumentsCache.arguments(changedProjectPartIds.first);
for (ArgumentsEntry &entry : entries) {
m_pchTaskGenerator.addProjectParts(m_projectPartsManager.projects(entry.ids),
std::move(entry.arguments));
}
client()->precompiledHeadersUpdated(std::move(changedProjectPartIds.second));
}
void PchManagerServer::pathsChanged(const FilePathIds &/*filePathIds*/)
void PchManagerServer::pathsChanged(const FilePathIds &filePathIds)
{
m_buildDependenciesStorage.insertOrUpdateIndexingTimeStamps(filePathIds, 0);
}
void PchManagerServer::setPchCreationProgress(int progress, int total)

View File

@@ -39,6 +39,7 @@ namespace ClangBackEnd {
class SourceRangesAndDiagnosticsForQueryMessage;
class PchTaskGeneratorInterface;
class BuildDependenciesStorageInterface;
class PchManagerServer : public PchManagerServerInterface,
public ClangPathWatcherNotifier,
@@ -49,7 +50,8 @@ public:
PchManagerServer(ClangPathWatcherInterface &fileSystemWatcher,
PchTaskGeneratorInterface &pchTaskGenerator,
ProjectPartsManagerInterface &projectParts,
GeneratedFilesInterface &generatedFiles);
GeneratedFilesInterface &generatedFiles,
BuildDependenciesStorageInterface &buildDependenciesStorage);
void end() override;
void updateProjectParts(UpdateProjectPartsMessage &&message) override;
@@ -57,7 +59,7 @@ public:
void updateGeneratedFiles(UpdateGeneratedFilesMessage &&message) override;
void removeGeneratedFiles(RemoveGeneratedFilesMessage &&message) override;
void pathsWithIdsChanged(const ProjectPartIds &ids) override;
void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) override;
void pathsChanged(const FilePathIds &filePathIds) override;
void setPchCreationProgress(int progress, int total);
@@ -68,6 +70,7 @@ private:
PchTaskGeneratorInterface &m_pchTaskGenerator;
ProjectPartsManagerInterface &m_projectPartsManager;
GeneratedFilesInterface &m_generatedFiles;
BuildDependenciesStorageInterface &m_buildDependenciesStorage;
ToolChainsArgumentsCache m_toolChainsArgumentsCache;
};

View File

@@ -42,7 +42,10 @@ class PchTask
public:
PchTask(ProjectPartId projectPartId,
FilePathIds &&includes,
FilePathIds &&sources,
FilePathIds &&watchedSystemIncludes,
FilePathIds &&watchedProjectIncludes,
FilePathIds &&watchedUserIncludes,
FilePathIds &&watchedUserSources,
CompilerMacros &&compilerMacros,
Utils::SmallStringVector &&usedMacros, // TODO remove
Utils::SmallStringVector toolChainArguments,
@@ -53,7 +56,10 @@ public:
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None)
: projectPartIds({projectPartId})
, includes(includes)
, sources(sources)
, watchedSystemIncludes(watchedSystemIncludes)
, watchedProjectIncludes(watchedProjectIncludes)
, watchedUserIncludes(watchedUserIncludes)
, watchedUserSources(watchedUserSources)
, compilerMacros(compilerMacros)
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
@@ -65,7 +71,10 @@ public:
PchTask(ProjectPartIds &&projectPartIds,
FilePathIds &&includes,
FilePathIds &&sources,
FilePathIds &&watchedSystemIncludes,
FilePathIds &&watchedProjectIncludes,
FilePathIds &&watchedUserIncludes,
FilePathIds &&watchedUserSources,
CompilerMacros &&compilerMacros,
Utils::SmallStringVector &&usedMacros, // TODO remove
Utils::SmallStringVector toolChainArguments,
@@ -76,7 +85,10 @@ public:
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None)
: projectPartIds(std::move(projectPartIds))
, includes(includes)
, sources(sources)
, watchedSystemIncludes(watchedSystemIncludes)
, watchedProjectIncludes(watchedProjectIncludes)
, watchedUserIncludes(watchedUserIncludes)
, watchedUserSources(watchedUserSources)
, compilerMacros(compilerMacros)
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
@@ -90,6 +102,10 @@ public:
{
return first.systemPchPath == second.systemPchPath
&& first.projectPartIds == second.projectPartIds && first.includes == second.includes
&& first.watchedSystemIncludes == second.watchedSystemIncludes
&& first.watchedProjectIncludes == second.watchedProjectIncludes
&& first.watchedUserIncludes == second.watchedUserIncludes
&& first.watchedUserSources == second.watchedUserSources
&& first.compilerMacros == second.compilerMacros
&& first.systemIncludeSearchPaths == second.systemIncludeSearchPaths
&& first.projectIncludeSearchPaths == second.projectIncludeSearchPaths
@@ -105,7 +121,10 @@ public:
FilePath systemPchPath;
ProjectPartIds projectPartIds;
FilePathIds includes;
FilePathIds sources;
FilePathIds watchedSystemIncludes;
FilePathIds watchedProjectIncludes;
FilePathIds watchedUserIncludes;
FilePathIds watchedUserSources;
CompilerMacros compilerMacros;
IncludeSearchPaths systemIncludeSearchPaths;
IncludeSearchPaths projectIncludeSearchPaths;

View File

@@ -52,6 +52,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
pchTaskSets.emplace_back(PchTask{projectPart.projectPartId,
std::move(filter.topSystemIncludes),
{},
{},
{},
{},
std::move(filter.systemCompilerMacros),
std::move(filter.systemUsedMacros),
projectPart.toolChainArguments,
@@ -62,6 +65,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
projectPart.languageExtension},
PchTask{projectPart.projectPartId,
std::move(filter.topProjectIncludes),
std::move(filter.systemIncludes),
std::move(filter.projectIncludes),
std::move(filter.userIncludes),
std::move(filter.sources),
std::move(filter.projectCompilerMacros),
std::move(filter.projectUsedMacros),

View File

@@ -98,8 +98,8 @@ bool PchTasksMerger::mergePchTasks(PchTask &firstTask, PchTask &secondTask)
firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds),
std::move(secondTask.projectPartIds));
firstTask.includes = merge(std::move(firstTask.includes), std::move(secondTask.includes));
firstTask.sources = merge(std::move(firstTask.sources),
std::move(secondTask.sources));
firstTask.watchedSystemIncludes = merge(std::move(firstTask.watchedSystemIncludes),
std::move(secondTask.watchedSystemIncludes));
firstTask.compilerMacros = std::move(macros);
firstTask.systemIncludeSearchPaths = mergeIncludeSearchPaths(
std::move(firstTask.systemIncludeSearchPaths),

View File

@@ -99,6 +99,7 @@ public:
projectIncludes.reserve(sources.size());
topSystemIncludes.reserve(sources.size() / 10);
topProjectIncludes.reserve(sources.size() / 10);
userIncludes.reserve(sources.size());
this->sources.reserve(sources.size());
for (SourceEntry source : sources)
@@ -128,23 +129,22 @@ private:
case SourceType::TopSystemInclude:
topSystemIncludes.emplace_back(source.sourceId);
systemIncludes.emplace_back(source.sourceId);
sources.emplace_back(source.sourceId);
break;
case SourceType::SystemInclude:
systemIncludes.emplace_back(source.sourceId);
sources.emplace_back(source.sourceId);
break;
case SourceType::TopProjectInclude:
topProjectIncludes.emplace_back(source.sourceId);
projectIncludes.emplace_back(source.sourceId);
sources.emplace_back(source.sourceId);
break;
case SourceType::ProjectInclude:
projectIncludes.emplace_back(source.sourceId);
sources.emplace_back(source.sourceId);
break;
case SourceType::UserInclude:
userIncludes.emplace_back(source.sourceId);
break;
case SourceType::Source:
sources.emplace_back(source.sourceId);
break;
}
@@ -215,6 +215,7 @@ private:
public:
FilePathIds sources;
FilePathIds userIncludes;
FilePathIds projectIncludes;
FilePathIds systemIncludes;
FilePathIds topProjectIncludes;

View File

@@ -98,7 +98,7 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
std::vector<SymbolIndexerTask> symbolIndexerTask;
symbolIndexerTask.reserve(projectPart.sourcePathIds.size());
for (FilePathId sourcePathId : projectPart.sourcePathIds) {
SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(
SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps(
sourcePathId);
if (!m_modifiedTimeChecker.isUpToDate(dependentTimeStamps)) {
@@ -122,7 +122,8 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
auto store = [&] {
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(
symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
transaction.commit();
@@ -144,28 +145,17 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
}
}
m_pathWatcher.updateIdPaths(
{{projectPartId, m_buildDependencyStorage.fetchPchSources(projectPartId)}});
m_pathWatcher.updateIdPaths({{{projectPartId, SourceType::Source},
m_buildDependencyStorage.fetchPchSources(projectPartId)}});
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries();
}
void SymbolIndexer::pathsWithIdsChanged(const ProjectPartIds &) {}
void SymbolIndexer::pathsWithIdsChanged(const std::vector<IdPaths> &) {}
void SymbolIndexer::pathsChanged(const FilePathIds &filePathIds)
{
m_modifiedTimeChecker.pathsChanged(filePathIds);
FilePathIds dependentSourcePathIds = m_symbolStorage.fetchDependentSourceIds(filePathIds);
std::vector<SymbolIndexerTask> symbolIndexerTask;
symbolIndexerTask.reserve(dependentSourcePathIds.size());
for (FilePathId dependentSourcePathId : dependentSourcePathIds)
updateChangedPath(dependentSourcePathId, symbolIndexerTask);
m_symbolIndexerTaskQueue.addOrUpdateTasks(std::move(symbolIndexerTask));
m_symbolIndexerTaskQueue.processEntries();
}
void SymbolIndexer::updateChangedPath(FilePathId filePathId,
@@ -182,7 +172,8 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
ProjectPartId projectPartId = optionalArtefact->projectPartId;
SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(filePathId);
SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps(
filePathId);
auto indexing = [optionalArtefact = std::move(optionalArtefact),
filePathId,
@@ -207,7 +198,7 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
auto store = [&] {
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
m_symbolStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
transaction.commit();

View File

@@ -60,7 +60,7 @@ public:
void updateProjectParts(ProjectPartContainers &&projectParts);
void updateProjectPart(ProjectPartContainer &&projectPart);
void pathsWithIdsChanged(const ProjectPartIds &ids) override;
void pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) override;
void pathsChanged(const FilePathIds &filePathIds) override;
void updateChangedPath(FilePathId filePath,
std::vector<SymbolIndexerTask> &symbolIndexerTask);
@@ -75,6 +75,9 @@ public:
FilePathIds updatableFilePathIds(const ProjectPartContainer &projectPart,
const Utils::optional<ProjectPartArtefact> &optionalArtefact) const;
private:
FilePathIds filterProjectPartSources(const FilePathIds &filePathIds) const;
private:
SymbolIndexerTaskQueueInterface &m_symbolIndexerTaskQueue;
SymbolStorageInterface &m_symbolStorage;

View File

@@ -70,93 +70,6 @@ public:
deleteNewLocationsTable();
}
void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) override
{
try {
Sqlite::ImmediateTransaction transaction{database};
for (FilePathId filePathId : filePathIds) {
inserOrUpdateIndexingTimesStampStatement.write(filePathId.filePathId,
indexingTimeStamp.value);
}
transaction.commit();
} catch (const Sqlite::StatementIsBusy &) {
insertOrUpdateIndexingTimeStamps(filePathIds, indexingTimeStamp);
}
}
void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) override
{
for (FileStatus fileStatus : fileStatuses) {
inserOrUpdateIndexingTimesStampStatement.write(fileStatus.filePathId.filePathId,
fileStatus.lastModified);
}
}
SourceTimeStamps fetchIndexingTimeStamps() const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto timeStamps = fetchIndexingTimeStampsStatement.template values<SourceTimeStamp, 2>(
1024);
transaction.commit();
return timeStamps;
} catch (const Sqlite::StatementIsBusy &) {
return fetchIndexingTimeStamps();
}
}
SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const override
{
try {
Sqlite::DeferredTransaction transaction{database};
auto timeStamps = fetchIncludedIndexingTimeStampsStatement
.template values<SourceTimeStamp, 2>(1024, sourcePathId.filePathId);
transaction.commit();
return timeStamps;
} catch (const Sqlite::StatementIsBusy &) {
return fetchIncludedIndexingTimeStamps(sourcePathId);
}
}
FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const override
{
try {
FilePathIds dependentSourceIds;
Sqlite::DeferredTransaction transaction{database};
for (FilePathId sourcePathId : sourcePathIds) {
FilePathIds newDependentSourceIds;
newDependentSourceIds.reserve(dependentSourceIds.size() + 1024);
auto newIds = fetchDependentSourceIdsStatement
.template values<FilePathId>(1024, sourcePathId.filePathId);
std::set_union(dependentSourceIds.begin(),
dependentSourceIds.end(),
newIds.begin(),
newIds.end(),
std::back_inserter(newDependentSourceIds));
dependentSourceIds = std::move(newDependentSourceIds);
}
transaction.commit();
return dependentSourceIds;
} catch (const Sqlite::StatementIsBusy &) {
return fetchDependentSourceIds(sourcePathIds);
}
}
void fillTemporarySymbolsTable(const SymbolEntries &symbolEntries)
{
WriteStatement &statement = insertSymbolsToNewSymbolsStatement;
@@ -278,25 +191,6 @@ public:
database};
WriteStatement deleteNewSymbolsTableStatement{"DELETE FROM newSymbols", database};
WriteStatement deleteNewLocationsTableStatement{"DELETE FROM newLocations", database};
WriteStatement inserOrUpdateIndexingTimesStampStatement{
"INSERT INTO fileStatuses(sourceId, indexingTimeStamp) VALUES (?001, ?002) ON "
"CONFLICT(sourceId) DO UPDATE SET indexingTimeStamp = ?002",
database};
mutable ReadStatement fetchIncludedIndexingTimeStampsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"dependencySourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.sourceId == collectedDependencies.sourceId) SELECT DISTINCT sourceId, "
"indexingTimeStamp FROM collectedDependencies NATURAL JOIN fileStatuses ORDER BY sourceId",
database};
mutable ReadStatement fetchIndexingTimeStampsStatement{
"SELECT sourceId, indexingTimeStamp FROM fileStatuses", database};
mutable ReadStatement fetchDependentSourceIdsStatement{
"WITH RECURSIVE collectedDependencies(sourceId) AS (VALUES(?) UNION SELECT "
"sourceDependencies.sourceId FROM sourceDependencies, collectedDependencies WHERE "
"sourceDependencies.dependencySourceId == collectedDependencies.sourceId) SELECT sourceId "
"FROM collectedDependencies WHERE sourceId NOT IN (SELECT dependencySourceId FROM "
"sourceDependencies) ORDER BY sourceId",
database};
};
} // namespace ClangBackEnd

View File

@@ -48,11 +48,6 @@ public:
virtual void addSymbolsAndSourceLocations(const SymbolEntries &symbolEntries,
const SourceLocationEntries &sourceLocations)
= 0;
virtual void insertOrUpdateIndexingTimeStamps(const FilePathIds &filePathIds, TimeStamp indexingTimeStamp) = 0;
virtual void insertOrUpdateIndexingTimeStamps(const FileStatuses &fileStatuses) = 0;
virtual SourceTimeStamps fetchIndexingTimeStamps() const = 0;
virtual SourceTimeStamps fetchIncludedIndexingTimeStamps(FilePathId sourcePathId) const = 0;
virtual FilePathIds fetchDependentSourceIds(const FilePathIds &sourcePathIds) const = 0;
protected:
~SymbolStorageInterface() = default;

View File

@@ -28,8 +28,11 @@
#include "mockfilepathcaching.h"
#include "mocksqlitedatabase.h"
#include <sqlitedatabase.h>
#include <builddependenciesstorage.h>
#include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitewritestatement.h>
#include <utils/optional.h>
@@ -70,7 +73,12 @@ protected:
MockSqliteWriteStatement &updatePchCreationTimeStampStatement = storage.updatePchCreationTimeStampStatement;
MockSqliteWriteStatement &deleteAllProjectPartsFilesWithProjectPartNameStatement
= storage.deleteAllProjectPartsFilesWithProjectPartNameStatement;
MockSqliteReadStatement &fetchProjectPartsFilesStatement = storage.fetchPchSourcesStatement;
MockSqliteReadStatement &fetchPchSourcesStatement = storage.fetchPchSourcesStatement;
MockSqliteReadStatement &fetchSourcesStatement = storage.fetchSourcesStatement;
MockSqliteWriteStatement &inserOrUpdateIndexingTimesStampStatement = storage.inserOrUpdateIndexingTimesStampStatement;
MockSqliteReadStatement &fetchIndexingTimeStampsStatement = storage.fetchIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchIncludedIndexingTimeStampsStatement = storage.fetchIncludedIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchDependentSourceIdsStatement = storage.fetchDependentSourceIdsStatement;
};
TEST_F(BuildDependenciesStorage, ConvertStringsToJson)
@@ -233,13 +241,163 @@ TEST_F(BuildDependenciesStorage, FetchUsedMacros)
ASSERT_THAT(usedMacros, result);
}
TEST_F(BuildDependenciesStorage, FetchSources)
TEST_F(BuildDependenciesStorage, FetchPchSources)
{
ClangBackEnd::FilePathIds result{3, 5, 7};
EXPECT_CALL(fetchProjectPartsFilesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result));
EXPECT_CALL(fetchPchSourcesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result));
auto sources = storage.fetchPchSources(22);
ASSERT_THAT(sources, result);
}
TEST_F(BuildDependenciesStorage, FetchSources)
{
ClangBackEnd::FilePathIds result{3, 5, 7};
EXPECT_CALL(fetchSourcesStatement, valuesReturnFilePathIds(_, 22)).WillOnce(Return(result));
auto sources = storage.fetchSources(22);
ASSERT_THAT(sources, result);
}
TEST_F(BuildDependenciesStorage, FetchIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024));
EXPECT_CALL(mockDatabase, commit());
storage.fetchIndexingTimeStamps();
}
TEST_F(BuildDependenciesStorage, InsertIndexingTimeStamp)
{
ClangBackEnd::FileStatuses fileStatuses{{1, 0, 34}, {2, 0, 37}};
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(37)));
storage.insertOrUpdateIndexingTimeStamps(fileStatuses);
}
TEST_F(BuildDependenciesStorage, InsertIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(34)));
EXPECT_CALL(mockDatabase, commit());
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
}
TEST_F(BuildDependenciesStorage, FetchIncludedIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchIncludedIndexingTimeStamps(1);
}
TEST_F(BuildDependenciesStorage, FetchDependentSourceIdsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(7)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchDependentSourceIds({3, 2, 7});
}
class BuildDependenciesStorageSlow : public testing::Test
{
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::BuildDependenciesStorage<> storage{database};
};
TEST_F(BuildDependenciesStorageSlow, InsertIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 34}));
}
TEST_F(BuildDependenciesStorageSlow, UpdateIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
storage.insertOrUpdateIndexingTimeStamps({1}, 37);
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 37}, SourceTimeStamp{2, 34}));
}
TEST_F(BuildDependenciesStorageSlow, InsertIndexingTimeStamp)
{
storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 37}});
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
}
TEST_F(BuildDependenciesStorageSlow, UpdateIndexingTimeStamp)
{
storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 34}});
storage.insertOrUpdateIndexingTimeStamps({{2, 0, 37}});
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
}
TEST_F(BuildDependenciesStorageSlow, FetchIncludedIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34);
storage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}});
auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1);
ASSERT_THAT(timeStamps,
ElementsAre(SourceTimeStamp{1, 34},
SourceTimeStamp{2, 34},
SourceTimeStamp{3, 34},
SourceTimeStamp{4, 34}));
}
TEST_F(BuildDependenciesStorageSlow, FetchDependentSourceIds)
{
storage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}});
auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7});
ASSERT_THAT(sourceIds, ElementsAre(FilePathId{1}, FilePathId{4}, FilePathId{7}));
}
} // namespace

View File

@@ -48,8 +48,11 @@ using ClangBackEnd::FilePath;
using ClangBackEnd::FilePathId;
using ClangBackEnd::FilePathIds;
using ClangBackEnd::FilePathView;
using ClangBackEnd::IdPaths;
using ClangBackEnd::ProjectChunkId;
using ClangBackEnd::ProjectPartId;
using ClangBackEnd::ProjectPartIds;
using ClangBackEnd::SourceType;
using ClangBackEnd::WatcherEntries;
using ClangBackEnd::WatcherEntry;
@@ -111,9 +114,9 @@ protected:
NiceMock<MockFileSystem> mockFileSystem;
Watcher watcher{mockFilePathCache, mockFileSystem, &notifier};
NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher();
ProjectPartId id1{2};
ProjectPartId id2{3};
ProjectPartId id3{4};
ProjectChunkId id1{2, SourceType::ProjectInclude};
ProjectChunkId id2{2, SourceType::Source};
ProjectChunkId id3{4, SourceType::SystemInclude};
FilePathView path1{"/path/path1"};
FilePathView path2{"/path/path2"};
FilePathView path3{"/path2/path1"};
@@ -128,14 +131,15 @@ protected:
Utils::PathString directoryPathString2 = directoryPath2;
FilePathIds pathIds = {1, 2, 3, 4, 5};
ClangBackEnd::DirectoryPathIds directoryPaths = {1, 2, 3};
ClangBackEnd::ProjectPartIds ids{id1, id2, id3};
WatcherEntry watcherEntry1{ids[0], directoryPaths[0], pathIds[0]};
WatcherEntry watcherEntry2{ids[1], directoryPaths[0], pathIds[0]};
WatcherEntry watcherEntry3{ids[0], directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry4{ids[1], directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry5{ids[2], directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry6{ids[0], directoryPaths[1], pathIds[2]};
WatcherEntry watcherEntry7{ids[1], directoryPaths[1], pathIds[3]};
ClangBackEnd::ProjectChunkIds ids{id1, id2, id3};
WatcherEntry watcherEntry1{id1, directoryPaths[0], pathIds[0]};
WatcherEntry watcherEntry2{id2, directoryPaths[0], pathIds[0]};
WatcherEntry watcherEntry3{id1, directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry4{id2, directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry5{id3, directoryPaths[0], pathIds[1]};
WatcherEntry watcherEntry6{id1, directoryPaths[1], pathIds[2]};
WatcherEntry watcherEntry7{id2, directoryPaths[1], pathIds[3]};
WatcherEntry watcherEntry8{id3, directoryPaths[1], pathIds[3]};
};
TEST_F(ClangPathWatcher, AddIdPaths)
@@ -260,12 +264,13 @@ TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths)
TEST_F(ClangPathWatcher, RemoveEntriesWithId)
{
watcher.updateIdPaths(
{{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[1]}}});
watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}},
{id2, {pathIds[0], pathIds[1]}},
{id3, {pathIds[1], pathIds[3]}}});
watcher.removeIds({id1});
watcher.removeIds({2});
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry2, watcherEntry4, watcherEntry5));
ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry5, watcherEntry8));
}
TEST_F(ClangPathWatcher, RemoveNoPathsForEmptyIds)
@@ -284,28 +289,28 @@ TEST_F(ClangPathWatcher, RemoveNoPathsForOneId)
EXPECT_CALL(mockQFileSytemWatcher, removePaths(_))
.Times(0);
watcher.removeIds({id3});
watcher.removeIds({id3.id});
}
TEST_F(ClangPathWatcher, RemovePathForOneId)
{
watcher.updateIdPaths(
{{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
{{id1, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0], pathIds[1], pathIds[3]}}});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath2)));
watcher.removeIds({id2});
watcher.removeIds({id3.id});
}
TEST_F(ClangPathWatcher, RemoveNoPathSecondTime)
{
watcher.updateIdPaths(
{{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
watcher.removeIds({id2});
watcher.removeIds({id2.id});
EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)).Times(0);
watcher.removeIds({id2});
watcher.removeIds({id2.id});
}
TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
@@ -315,7 +320,7 @@ TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId)
EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath, directoryPath2)));
watcher.removeIds({id1, id2, id3});
watcher.removeIds({id1.id, id2.id, id3.id});
}
TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
@@ -325,7 +330,7 @@ TEST_F(ClangPathWatcher, RemoveOnePathForTwoId)
EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath)));
watcher.removeIds({id1, id2});
watcher.removeIds({id1.id, id2.id});
}
TEST_F(ClangPathWatcher, NotAnymoreWatchedEntriesWithId)
@@ -349,13 +354,14 @@ TEST_F(ClangPathWatcher, RemoveUnusedEntries)
TEST_F(ClangPathWatcher, TwoNotifyFileChanges)
{
watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}},
{id2, {pathIds[0], pathIds[1], pathIds[3]}},
{id2, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}},
{id3, {pathIds[4]}}});
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[1]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2));
EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id1, id2)));
EXPECT_CALL(notifier,
pathsWithIdsChanged(ElementsAre(IdPaths{id1, {1, 2}}, IdPaths{id2, {1, 2, 4}})));
mockQFileSytemWatcher.directoryChanged(directoryPath);
mockQFileSytemWatcher.directoryChanged(directoryPath2);

View File

@@ -52,8 +52,8 @@ public:
CommandLineBuilder() { cppProjectInfo.language = Utils::Language::Cxx; }
public:
ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}};
ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}};
ClangBackEnd::PchTask emptyProjectInfo{0, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}};
ClangBackEnd::PchTask cppProjectInfo{1, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}};
};
template <>

View File

@@ -359,9 +359,8 @@ std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry)
std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry)
{
out << "("
<< entry.id << ", "
<< entry.filePathId
out << "(" << entry.directoryPathId << ", " << entry.filePathId << ", " << entry.id << ", "
<< entry.lastModified << ", "
<< ")";
return out;
@@ -1290,6 +1289,17 @@ std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths)
{
return out << "(" << pchPaths.projectPchPath << ", " << pchPaths.systemPchPath << ")";
}
std::ostream &operator<<(std::ostream &out, const ProjectChunkId &chunk)
{
return out << "(" << chunk.id << ", " << typeToString(chunk.sourceType) << ")";
}
std::ostream &operator<<(std::ostream &out, const DirectoryPathId &id)
{
return out << id.directoryPathId;
}
void PrintTo(const FilePath &filePath, ::std::ostream *os)
{
*os << filePath;

View File

@@ -200,6 +200,8 @@ struct ArgumentsEntry;
class ProjectPartContainer;
class ProjectPartId;
class PchPaths;
class ProjectChunkId;
class DirectoryPathId;
std::ostream &operator<<(std::ostream &out, const SourceLocationEntry &entry);
std::ostream &operator<<(std::ostream &out, const IdPaths &idPaths);
@@ -293,6 +295,8 @@ std::ostream &operator<<(std::ostream &out, const ArgumentsEntry &entry);
std::ostream &operator<<(std::ostream &out, const ProjectPartContainer &container);
std::ostream &operator<<(std::ostream &out, const ProjectPartId &projectPathId);
std::ostream &operator<<(std::ostream &out, const PchPaths &pchPaths);
std::ostream &operator<<(std::ostream &out, const ProjectChunkId &chunk);
std::ostream &operator<<(std::ostream &out, const DirectoryPathId &id);
void PrintTo(const FilePath &filePath, ::std::ostream *os);
void PrintTo(const FilePathView &filePathView, ::std::ostream *os);

View File

@@ -53,5 +53,16 @@ public:
void(long long pchCreationTimeStamp, ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(fetchPchSources,
ClangBackEnd::FilePathIds(ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(fetchSources,
ClangBackEnd::FilePathIds(ClangBackEnd::ProjectPartId projectPartId));
MOCK_METHOD2(insertOrUpdateIndexingTimeStamps,
void(const ClangBackEnd::FilePathIds &filePathIds,
ClangBackEnd::TimeStamp indexingTimeStamp));
MOCK_METHOD1(insertOrUpdateIndexingTimeStamps, void(const ClangBackEnd::FileStatuses &));
MOCK_CONST_METHOD0(fetchIndexingTimeStamps, ClangBackEnd::SourceTimeStamps());
MOCK_CONST_METHOD1(fetchIncludedIndexingTimeStamps,
ClangBackEnd::SourceTimeStamps(ClangBackEnd::FilePathId sourcePathId));
MOCK_CONST_METHOD1(fetchDependentSourceIds,
ClangBackEnd::FilePathIds(const ClangBackEnd::FilePathIds &sourcePathIds));
};

View File

@@ -32,7 +32,7 @@
class MockClangPathWatcherNotifier : public ClangBackEnd::ClangPathWatcherNotifier
{
public:
MOCK_METHOD1(pathsWithIdsChanged, void(const ClangBackEnd::ProjectPartIds &ids));
MOCK_METHOD1(pathsWithIdsChanged, void(const std::vector<ClangBackEnd::IdPaths> &idPaths));
MOCK_METHOD1(pathsChanged,
void (const ClangBackEnd::FilePathIds &filePathIds));

View File

@@ -37,11 +37,4 @@ public:
MOCK_METHOD2(addSymbolsAndSourceLocations,
void(const ClangBackEnd::SymbolEntries &symbolEentries,
const ClangBackEnd::SourceLocationEntries &sourceLocations));
MOCK_METHOD2(insertOrUpdateIndexingTimeStamps,
void(const FilePathIds &filePathIds, ClangBackEnd::TimeStamp indexingTimeStamp));
MOCK_METHOD1(insertOrUpdateIndexingTimeStamps, void(const ClangBackEnd::FileStatuses &));
MOCK_CONST_METHOD0(fetchIndexingTimeStamps, ClangBackEnd::SourceTimeStamps());
MOCK_CONST_METHOD1(fetchIncludedIndexingTimeStamps,
ClangBackEnd::SourceTimeStamps(ClangBackEnd::FilePathId sourcePathId));
MOCK_CONST_METHOD1(fetchDependentSourceIds, FilePathIds(const FilePathIds &sourcePathIds));
};

View File

@@ -34,12 +34,13 @@
#include "mockpchmanagerclient.h"
#include "testenvironment.h"
#include <refactoringdatabaseinitializer.h>
#include <filepathcaching.h>
#include <generatedfiles.h>
#include <pchcreator.h>
#include <precompiledheadersupdatedmessage.h>
#include <progressmessage.h>
#include <refactoringdatabaseinitializer.h>
#include <updateprojectpartsmessage.h>
#include <sqlitedatabase.h>
@@ -55,12 +56,14 @@ using ClangBackEnd::GeneratedFiles;
using ClangBackEnd::IdPaths;
using ClangBackEnd::IncludeSearchPathType;
using ClangBackEnd::PchTask;
using ClangBackEnd::PrecompiledHeadersUpdatedMessage;
using ClangBackEnd::ProjectChunkId;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartPch;
using ClangBackEnd::SourceEntries;
using ClangBackEnd::SourceEntry;
using ClangBackEnd::SourceType;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::ProjectPartContainer;
using Utils::PathString;
using Utils::SmallString;
@@ -91,6 +94,13 @@ protected:
return creator.filePathCache().filePathId(path);
}
FilePathIds sorted(FilePathIds &&filePathIds)
{
std::sort(filePathIds.begin(), filePathIds.end());
return std::move(filePathIds);
}
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
@@ -111,14 +121,19 @@ protected:
mockBuildDependenciesStorage};
PchTask pchTask1{
1,
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
id(generatedFilePath),
id(main2Path)},
sorted({id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")}),
sorted({id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system2.h"),
id(generatedFilePath)}),
sorted({id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
id(generatedFilePath)}),
sorted({id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(generatedFilePath)}),
sorted({id(main2Path), id(generatedFilePath)}),
{},
{},
{},
@@ -213,15 +228,34 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterSucess)
{
creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, 1),
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp")))))));
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system2.h")))))));
creator.doInMainThreadAfterFinished();
}
@@ -232,15 +266,34 @@ TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterFail)
pchTask1.projectIncludeSearchPaths = {};
creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, 1),
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp")))))));
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system2.h")))))));
creator.doInMainThreadAfterFinished();
}
@@ -282,15 +335,40 @@ TEST_F(PchCreatorVerySlowTest, ProjectPartPchCleared)
ASSERT_FALSE(creator.projectPartPch().isValid());
}
TEST_F(PchCreatorVerySlowTest, SourcesCleared)
TEST_F(PchCreatorVerySlowTest, WatchedSystemIncludesCleared)
{
creator.generatePch(std::move(pchTask1));
creator.clear();
ASSERT_THAT(creator.sources(), IsEmpty());
ASSERT_THAT(creator.watchedSystemIncludes(), IsEmpty());
}
TEST_F(PchCreatorVerySlowTest, WatchedProjectIncludesCleared)
{
creator.generatePch(std::move(pchTask1));
creator.clear();
ASSERT_THAT(creator.watchedProjectIncludes(), IsEmpty());
}
TEST_F(PchCreatorVerySlowTest, WatchedUserIncludesCleared)
{
creator.generatePch(std::move(pchTask1));
creator.clear();
ASSERT_THAT(creator.watchedUserIncludes(), IsEmpty());
}
TEST_F(PchCreatorVerySlowTest, WatchedSourcesCleared)
{
creator.generatePch(std::move(pchTask1));
creator.clear();
ASSERT_THAT(creator.watchedSources(), IsEmpty());
}
TEST_F(PchCreatorVerySlowTest, ClangToolCleared)
{
creator.generatePch(std::move(pchTask1));
@@ -306,6 +384,9 @@ TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesFaultyPchForPchTask
0,
{id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")},
{},
{},
{},
{},
{{"DEFINE", "1", 1}},
{},
{},
@@ -336,20 +417,37 @@ TEST_F(PchCreatorSlowTest, NoIncludesInTheMainThreadCalls)
{
pchTask1.includes = {};
creator.generatePch(std::move(pchTask1));
EXPECT_CALL(mockPchManagerClient,
precompiledHeadersUpdated(
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
ElementsAre(Eq(creator.projectPartPch().projectPartId)))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::Source}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(id(main2Path)))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, 1),
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::UserInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp")))))));
id(TESTDATA_DIR "/builddependencycollector/project/header1.h"),
id(TESTDATA_DIR "/builddependencycollector/project/header2.h")))))));
EXPECT_CALL(
mockClangPathWatcher,
updateIdPaths(ElementsAre(
AllOf(Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::ProjectInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")))))));
EXPECT_CALL(mockClangPathWatcher,
updateIdPaths(ElementsAre(AllOf(
Field(&ClangBackEnd::IdPaths::id, ProjectChunkId{1, SourceType::SystemInclude}),
Field(&ClangBackEnd::IdPaths::filePathIds,
UnorderedElementsAre(
id(TESTDATA_DIR "/builddependencycollector/system/system1.h"),
id(TESTDATA_DIR "/builddependencycollector/system/system2.h")))))));
EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(Gt(0), Eq(1)));
creator.doInMainThreadAfterFinished();

View File

@@ -25,11 +25,12 @@
#include "googletest.h"
#include "mockbuilddependenciesstorage.h"
#include "mockclangpathwatcher.h"
#include "mockgeneratedfiles.h"
#include "mockpchmanagerclient.h"
#include "mockpchtaskgenerator.h"
#include "mockprojectpartsmanager.h"
#include "mockgeneratedfiles.h"
#include <filepathcaching.h>
#include <pchmanagerserver.h>
@@ -42,12 +43,13 @@
#include <updateprojectpartsmessage.h>
namespace {
using Utils::PathString;
using Utils::SmallString;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::FileContainers;
using ClangBackEnd::FilePathId;
using ClangBackEnd::ProjectPartContainer;
using ClangBackEnd::ProjectPartContainers;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::FileContainers;
using Utils::PathString;
using Utils::SmallString;
using UpToDataProjectParts = ClangBackEnd::ProjectPartsManagerInterface::UpToDataProjectParts;
class PchManagerServer : public ::testing::Test
@@ -71,21 +73,27 @@ protected:
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
NiceMock<MockProjectPartsManager> mockProjectPartsManager;
NiceMock<MockGeneratedFiles> mockGeneratedFiles;
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
ClangBackEnd::FilePathCaching filePathCache{database};
ClangBackEnd::PchManagerServer server{mockClangPathWatcher,
mockPchTaskGenerator,
mockProjectPartsManager,
mockGeneratedFiles};
mockGeneratedFiles,
mockBuildDependenciesStorage};
NiceMock<MockPchManagerClient> mockPchManagerClient;
ClangBackEnd::ProjectPartId projectPartId1{1};
ClangBackEnd::ProjectPartId projectPartId2{2};
ClangBackEnd::ProjectPartId projectPartId3{3};
ClangBackEnd::ProjectPartId projectPartId4{4};
ClangBackEnd::ProjectPartId projectPartId5{5};
ClangBackEnd::ProjectPartId projectPartId6{6};
PathString main1Path = TESTDATA_DIR "/BuildDependencyCollector_main3.cpp";
PathString main2Path = TESTDATA_DIR "/BuildDependencyCollector_main2.cpp";
PathString header1Path = TESTDATA_DIR "/BuildDependencyCollector_header1.h";
PathString header2Path = TESTDATA_DIR "/BuildDependencyCollector_header2.h";
ClangBackEnd::IdPaths idPath{projectPartId1, {1, 2}};
ClangBackEnd::IdPaths idPath{{projectPartId1, ClangBackEnd::SourceType::Source}, {1, 2}};
ProjectPartContainer projectPart1{
projectPartId1,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
@@ -108,6 +116,50 @@ protected:
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPart3{
projectPartId3,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header1Path)},
{id(main1Path)},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPart4{
projectPartId4,
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header2Path)},
{id(main2Path)},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPart5{
projectPartId5,
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header1Path)},
{id(main1Path)},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
ProjectPartContainer projectPart6{
projectPartId6,
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1", 1}},
{{"/includes", 1, ClangBackEnd::IncludeSearchPathType::BuiltIn}},
{{"/project/includes", 1, ClangBackEnd::IncludeSearchPathType::User}},
{id(header2Path)},
{id(main2Path)},
Utils::Language::C,
Utils::LanguageVersion::C11,
Utils::LanguageExtension::All};
std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2};
std::vector<ProjectPartContainer> projectParts1{projectPart1};
std::vector<ProjectPartContainer> projectParts2{projectPart2};
@@ -169,19 +221,68 @@ TEST_F(PchManagerServer, SetPathWatcherNotifier)
ClangBackEnd::PchManagerServer server{mockClangPathWatcher,
mockPchTaskGenerator,
mockProjectPartsManager,
mockGeneratedFiles};
mockGeneratedFiles,
mockBuildDependenciesStorage};
}
TEST_F(PchManagerServer, UpdateProjectPartQueueByPathIds)
{
server.updateProjectParts(
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{
{projectPart1, projectPart2, projectPart3, projectPart4, projectPart5, projectPart6},
{"toolChainArgument"}});
EXPECT_CALL(mockProjectPartsManager, projects(ElementsAre(projectPart1.projectPartId)))
.WillOnce(Return(std::vector<ClangBackEnd::ProjectPartContainer>{{projectPart1}}));
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(ElementsAre(projectPart1), ElementsAre("toolChainArgument")));
EXPECT_CALL(mockProjectPartsManager,
projects(ElementsAre(projectPart1.projectPartId,
projectPart2.projectPartId,
projectPart4.projectPartId,
projectPart5.projectPartId)))
.WillOnce(Return(std::vector<ClangBackEnd::ProjectPartContainer>{
{projectPart1, projectPart2, projectPart4, projectPart5}}));
EXPECT_CALL(mockPchTaskGenerator,
addProjectParts(ElementsAre(projectPart1, projectPart2, projectPart4, projectPart5),
ElementsAre("toolChainArgument")));
server.pathsWithIdsChanged({projectPartId1});
server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::TopProjectInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::TopSystemInclude}, {}},
{{projectPartId3, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId4, ClangBackEnd::SourceType::ProjectInclude}, {}},
{{projectPartId5, ClangBackEnd::SourceType::SystemInclude}, {}},
{{projectPartId6, ClangBackEnd::SourceType::Source}, {}}});
}
TEST_F(PchManagerServer, DontUpdateProjectPartQueueByPathIdsIfItUserFile)
{
server.updateProjectParts(ClangBackEnd::UpdateProjectPartsMessage{{projectPart1, projectPart2},
{"toolChainArgument"}});
EXPECT_CALL(mockProjectPartsManager, projects(_)).Times(0);
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::Source}, {}}});
}
TEST_F(PchManagerServer, ShortcutPrecompiledHeaderGenerationForUserIncludesAndSources)
{
EXPECT_CALL(mockPchManagerClient,
precompiledHeadersUpdated(
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartIds,
UnorderedElementsAre(projectPartId3, projectPartId6))));
server.pathsWithIdsChanged({{{projectPartId1, ClangBackEnd::SourceType::TopProjectInclude}, {}},
{{projectPartId2, ClangBackEnd::SourceType::TopSystemInclude}, {}},
{{projectPartId3, ClangBackEnd::SourceType::UserInclude}, {}},
{{projectPartId4, ClangBackEnd::SourceType::ProjectInclude}, {}},
{{projectPartId5, ClangBackEnd::SourceType::SystemInclude}, {}},
{{projectPartId6, ClangBackEnd::SourceType::Source}, {}}});
}
TEST_F(PchManagerServer, ResetTimeStampForChangedFilesInDatabase)
{
EXPECT_CALL(mockBuildDependenciesStorage,
insertOrUpdateIndexingTimeStamps(ElementsAre(FilePathId{1}, FilePathId{3}, FilePathId{5}),
TypedEq<ClangBackEnd::TimeStamp>(0)));
server.pathsChanged({1, 3, 5});
}
TEST_F(PchManagerServer, SetPchCreationProgress)
@@ -214,7 +315,7 @@ TEST_F(PchManagerServer, RemoveToolChainsArguments)
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
server.removeProjectParts(removeProjectPartsMessage.clone());
server.pathsWithIdsChanged({projectPart1.projectPartId});
server.pathsWithIdsChanged({{{projectPart1.projectPartId, ClangBackEnd::SourceType::Source}, {}}});
}
TEST_F(PchManagerServer, DontGeneratePchIfGeneratedFilesAreNotValid)

View File

@@ -84,7 +84,8 @@ protected:
{2, SourceType::UserInclude, 1},
{3, SourceType::TopProjectInclude, 1},
{4, SourceType::SystemInclude, 1},
{5, SourceType::TopSystemInclude, 1}};
{5, SourceType::TopSystemInclude, 1},
{6, SourceType::Source, 1}};
UsedMacros usedMacros{{"LIANG", 0},{"YI", 1}, {"ER", 2}, {"SAN", 3}, {"SE", 4}, {"WU", 5}};
BuildDependency buildDependency{firstSources, usedMacros, {}, {}, {}};
};
@@ -100,7 +101,10 @@ TEST_F(PchTaskGenerator, AddProjectParts)
Field(&PchTaskSet::system,
AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
Field(&PchTask::includes, ElementsAre(5)),
Field(&PchTask::sources, IsEmpty()),
Field(&PchTask::watchedSystemIncludes, IsEmpty()),
Field(&PchTask::watchedProjectIncludes, IsEmpty()),
Field(&PchTask::watchedUserIncludes, IsEmpty()),
Field(&PchTask::watchedUserSources, IsEmpty()),
Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"SE", "4", 4}, CompilerMacro{"WU", "5", 5})),
Field(&PchTask::systemIncludeSearchPaths,
@@ -117,7 +121,10 @@ TEST_F(PchTaskGenerator, AddProjectParts)
&PchTaskSet::project,
AllOf(Field(&PchTask::projectPartIds, ElementsAre(ProjectPartId{1})),
Field(&PchTask::includes, ElementsAre(3)),
Field(&PchTask::sources, ElementsAre(1, 3, 4, 5)),
Field(&PchTask::watchedSystemIncludes, ElementsAre(4, 5)),
Field(&PchTask::watchedProjectIncludes, ElementsAre(1, 3)),
Field(&PchTask::watchedUserIncludes, ElementsAre(2)),
Field(&PchTask::watchedUserSources, ElementsAre(6)),
Field(&PchTask::compilerMacros,
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})),
Field(&PchTask::systemIncludeSearchPaths,

View File

@@ -67,6 +67,9 @@ protected:
PchTask systemTask1{1,
{1, 2},
{1, 2},
{2, 3},
{3, 4},
{6, 7},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}},
{"--yi"},
@@ -75,6 +78,9 @@ protected:
PchTask systemTask2{2,
{1, 2},
{1, 2},
{2, 3},
{3, 4},
{6, 7},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}},
{"--yi"},
@@ -83,6 +89,9 @@ protected:
PchTask systemTask2b{2,
{3, 4},
{3, 4},
{5, 6},
{4, 7},
{8, 9},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}},
{"--yi"},
@@ -91,6 +100,9 @@ protected:
PchTask systemTask3{3,
{1, 2},
{1, 2},
{2, 3},
{3, 4},
{6, 7},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}},
{"--yi"},
@@ -99,6 +111,9 @@ protected:
PchTask projectTask1{1,
{11, 12},
{11, 12},
{12, 13},
{13, 14},
{16, 17},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}},
{"--yi"},
@@ -107,6 +122,9 @@ protected:
PchTask projectTask2{2,
{11, 12},
{11, 12},
{12, 13},
{13, 14},
{16, 17},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}},
{"--yi"},
@@ -115,6 +133,9 @@ protected:
PchTask projectTask2b{2,
{21, 22},
{11, 12},
{22, 23},
{23, 24},
{26, 27},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}},
{"--yi"},
@@ -123,6 +144,9 @@ protected:
PchTask projectTask3{3,
{21, 22},
{21, 22},
{22, 23},
{23, 24},
{26, 27},
{{"SE", "4", 4}, {"WU", "5", 5}},
{{"ER", 2}, {"SAN", 3}},
{"--yi"},
@@ -131,6 +155,9 @@ protected:
PchTask systemTask4{{1, 3},
{1, 2},
{1, 2},
{2, 3},
{3, 4},
{5, 8},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{{"LIANG", 0}, {"YI", 1}},
{"--yi"},

View File

@@ -54,7 +54,10 @@ protected:
ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue};
PchTask systemTask1{1,
{1, 2},
{1, 2, 3},
{},
{},
{},
{},
{{"YI", "1", 1}, {"SAN", "3", 3}},
{"YI", "LIANG"},
{"--yi"},
@@ -66,6 +69,9 @@ protected:
PchTask projectTask1{1,
{11, 12},
{11, 12},
{21, 22},
{31, 32},
{41, 42},
{{"SE", "4", 4}, {"WU", "5", 5}},
{"ER", "SAN"},
{"--yi"},
@@ -75,7 +81,10 @@ protected:
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask systemTask2{2,
{11, 12},
{11, 12, 13},
{},
{},
{},
{},
{{"SE", "4", 4}, {"WU", "5", 5}},
{"ER", "SAN"},
{"--yi"},
@@ -87,6 +96,9 @@ protected:
PchTask projectTask2{2,
{11, 12},
{11, 12},
{21, 22},
{31, 32},
{41, 42},
{{"SE", "4", 4}, {"WU", "5", 5}},
{"ER", "SAN"},
{"--yi"},
@@ -97,7 +109,10 @@ protected:
{"/to/path2", 2, IncludeSearchPathType::User}}};
PchTask systemTask3{3,
{1, 2},
{1, 2},
{},
{},
{},
{},
{{"YI", "2", 1}, {"SAN", "3", 3}},
{"YI", "LIANG"},
{"--yi"},
@@ -268,18 +283,25 @@ TEST_F(PchTasksMerger, DontMergeIncludes)
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2));
}
TEST_F(PchTasksMerger, MergeAllIncludes)
TEST_F(PchTasksMerger, DontMergeWatchedSystemSources)
{
Merger::mergePchTasks(systemTask1, systemTask2);
ASSERT_THAT(systemTask1.sources, ElementsAre(1, 2, 3, 11, 12, 13));
ASSERT_THAT(systemTask1.watchedSystemIncludes, IsEmpty());
}
TEST_F(PchTasksMerger, DontAllMergeIncludes)
TEST_F(PchTasksMerger, DontMergeWatchedProjectSources)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.sources, ElementsAre(1, 2, 3));
ASSERT_THAT(systemTask1.watchedProjectIncludes, IsEmpty());
}
TEST_F(PchTasksMerger, DontMergeWatchedUserSources)
{
Merger::mergePchTasks(systemTask1, systemTask3);
ASSERT_THAT(systemTask1.watchedUserSources, IsEmpty());
}
TEST_F(PchTasksMerger, MergeProjectIds)

View File

@@ -463,7 +463,6 @@ protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
Storage storage{database};
ClangBackEnd::SymbolStorage<> symbolStorage{database};
ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
};
@@ -505,13 +504,13 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectParts)
TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps)
{
symbolStorage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 34);
buildDependenciesStorage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 34);
buildDependenciesStorage.insertOrUpdateSourceDependencies(
{{3, 1}, {4, 1}, {1, 2}, {7, 5}, {8, 6}, {6, 5}, {9, 10}});
storage.resetIndexingTimeStamps({projectPart1, projectPart2});
ASSERT_THAT(symbolStorage.fetchIndexingTimeStamps(),
ASSERT_THAT(buildDependenciesStorage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 0},
SourceTimeStamp{2, 0},
SourceTimeStamp{3, 0},

View File

@@ -116,11 +116,11 @@ protected:
.WillByDefault(Return(artefact));
ON_CALL(mockBuildDependenciesStorage, fetchLowestLastModifiedTime(A<FilePathId>())).WillByDefault(Return(-1));
ON_CALL(mockCollector, collectSymbols()).WillByDefault(Return(true));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(sourceFileIds))
.WillByDefault(Return(sourceFileIds));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0])))
ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(ElementsAre(sourceFileIds[0])))
.WillByDefault(Return(FilePathIds{sourceFileIds[0]}));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(ElementsAre(main1PathId)))
ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(ElementsAre(main1PathId)))
.WillByDefault(Return(FilePathIds{main1PathId}));
mockCollector.setIsUsed(false);
@@ -879,16 +879,16 @@ TEST_F(SymbolIndexer, UpdateProjectPartsFetchIncludedIndexingTimeStamps)
Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::None};
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId)))
EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId)))
.WillOnce(Return(dependentSourceTimeStamps1));
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps1));
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId)))
EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId)))
.WillOnce(Return(dependentSourceTimeStamps2));
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps2));
EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses1));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1));
EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses2));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
indexer.updateProjectParts({projectPart});
}
@@ -917,642 +917,6 @@ TEST_F(SymbolIndexer, DependentSourceAreUpToDate)
indexer.updateProjectParts({projectPart1});
}
TEST_F(SymbolIndexer, SourcesAreWatched)
{
using ClangBackEnd::IdPaths;
InSequence s;
FilePathIds sourcePathIds{4, 6, 8};
EXPECT_CALL(mockBuildDependenciesStorage, fetchPchSources(projectPart1.projectPartId))
.WillOnce(Return(sourcePathIds));
EXPECT_CALL(mockPathWatcher,
updateIdPaths(ElementsAre(AllOf(Field(&IdPaths::id, projectPart1.projectPartId),
Field(&IdPaths::filePathIds, sourcePathIds)))));
indexer.updateProjectParts({projectPart1});
}
TEST_F(SymbolIndexer, CallSetNotifier)
{
EXPECT_CALL(mockPathWatcher, setNotifier(_));
ClangBackEnd::SymbolIndexer indexer{indexerQueue,
mockSymbolStorage,
mockBuildDependenciesStorage,
mockPrecompiledHeaderStorage,
mockPathWatcher,
filePathCache,
fileStatusCache,
mockSqliteTransactionBackend,
mockProjectPartsStorage,
mockModifiedTimeChecker,
testEnvironment};
}
TEST_F(SymbolIndexer, PathChangedCallsFetchProjectPartArtefactInStorage)
{
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[1]));
indexer.pathsChanged(sourceFileIds);
}
TEST_F(SymbolIndexer, PathChangedCallsFetchSourcePathIds)
{
InSequence s;
EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(sourceFileIds))
.WillOnce(Return(FilePathIds{2, 6, 5}));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{2}));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{6}));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(FilePathId{5}));
indexer.pathsChanged(sourceFileIds);
}
TEST_F(SymbolIndexer, PathChangedFetchIncludedIndexingTimeStamps)
{
InSequence s;
ProjectPartContainer projectPart{1,
{"-Wno-pragma-once-outside-header"},
{{"BAR", "1", 1}, {"FOO", "1", 2}},
Utils::clone(systemIncludeSearchPaths),
Utils::clone(projectIncludeSearchPaths),
{header1PathId},
{main1PathId, main2PathId},
Utils::Language::Cxx,
Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::None};
EXPECT_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillOnce(Return(FilePathIds{1, 2}));
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(1)))
.WillOnce(Return(dependentSourceTimeStamps1));
EXPECT_CALL(mockSymbolStorage, fetchIncludedIndexingTimeStamps(Eq(2)))
.WillOnce(Return(dependentSourceTimeStamps2));
EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses1));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1));
EXPECT_CALL(mockCollector, fileStatuses()).WillOnce(ReturnRef(fileStatuses2));
EXPECT_CALL(mockSymbolStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2));
indexer.pathsChanged({1, 3});
}
TEST_F(SymbolIndexer, PathChangedFetchesDependentSourceIdsFromStorage)
{
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]));
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[1]));
indexer.pathsChanged(sourceFileIds);
}
TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
{
InSequence s;
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)));
EXPECT_CALL(mockCollector,
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath)
{
InSequence s;
EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin());
EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0]))
.WillOnce(Return(nullArtefact));
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(_)).Times(0);
EXPECT_CALL(mockCollector, setFile(_, _)).Times(0);
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0);
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(_, _)).Times(0);
EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasNoError)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectPch)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/system/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasErrorWithProjectAndSystemPch)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/system/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsProjectAndSystemPchPathsAndHasOnlyError)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{"/project/pch", "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/system/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(false));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations)).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsSystemPchPathsAndHasErrorWithProjectPch)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillOnce(Return(ClangBackEnd::PchPaths{{}, "/system/pch"}));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/system/pch"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, PathsChangedCallsGetsNoPchPathsAndHasErrors)
{
InSequence s;
EXPECT_CALL(mockProjectPartsStorage,
fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillOnce(Return(artefact));
EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)));
EXPECT_CALL(mockCollector,
setFile(sourceFileIds[0],
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
EXPECT_CALL(mockCollector, collectSymbols()).WillOnce(Return(true));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockCollector, collectSymbols()).Times(0);
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
{
ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillByDefault(Return(artefact));
ON_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeaders(Eq(artefact.projectPartId)))
.WillByDefault(Return(pchPaths));
std::vector<SymbolIndexerTask> symbolIndexerTask;
EXPECT_CALL(mockCollector,
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"),
"-Xclang",
"-include-pch",
"-Xclang",
toNativePath("/project/pch"))));
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists)
{
ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq<FilePathId>(sourceFileIds[0])))
.WillByDefault(Return(artefact));
std::vector<SymbolIndexerTask> symbolIndexerTask;
EXPECT_CALL(mockCollector,
setFile(Eq(sourceFileIds[0]),
ElementsAre("clang++",
"-w",
"-DFOO",
"-DNOMINMAX",
"-x",
"c++",
"-std=c++14",
"-nostdinc",
"-nostdinc++",
"-DBAR=1",
"-DFOO=1",
"-isystem",
toNativePath(TESTDATA_DIR "/preincludes"),
"-I",
toNativePath("/project/includes"),
"-I",
toNativePath("/other/project/includes"),
"-isystem",
toNativePath(TESTDATA_DIR),
"-isystem",
toNativePath("/other/includes"),
"-isystem",
toNativePath("/includes"))));
indexer.pathsChanged({sourceFileIds[0]});
}
TEST_F(SymbolIndexer, CompilerMacrosAndIncludeSearchPathsAreNotDifferent)
{
ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(A<ProjectPartId>()))
@@ -1660,7 +1024,8 @@ TEST_F(SymbolIndexer, PathsChangedUpdatesFileStatusCache)
{
auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp");
ON_CALL(mockFileSystem, lastModified(Eq(sourceId))).WillByDefault(Return(65));
ON_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillByDefault(Return(FilePathIds{sourceId}));
ON_CALL(mockBuildDependenciesStorage, fetchDependentSourceIds(_))
.WillByDefault(Return(FilePathIds{sourceId}));
indexer.pathsChanged({sourceId});

View File

@@ -69,10 +69,6 @@ protected:
MockSqliteWriteStatement &insertNewLocationsInLocationsStatement = storage.insertNewLocationsInLocationsStatement;
MockSqliteWriteStatement &deleteNewSymbolsTableStatement = storage.deleteNewSymbolsTableStatement;
MockSqliteWriteStatement &deleteNewLocationsTableStatement = storage.deleteNewLocationsTableStatement;
MockSqliteWriteStatement &inserOrUpdateIndexingTimesStampStatement = storage.inserOrUpdateIndexingTimesStampStatement;
MockSqliteReadStatement &fetchIndexingTimeStampsStatement = storage.fetchIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchIncludedIndexingTimeStampsStatement = storage.fetchIncludedIndexingTimeStampsStatement;
MockSqliteReadStatement &fetchDependentSourceIdsStatement = storage.fetchDependentSourceIdsStatement;
SymbolEntries symbolEntries{{1, {"functionUSR", "function", SymbolKind::Function}},
{2, {"function2USR", "function2", SymbolKind::Function}}};
SourceLocationEntries sourceLocations{{1, 3, {42, 23}, SourceLocationKind::Declaration},
@@ -192,145 +188,4 @@ TEST_F(SymbolStorage, AddTablesInConstructor)
Storage storage{mockDatabase};
}
TEST_F(SymbolStorage, FetchIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIndexingTimeStampsStatement, valuesReturnSourceTimeStamps(1024));
EXPECT_CALL(mockDatabase, commit());
storage.fetchIndexingTimeStamps();
}
TEST_F(SymbolStorage, InsertIndexingTimeStamp)
{
ClangBackEnd::FileStatuses fileStatuses{{1, 0, 34}, {2, 0, 37}};
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(37)));
storage.insertOrUpdateIndexingTimeStamps(fileStatuses);
}
TEST_F(SymbolStorage, InsertIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, immediateBegin());
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(1), TypedEq<int>(34)));
EXPECT_CALL(inserOrUpdateIndexingTimesStampStatement, write(TypedEq<int>(2), TypedEq<int>(34)));
EXPECT_CALL(mockDatabase, commit());
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
}
TEST_F(SymbolStorage, FetchIncludedIndexingTimeStampsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchIncludedIndexingTimeStampsStatement,
valuesReturnSourceTimeStamps(1024, TypedEq<int>(1)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchIncludedIndexingTimeStamps(1);
}
TEST_F(SymbolStorage, FetchDependentSourceIdsIsBusy)
{
InSequence s;
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)))
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockDatabase, rollback());
EXPECT_CALL(mockDatabase, deferredBegin());
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(3)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(2)));
EXPECT_CALL(fetchDependentSourceIdsStatement, valuesReturnFilePathIds(1024, TypedEq<int>(7)));
EXPECT_CALL(mockDatabase, commit());
storage.fetchDependentSourceIds({3, 2, 7});
}
class SymbolStorageSlow : public testing::Test
{
protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
ClangBackEnd::SymbolStorage<> storage{database};
ClangBackEnd::BuildDependenciesStorage<> buildDependenciesStorage{database};
};
TEST_F(SymbolStorageSlow, InsertIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 34}));
}
TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2}, 34);
storage.insertOrUpdateIndexingTimeStamps({1}, 37);
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 37}, SourceTimeStamp{2, 34}));
}
TEST_F(SymbolStorageSlow, InsertIndexingTimeStamp)
{
storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 37}});
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
}
TEST_F(SymbolStorageSlow, UpdateIndexingTimeStamp)
{
storage.insertOrUpdateIndexingTimeStamps({{1, 0, 34}, {2, 0, 34}});
storage.insertOrUpdateIndexingTimeStamps({{2, 0, 37}});
ASSERT_THAT(storage.fetchIndexingTimeStamps(),
ElementsAre(SourceTimeStamp{1, 34}, SourceTimeStamp{2, 37}));
}
TEST_F(SymbolStorageSlow, FetchIncludedIndexingTimeStamps)
{
storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34);
buildDependenciesStorage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}});
auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1);
ASSERT_THAT(timeStamps,
ElementsAre(SourceTimeStamp{1, 34},
SourceTimeStamp{2, 34},
SourceTimeStamp{3, 34},
SourceTimeStamp{4, 34}));
}
TEST_F(SymbolStorageSlow, FetchDependentSourceIds)
{
buildDependenciesStorage.insertOrUpdateSourceDependencies(
{{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}});
auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7});
ASSERT_THAT(sourceIds, ElementsAre(FilePathId{1}, FilePathId{4}, FilePathId{7}));
}
} // namespace

View File

@@ -97,8 +97,14 @@ TEST_F(UsedMacroFilter, Sources)
{
ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros);
ASSERT_THAT(filter.sources,
ElementsAre(FilePathId{2}, FilePathId{3}, FilePathId{4}, FilePathId{5}));
ASSERT_THAT(filter.sources, ElementsAre(FilePathId{6}));
}
TEST_F(UsedMacroFilter, UserIncludes)
{
ClangBackEnd::UsedMacroFilter filter(sources, usedMacros, compileMacros);
ASSERT_THAT(filter.userIncludes, ElementsAre(FilePathId{1}));
}
TEST_F(UsedMacroFilter, SystemUsedMacros)