logic: refresh info generator fixes and tests

* fixed case where "to-index" state of a file has changed and thus the file needs to be re-indexed
* clear and re-index files that depend on changed non-indexed files
* clear and re-index files referenced by unchanged but cleared (due to referencing a changed file) files
* fixed: updated files with changed timestamp that do not have content in the db will now count as changed
* refined refresh info generator tests
* updated checklists for manual project setup tests
This commit is contained in:
mlangkabel
2018-09-14 16:02:01 +02:00
parent 5b7938eda6
commit 5517cd4ccf
10 changed files with 604 additions and 173 deletions
+17 -7
View File
@@ -344,18 +344,13 @@ void PersistentStorage::clearFileElements(const std::vector<FilePath>& filePaths
}
}
std::vector<FileInfo> PersistentStorage::getFileInfoForAllIndexedFiles() const
std::vector<FileInfo> PersistentStorage::getFileInfoForAllFiles() const
{
TRACE();
std::vector<FileInfo> fileInfos;
for (StorageFile file : m_sqliteIndexStorage.getAll<StorageFile>())
{
if (!file.indexed)
{
continue;
}
boost::posix_time::ptime modificationTime = boost::posix_time::not_a_date_time;
if (file.modificationTime != "not-a-date-time")
{
@@ -1471,7 +1466,22 @@ std::shared_ptr<TextAccess> PersistentStorage::getFileContent(const FilePath& fi
{
TRACE();
return m_sqliteIndexStorage.getFileContentByPath(filePath.wstr());
std::shared_ptr<TextAccess> fileContent = m_sqliteIndexStorage.getFileContentByPath(filePath.wstr());
if (fileContent->getLineCount() > 0)
{
return fileContent;
}
return TextAccess::createFromFile(FilePath(filePath));
}
bool PersistentStorage::hasContentForFile(const FilePath& filePath) const
{
std::shared_ptr<TextAccess> fileContent = m_sqliteIndexStorage.getFileContentByPath(filePath.wstr());
if (fileContent->getLineCount() > 0)
{
return true;
}
return false;
}
FileInfo PersistentStorage::getFileInfoForFileId(Id id) const
+2 -1
View File
@@ -66,7 +66,7 @@ public:
void clearAllErrors();
void clearFileElements(const std::vector<FilePath>& filePaths, std::function<void(int)> updateStatusCallback);
std::vector<FileInfo> getFileInfoForAllIndexedFiles() const;
std::vector<FileInfo> getFileInfoForAllFiles() const;
std::set<FilePath> getIncompleteFiles() const;
bool getFilePathIndexed(const FilePath& path) const;
@@ -119,6 +119,7 @@ public:
std::shared_ptr<SourceLocationFile> getCommentLocationsInFile(const FilePath& filePath) const override;
std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const override;
bool hasContentForFile(const FilePath& filePath) const;
FileInfo getFileInfoForFileId(Id id) const override;
@@ -811,7 +811,7 @@ std::shared_ptr<TextAccess> SqliteIndexStorage::getFileContentByPath(const std::
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
}
return TextAccess::createFromFile(FilePath(filePath));
return TextAccess::createFromString("");
}
void SqliteIndexStorage::setFileIndexed(Id fileId, bool indexed)
+75 -43
View File
@@ -12,15 +12,15 @@
RefreshInfo RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(
const std::vector<std::shared_ptr<SourceGroup>>& sourceGroups, std::shared_ptr<const PersistentStorage> storage)
{
const std::set<FilePath> allSourceFilePathsFromSourcegroups = getAllSourceFilePaths(sourceGroups);
std::set<FilePath> unchangedFilePaths;
// 1) Divide filepaths that are already known by the storage to "unchanged and indexed", "unchanged and non-indexed" and "changed"
std::set<FilePath> unchangedIndexedFilePaths;
std::set<FilePath> unchangedNonindexedFilePaths;
std::set<FilePath> changedFilePaths;
{
const std::vector<FileInfo> fileInfosFromStorage = storage->getFileInfoForAllIndexedFiles();
const std::vector<FileInfo> fileInfosFromStorage = storage->getFileInfoForAllFiles();
std::set<FilePath> alreadyIndexedPaths;
std::set<FilePath> alreadyKnownPaths;
{
const std::set<FilePath> filePathsFromStorage = utility::toSet(utility::convert<FileInfo, FilePath>(
fileInfosFromStorage, [](const FileInfo& info) { return info.path; }
@@ -28,24 +28,35 @@ RefreshInfo RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(
for (std::shared_ptr<SourceGroup> sourceGroup : sourceGroups)
{
utility::append(alreadyIndexedPaths, sourceGroup->filterToContainedFilePaths(filePathsFromStorage));
utility::append(alreadyKnownPaths, sourceGroup->filterToContainedFilePaths(filePathsFromStorage));
}
}
// checking source and header files
for (const FileInfo& info : fileInfosFromStorage)
{
if (alreadyIndexedPaths.find(info.path) != alreadyIndexedPaths.end() && info.path.exists())
if (alreadyKnownPaths.find(info.path) != alreadyKnownPaths.end() && info.path.exists())
{
if (didFileChange(info, storage))
if (storage->getFilePathIndexed(info.path))
{
changedFilePaths.insert(info.path);
if (didFileChange(info, storage))
{
changedFilePaths.insert(info.path);
}
else
{
unchangedIndexedFilePaths.insert(info.path);
}
}
else
{
unchangedFilePaths.insert(info.path);
changedFilePaths.insert(info.path);
}
}
else if (!storage->getFilePathIndexed(info.path) && !didFileChange(info, storage))
{
unchangedNonindexedFilePaths.insert(info.path);
}
else // file has been removed
{
changedFilePaths.insert(info.path);
@@ -53,56 +64,68 @@ RefreshInfo RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(
}
}
const std::set<FilePath> allSourceFilePathsFromSourcegroups = getAllSourceFilePaths(sourceGroups);
// 2) Figure out which files need to be cleared
// 2.1) Add all changed files
std::set<FilePath> filesToClear = changedFilePaths;
// handle referencing paths
// 2.2) Add files that are reference the changed files
utility::append(filesToClear, storage->getReferencing(changedFilePaths));
// handle referenced paths
// 2.3) Handle files that are referenced by the files that will be cleared. These will be re-indexed on the fly. However, we do not
// need to clear files that are also referenced by unchanged source files, because otherwise we will lose these connections.
// 2.3.1) Get all source file paths that will not be cleared.
// - Initially this list contains all source file paths the project would index right now.
// - Then we remove all source files that will be cleared
// - NOTE: Source files that are new to the project will part of this list, but won't result in any referenced
// paths because they are not part of the DB. Source files that are new to the project but are already in the
// DB will be removed from this list if they have changed or reference changed files.
std::set<FilePath> staticSourceFiles = allSourceFilePathsFromSourcegroups;
for (const FilePath& path : changedFilePaths)
for (const FilePath& path : filesToClear)
{
staticSourceFiles.erase(path);
}
// 2.3.2) Get sets of referenced files
const std::set<FilePath> staticReferencedFilePaths = storage->getReferenced(staticSourceFiles);
const std::set<FilePath> dynamicReferencedFilePaths = storage->getReferenced(changedFilePaths);
const std::set<FilePath> dynamicReferencedFilePaths = storage->getReferenced(filesToClear);
// 2.3.3) Add "dynamicReferencedFilePaths" to "filesToClear" that are not refenced by static paths, because these files may not be
// referenced anymore. If they still are, they will be re-added when encountered during re-indexing.
for (const FilePath& path : dynamicReferencedFilePaths)
{
if (staticReferencedFilePaths.find(path) == staticReferencedFilePaths.end() &&
staticSourceFiles.find(path) == staticSourceFiles.end())
{
// file may not be referenced anymore and will be reindexed if still needed
filesToClear.insert(path);
}
}
for (const FilePath& path : unchangedFilePaths)
{
staticSourceFiles.erase(path);
}
const std::set<FilePath> filesToAdd = staticSourceFiles;
std::set<FilePath> staticSourceFilePaths;
// 3) Figure out which files need to be indexed
std::set<FilePath> filesToIndex;
for (const FilePath& path : allSourceFilePathsFromSourcegroups)
{
if (filesToClear.find(path) == filesToClear.end() && filesToAdd.find(path) == filesToAdd.end())
if (filesToClear.find(path) != filesToClear.end() || // file will be cleared
unchangedIndexedFilePaths.find(path) == unchangedIndexedFilePaths.end()) // file has been changed or added
{
staticSourceFilePaths.insert(path);
filesToIndex.insert(path);
}
}
// 4) Store and return this information
RefreshInfo info;
info.mode = REFRESH_UPDATED_FILES;
info.filesToClear = filesToClear;
for (const std::shared_ptr<SourceGroup>& sourceGroup : sourceGroups)
info.filesToIndex = filesToIndex;
for (const FilePath fileToClear : filesToClear)
{
if (sourceGroup->getStatus() == SOURCE_GROUP_STATUS_ENABLED)
if (storage->getFilePathIndexed(fileToClear))
{
utility::append(info.filesToIndex, sourceGroup->filterToContainedSourceFilePath(staticSourceFilePaths));
info.filesToClear.insert(fileToClear);
}
else
{
info.nonIndexedFilesToClear.insert(fileToClear);
}
}
@@ -115,11 +138,14 @@ RefreshInfo RefreshInfoGenerator::getRefreshInfoForIncompleteFiles(const std::ve
info.mode = REFRESH_UPDATED_AND_INCOMPLETE_FILES;
std::set<FilePath> incompleteFiles;
for (const FilePath& path : storage->getIncompleteFiles())
{
if (info.filesToClear.find(path) == info.filesToClear.end())
const std::set<FilePath> filesToClear = utility::concat(info.filesToClear, info.nonIndexedFilesToClear);
for (const FilePath& path : storage->getIncompleteFiles())
{
incompleteFiles.insert(path);
if (filesToClear.find(path) == filesToClear.end())
{
incompleteFiles.insert(path);
}
}
}
@@ -188,24 +214,30 @@ bool RefreshInfoGenerator::didFileChange(const FileInfo& info, std::shared_ptr<c
FileInfo diskFileInfo = FileSystem::getFileInfoForPath(info.path);
if (diskFileInfo.lastWriteTime > info.lastWriteTime)
{
if (!storage->hasContentForFile(info.path))
{
return true;
}
std::shared_ptr<TextAccess> storedFileContent = storage->getFileContent(info.path);
std::shared_ptr<TextAccess> diskFileContent = TextAccess::createFromFile(diskFileInfo.path);
const std::vector<std::string>& diskFileLines = diskFileContent->getAllLines();
const std::vector<std::string>& storedFileLines = storedFileContent->getAllLines();
if (diskFileLines.size() == storedFileLines.size())
if (diskFileLines.size() != storedFileLines.size())
{
for (size_t i = 0; i < diskFileLines.size(); i++)
{
if (diskFileLines[i] != storedFileLines[i])
{
return true;
}
}
return false;
return true;
}
return true;
for (size_t i = 0; i < diskFileLines.size(); i++)
{
if (diskFileLines[i] != storedFileLines[i])
{
return true;
}
}
return false;
}
return false;
}
+2 -2
View File
@@ -15,12 +15,12 @@ class RefreshInfoGenerator
{
public:
static RefreshInfo getRefreshInfoForUpdatedFiles(
const std::vector<std::shared_ptr<SourceGroup>>& sourceGroups,
const std::vector<std::shared_ptr<SourceGroup>>& sourceGroups,
std::shared_ptr<const PersistentStorage> storage
);
static RefreshInfo getRefreshInfoForIncompleteFiles(
const std::vector<std::shared_ptr<SourceGroup>>& sourceGroups,
const std::vector<std::shared_ptr<SourceGroup>>& sourceGroups,
std::shared_ptr<const PersistentStorage> storage
);
+503 -115
View File
@@ -29,7 +29,7 @@ public:
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_refresh_info_for_all_files_has_nothing_to_clear_and_specified_source_files_for_basic_sourcegroup()
void test_refresh_info_for_all_files_clears_nothing_and_indexes_previously_unknown_source_file()
{
cleanup();
{
@@ -49,7 +49,7 @@ public:
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToIndex), sourceFilePath
));
));
}
cleanup();
}
@@ -79,14 +79,58 @@ public:
cleanup();
}
void test_refresh_info_for_updated_files_indexes_previously_unknown_file()
// Now we will test how the refresh info generator reacts to different situations when generating refresh info for updated
// files. A file can have different states in the following dimensions:
// file may be known by the storage unknown / nonindexed / indexed
// file may be changed unchanged / changed
// file may be a source file sourcefile / headerfile
// file may now be indexed by the source group nottoindex / toindex
//
// We now wite a test case that checks for the expected result for every possible combination.
// Example: test_unknown_unchanged_sourcefile_that_is_nottoindex
enum KnownState
{
UNKNOWN,
NON_INDEXED,
INDEXED
};
enum ChangedState
{
UNCHANGED,
CHANGED
};
enum FileState
{
SOURCE_FILE,
HEADER_FILE
};
enum IndexingState
{
NOT_TO_INDEX,
TO_INDEX
};
RefreshInfo getRefreshInfo(KnownState knownState, ChangedState changedState, FileState fileState, IndexingState indexingState)
{
RefreshInfo refreshInfo;
cleanup();
{
const FilePath unknownSourceFilePath = m_sourceFolder.getConcatenated(L"unknown_file.cpp");
const FilePath filePath = m_sourceFolder.getConcatenated(L"file.extension");
const std::set<FilePath> sourceFilePaths = ((fileState == SOURCE_FILE) ? std::set<FilePath>({ filePath }) : std::set<FilePath>({}));
const std::set<FilePath> allFilePaths = { filePath };
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({ unknownSourceFilePath })));
if (indexingState == NOT_TO_INDEX)
{
// a file is "not existing" if the source group does not care about it
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({}, {})));
}
else // if (indexingState == TO_INDEX)
{
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest(sourceFilePaths, allFilePaths)));
}
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
@@ -94,123 +138,263 @@ public:
);
storage->setup();
if (knownState == UNKNOWN)
{
// do not add anything to storage
}
else if (knownState == NON_INDEXED)
{
if (changedState == UNCHANGED)
{
addVeryNewFileToStorage(filePath, false, true, storage);
}
else // if (changedState == CHANGED)
{
addVeryOldFileToStorage(filePath, false, true, storage);
}
}
else // if (knownState == INDEXED)
{
if (changedState == UNCHANGED)
{
addVeryNewFileToStorage(filePath, true, true, storage);
}
else // if (changedState == CHANGED)
{
addVeryOldFileToStorage(filePath, true, true, storage);
}
}
addFileToFileSystem(filePath);
storage->buildCaches();
const RefreshInfo refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToIndex), unknownSourceFilePath
));
refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
}
cleanup();
return refreshInfo;
}
void test_refresh_info_for_updated_files_clears_non_existing_file()
void test_unknown_unchanged_sourcefile_that_is_nottoindex()
{
cleanup();
{
const FilePath nonexistingSourceFilePath = m_sourceFolder.getConcatenated(L"non_existing_file.cpp");
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({})));
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
m_bookmarkDbPath
);
storage->setup();
addVeryOldFileToStorage(nonexistingSourceFilePath, true, true, storage);
storage->buildCaches();
const RefreshInfo refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToClear), nonexistingSourceFilePath
));
}
cleanup();
const RefreshInfo refreshInfo = getRefreshInfo(UNKNOWN, UNCHANGED, SOURCE_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_refresh_info_for_updated_files_clears_and_indexes_outdated_file()
void test_unknown_unchanged_sourcefile_that_is_toindex()
{
cleanup();
{
const FilePath outdatedSourceFilePath = m_sourceFolder.getConcatenated(L"outdated_file.cpp");
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({ outdatedSourceFilePath })));
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
m_bookmarkDbPath
);
storage->setup();
addVeryOldFileToStorage(outdatedSourceFilePath, true, true, storage);
addFileToFileSystem(outdatedSourceFilePath);
storage->buildCaches();
const RefreshInfo refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToClear), outdatedSourceFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToIndex), outdatedSourceFilePath
));
}
cleanup();
const RefreshInfo refreshInfo = getRefreshInfo(UNKNOWN, UNCHANGED, SOURCE_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
}
void test_refresh_info_for_updated_files_keeps_up_to_date_file()
void test_unknown_unchanged_headerfile_that_is_nottoindex()
{
cleanup();
{
const FilePath upToDateSourceFilePath = m_sourceFolder.getConcatenated(L"up_to_date_file.cpp");
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({ upToDateSourceFilePath })));
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
m_bookmarkDbPath
);
storage->setup();
addVeryNewFileToStorage(upToDateSourceFilePath, true, true, storage);
addFileToFileSystem(upToDateSourceFilePath);
storage->buildCaches();
const RefreshInfo refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
cleanup();
const RefreshInfo refreshInfo = getRefreshInfo(UNKNOWN, UNCHANGED, HEADER_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_refresh_info_for_updated_files_clears_and_reindexes_outdated_file_and_referencing_source_file()
void test_unknown_unchanged_headerfile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(UNKNOWN, UNCHANGED, HEADER_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size()); // the header file will only be indexed on demand
}
void test_unknown_changed_sourcefile_that_is_nottoindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(UNKNOWN, CHANGED, SOURCE_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_unknown_changed_sourcefile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(UNKNOWN, CHANGED, SOURCE_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
}
void test_unknown_changed_headerfile_that_is_nottoindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(UNKNOWN, CHANGED, HEADER_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_unknown_changed_headerfile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(UNKNOWN, CHANGED, HEADER_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size()); // the header file will only be indexed on demand
}
void test_nonindexed_unchanged_sourcefile_that_is_nottoindex() // this test does not really make sense
{
const RefreshInfo refreshInfo = getRefreshInfo(NON_INDEXED, UNCHANGED, SOURCE_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_nonindexed_unchanged_sourcefile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(NON_INDEXED, UNCHANGED, SOURCE_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
}
void test_nonindexed_unchanged_headerfile_that_is_nottoindex() // this test does not make much sense without source files
{
const RefreshInfo refreshInfo = getRefreshInfo(NON_INDEXED, UNCHANGED, HEADER_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_nonindexed_unchanged_headerfile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(NON_INDEXED, UNCHANGED, HEADER_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size()); // the header file will only be indexed on demand
}
void test_nonindexed_changed_sourcefile_that_is_nottoindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(NON_INDEXED, CHANGED, SOURCE_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_nonindexed_changed_sourcefile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(NON_INDEXED, CHANGED, SOURCE_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
}
void test_nonindexed_changed_headerfile_that_is_nottoindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(NON_INDEXED, CHANGED, HEADER_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size()); // must be cleard here and will be re-indexed on demand
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_nonindexed_changed_headerfile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(NON_INDEXED, CHANGED, HEADER_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size()); // the header file will only be indexed on demand
}
void test_indexed_unchanged_sourcefile_that_is_nottoindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(INDEXED, UNCHANGED, SOURCE_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_indexed_unchanged_sourcefile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(INDEXED, UNCHANGED, SOURCE_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_indexed_unchanged_headerfile_that_is_nottoindex() // TODO: check if depending source file gets reindexed
{
const RefreshInfo refreshInfo = getRefreshInfo(INDEXED, UNCHANGED, HEADER_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_indexed_unchanged_headerfile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(INDEXED, UNCHANGED, HEADER_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_indexed_changed_sourcefile_that_is_nottoindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(INDEXED, CHANGED, SOURCE_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_indexed_changed_sourcefile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(INDEXED, CHANGED, SOURCE_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
}
void test_indexed_changed_headerfile_that_is_nottoindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(INDEXED, CHANGED, HEADER_FILE, NOT_TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
void test_indexed_changed_headerfile_that_is_toindex()
{
const RefreshInfo refreshInfo = getRefreshInfo(INDEXED, CHANGED, HEADER_FILE, TO_INDEX);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size()); // the header file will only be indexed on demand
}
// Now we test some referencing stuff
void test_refresh_info_for_updated_files_clears_and_reindexes_known_outdated_file_and_referencing_source_file()
{
cleanup();
{
@@ -261,7 +445,7 @@ public:
cleanup();
}
void test_refresh_info_for_updated_files_clears_outdated_header_file_and_reindexes_referencing_source()
void test_refresh_info_for_updated_files_clears_known_outdated_header_file_and_reindexes_referencing_source_file()
{
cleanup();
{
@@ -269,13 +453,15 @@ public:
const FilePath outdatedHeaderFilePath = m_sourceFolder.getConcatenated(L"outdated_file.h");
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({
upToDateSourceFilePath
},
{
upToDateSourceFilePath,
outdatedHeaderFilePath
})));
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest(
{
upToDateSourceFilePath
},
{
upToDateSourceFilePath,
outdatedHeaderFilePath
}
)));
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
@@ -312,6 +498,92 @@ public:
cleanup();
}
void test_refresh_info_for_updated_files_clears_unknown_outdated_header_file_and_reindexes_referencing_source()
{
cleanup();
{
const FilePath upToDateSourceFilePath = m_sourceFolder.getConcatenated(L"up_to_date_file.cpp");
const FilePath outdatedHeaderFilePath = m_sourceFolder.getConcatenated(L"outdated_file.h");
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({
upToDateSourceFilePath
})));
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
m_bookmarkDbPath
);
storage->setup();
const Id upToDateSourceFileId = addVeryNewFileToStorage(upToDateSourceFilePath, true, true, storage);
addFileToFileSystem(upToDateSourceFilePath);
const Id outdatedHeaderFileId = addVeryOldFileToStorage(outdatedHeaderFilePath, false, true, storage);
addFileToFileSystem(outdatedHeaderFilePath);
storage->addEdge(StorageEdgeData(Edge::EDGE_INCLUDE, upToDateSourceFileId, outdatedHeaderFileId));
storage->buildCaches();
const RefreshInfo refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToClear), upToDateSourceFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.nonIndexedFilesToClear), outdatedHeaderFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToIndex), upToDateSourceFilePath
));
}
cleanup();
}
void test_refresh_info_for_updated_files_does_not_clear_unknown_uptodate_header_file()
{
cleanup();
{
const FilePath upToDateSourceFilePath = m_sourceFolder.getConcatenated(L"up_to_date_file.cpp");
const FilePath upToDateHeaderFilePath = m_sourceFolder.getConcatenated(L"up_to_date_file.h");
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest(
{
upToDateSourceFilePath
}
)));
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
m_bookmarkDbPath
);
storage->setup();
const Id upToDateSourceFileId = addVeryNewFileToStorage(upToDateSourceFilePath, true, true, storage);
addFileToFileSystem(upToDateSourceFilePath);
const Id upToDateHeaderFileId = addVeryNewFileToStorage(upToDateHeaderFilePath, false, true, storage);
addFileToFileSystem(upToDateHeaderFilePath);
storage->addEdge(StorageEdgeData(Edge::EDGE_INCLUDE, upToDateSourceFileId, upToDateHeaderFileId));
storage->buildCaches();
const RefreshInfo refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(0, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(0, refreshInfo.filesToIndex.size());
}
cleanup();
}
void test_refresh_info_for_updated_files_clears_outdated_source_file_and_referened_uptodate_header_file()
{
cleanup();
@@ -417,6 +689,122 @@ public:
cleanup();
}
void test_clears_unchanged_files_referenced_by_unchanged_file_that_referenced_changed_indexed_file()
{
cleanup();
{
const FilePath upToDateSourceFilePath = m_sourceFolder.getConcatenated(L"up_to_date_file.cpp");
const FilePath upToDateHeaderFilePath = m_sourceFolder.getConcatenated(L"up_to_date_file.h");
const FilePath outOfDateHeaderFilePath = m_sourceFolder.getConcatenated(L"out_of_date_file.h");
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({
upToDateSourceFilePath
},
{
upToDateSourceFilePath,
outOfDateHeaderFilePath,
})));
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
m_bookmarkDbPath
);
storage->setup();
const Id upToDateSourceFileId = addVeryNewFileToStorage(upToDateSourceFilePath, true, true, storage);
addFileToFileSystem(upToDateSourceFilePath);
const Id upToDateHeaderFileId = addVeryNewFileToStorage(upToDateHeaderFilePath, false, true, storage);
addFileToFileSystem(upToDateHeaderFilePath);
const Id outOfDateHeaderFileId = addVeryOldFileToStorage(outOfDateHeaderFilePath, true, true, storage);
addFileToFileSystem(outOfDateHeaderFilePath);
storage->addEdge(StorageEdgeData(Edge::EDGE_INCLUDE, upToDateSourceFileId, upToDateHeaderFileId));
storage->addEdge(StorageEdgeData(Edge::EDGE_INCLUDE, upToDateSourceFileId, outOfDateHeaderFileId));
storage->buildCaches();
const RefreshInfo refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(2, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.nonIndexedFilesToClear), upToDateHeaderFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToClear), upToDateSourceFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToClear), outOfDateHeaderFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToIndex), upToDateSourceFilePath
));
}
cleanup();
}
void test_clears_unchanged_files_referenced_by_unchanged_file_that_referenced_changed_nonindexed_file()
{
cleanup();
{
const FilePath upToDateSourceFilePath = m_sourceFolder.getConcatenated(L"up_to_date_file.cpp");
const FilePath upToDateHeaderFilePath = m_sourceFolder.getConcatenated(L"up_to_date_file.h");
const FilePath outOfDateHeaderFilePath = m_sourceFolder.getConcatenated(L"out_of_date_file.h");
std::vector<std::shared_ptr<SourceGroup>> sourceGroups;
sourceGroups.push_back(std::shared_ptr<SourceGroupTest>(new SourceGroupTest({
upToDateSourceFilePath
},
{
upToDateSourceFilePath,
upToDateHeaderFilePath,
})));
std::shared_ptr<PersistentStorage> storage = std::make_shared<PersistentStorage>(
m_indexDbPath,
m_bookmarkDbPath
);
storage->setup();
const Id upToDateSourceFileId = addVeryNewFileToStorage(upToDateSourceFilePath, true, true, storage);
addFileToFileSystem(upToDateSourceFilePath);
const Id upToDateHeaderFileId = addVeryNewFileToStorage(upToDateHeaderFilePath, true, true, storage);
addFileToFileSystem(upToDateHeaderFilePath);
const Id outOfDateHeaderFileId = addVeryOldFileToStorage(outOfDateHeaderFilePath, false, true, storage);
addFileToFileSystem(outOfDateHeaderFilePath);
storage->addEdge(StorageEdgeData(Edge::EDGE_INCLUDE, upToDateSourceFileId, upToDateHeaderFileId));
storage->addEdge(StorageEdgeData(Edge::EDGE_INCLUDE, upToDateSourceFileId, outOfDateHeaderFileId));
storage->buildCaches();
const RefreshInfo refreshInfo = RefreshInfoGenerator::getRefreshInfoForUpdatedFiles(sourceGroups, storage);
TS_ASSERT_EQUALS(REFRESH_UPDATED_FILES, refreshInfo.mode);
TS_ASSERT_EQUALS(1, refreshInfo.nonIndexedFilesToClear.size());
TS_ASSERT_EQUALS(2, refreshInfo.filesToClear.size());
TS_ASSERT_EQUALS(1, refreshInfo.filesToIndex.size());
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.nonIndexedFilesToClear), outOfDateHeaderFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToClear), upToDateSourceFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToClear), upToDateHeaderFilePath
));
TS_ASSERT(utility::containsElement<FilePath>(
utility::toVector(refreshInfo.filesToIndex), upToDateSourceFilePath
));
}
cleanup();
}
private:
class SourceGroupSettingsTest : public SourceGroupSettings
{
@@ -25,7 +25,7 @@
* Click "Cancel"
* Run "2_update.sh"
* Press "Refresh" button
* Validate "Files to clear" shows "2"
* Validate "Files to clear" shows "3"
* Validate "source files to index" shows "1"
* Click "Start"
* Validate Project indexed without error
+1 -1
View File
@@ -24,7 +24,7 @@
* Click "Cancel"
* Run "2_update.sh"
* Press "Refresh" button
* Validate "Files to clear" shows "2"
* Validate "Files to clear" shows "3"
* Validate "source files to index" shows "1"
* Click "Start"
* Validate Project indexed without error
+1 -1
View File
@@ -24,7 +24,7 @@
* Click "Cancel"
* Run "2_update.sh"
* Press "Refresh" button
* Validate "Files to clear" shows "2"
* Validate "Files to clear" shows "3"
* Validate "source files to index" shows "1"
* Click "Start"
* Validate Project indexed without error
@@ -23,7 +23,7 @@
* Click "Cancel"
* Run "2_update.sh"
* Press "Refresh" button
* Validate "Files to clear" shows "2"
* Validate "Files to clear" shows "3"
* Validate "source files to index" shows "1"
* Click "Start"
* Validate Project indexed without error