diff options
Diffstat (limited to 'tests/unit')
-rw-r--r-- | tests/unit/unittest/changedfilepathcompressor-test.cpp | 112 | ||||
-rw-r--r-- | tests/unit/unittest/clangpathwatcher-test.cpp | 281 | ||||
-rw-r--r-- | tests/unit/unittest/directorypathcompressor-test.cpp | 99 | ||||
-rw-r--r-- | tests/unit/unittest/filepathcache-test.cpp | 150 | ||||
-rw-r--r-- | tests/unit/unittest/filepathstorage-test.cpp | 82 | ||||
-rw-r--r-- | tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp | 8 | ||||
-rw-r--r-- | tests/unit/unittest/filestatuscache-test.cpp | 180 | ||||
-rw-r--r-- | tests/unit/unittest/gtest-creator-printing.cpp | 2 | ||||
-rw-r--r-- | tests/unit/unittest/mockfilepathcaching.h | 6 | ||||
-rw-r--r-- | tests/unit/unittest/mockfilesystem.h | 37 | ||||
-rw-r--r-- | tests/unit/unittest/mockqfilesystemwatcher.h | 1 | ||||
-rw-r--r-- | tests/unit/unittest/mocksqlitereadstatement.cpp | 6 | ||||
-rw-r--r-- | tests/unit/unittest/mocksqlitereadstatement.h | 11 | ||||
-rw-r--r-- | tests/unit/unittest/symbolindexer-test.cpp | 17 | ||||
-rw-r--r-- | tests/unit/unittest/unittest.pro | 5 |
15 files changed, 697 insertions, 300 deletions
diff --git a/tests/unit/unittest/changedfilepathcompressor-test.cpp b/tests/unit/unittest/changedfilepathcompressor-test.cpp deleted file mode 100644 index 08e66a2541..0000000000 --- a/tests/unit/unittest/changedfilepathcompressor-test.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "googletest.h" - -#include "mocktimer.h" - -#include <changedfilepathcompressor.h> -#include <filepathcaching.h> -#include <refactoringdatabaseinitializer.h> - -namespace { - -using testing::ElementsAre; -using testing::Invoke; -using testing::IsEmpty; -using testing::NiceMock; - -using ClangBackEnd::FilePath; -using ClangBackEnd::FilePathId; - -class ChangedFilePathCompressor : public testing::Test -{ -protected: - void SetUp() - { - compressor.setCallback(mockCompressorCallback.AsStdFunction()); - } - - FilePathId filePathId(const QString &filePath) - { - Utils::SmallString utf8FilePath{filePath}; - - return filePathCache.filePathId(ClangBackEnd::FilePathView{utf8FilePath}); - } - -protected: - Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; - ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database}; - ClangBackEnd::FilePathCaching filePathCache{database}; - NiceMock<MockFunction<void (const ClangBackEnd::FilePathIds &filePathIds)>> mockCompressorCallback; - ClangBackEnd::ChangedFilePathCompressor<NiceMock<MockTimer>> compressor{filePathCache}; - NiceMock<MockTimer> &mockTimer = compressor.timer(); - QString filePath1{"filePath1"}; - QString filePath2{"filePath2"}; - FilePathId filePathId1 = filePathId(filePath1); - FilePathId filePathId2 = filePathId(filePath2); -}; - -TEST_F(ChangedFilePathCompressor, AddFilePath) -{ - compressor.addFilePath(filePath1); - - ASSERT_THAT(compressor.takeFilePathIds(), ElementsAre(filePathId(filePath1))); -} - -TEST_F(ChangedFilePathCompressor, NoFilePathsAferTakenThem) -{ - compressor.addFilePath(filePath1); - - compressor.takeFilePathIds(); - - ASSERT_THAT(compressor.takeFilePathIds(), IsEmpty()); -} - -TEST_F(ChangedFilePathCompressor, CallRestartTimerAfterAddingPath) -{ - EXPECT_CALL(mockTimer, start(20)); - - compressor.addFilePath(filePath1); -} - -TEST_F(ChangedFilePathCompressor, CallTimeOutAfterAddingPath) -{ - EXPECT_CALL(mockCompressorCallback, Call(ElementsAre(filePathId1, filePathId2))); - - compressor.addFilePath(filePath1); - compressor.addFilePath(filePath2); -} - -TEST_F(ChangedFilePathCompressor, RemoveDuplicates) -{ - EXPECT_CALL(mockCompressorCallback, Call(ElementsAre(filePathId1, filePathId2))); - - compressor.addFilePath(filePath1); - compressor.addFilePath(filePath2); - compressor.addFilePath(filePath1); -} - -} diff --git a/tests/unit/unittest/clangpathwatcher-test.cpp b/tests/unit/unittest/clangpathwatcher-test.cpp index 00fe91dc49..f4d99e358d 100644 --- a/tests/unit/unittest/clangpathwatcher-test.cpp +++ b/tests/unit/unittest/clangpathwatcher-test.cpp @@ -25,10 +25,11 @@ #include "googletest.h" -#include "mocktimer.h" +#include "mockclangpathwatchernotifier.h" #include "mockfilepathcaching.h" +#include "mockfilesystem.h" #include "mockqfilesystemwatcher.h" -#include "mockclangpathwatchernotifier.h" +#include "mocktimer.h" #include <clangpathwatcher.h> @@ -55,91 +56,126 @@ using ClangBackEnd::WatcherEntry; class ClangPathWatcher : public testing::Test { protected: - void SetUp(); + void SetUp() + { + ON_CALL(mockFilePathCache, filePathId(Eq(path1))).WillByDefault(Return(pathIds[0])); + ON_CALL(mockFilePathCache, filePathId(Eq(path2))).WillByDefault(Return(pathIds[1])); + ON_CALL(mockFilePathCache, filePathId(Eq(path3))).WillByDefault(Return(pathIds[2])); + ON_CALL(mockFilePathCache, filePathId(Eq(path4))).WillByDefault(Return(pathIds[3])); + ON_CALL(mockFilePathCache, filePathId(Eq(path5))).WillByDefault(Return(pathIds[4])); + ON_CALL(mockFilePathCache, filePath(Eq(pathIds[0]))).WillByDefault(Return(FilePath{path1})); + ON_CALL(mockFilePathCache, filePath(Eq(pathIds[1]))).WillByDefault(Return(FilePath{path2})); + ON_CALL(mockFilePathCache, filePath(Eq(pathIds[2]))).WillByDefault(Return(FilePath{path3})); + ON_CALL(mockFilePathCache, filePath(Eq(pathIds[3]))).WillByDefault(Return(FilePath{path4})); + ON_CALL(mockFilePathCache, filePath(Eq(pathIds[4]))).WillByDefault(Return(FilePath{path5})); + ON_CALL(mockFilePathCache, directoryPathId(TypedEq<FilePathId>(pathIds[0]))) + .WillByDefault(Return(directoryPaths[0])); + ON_CALL(mockFilePathCache, directoryPathId(TypedEq<FilePathId>(pathIds[1]))) + .WillByDefault(Return(directoryPaths[0])); + ON_CALL(mockFilePathCache, directoryPathId(TypedEq<FilePathId>(pathIds[2]))) + .WillByDefault(Return(directoryPaths[1])); + ON_CALL(mockFilePathCache, directoryPathId(TypedEq<FilePathId>(pathIds[3]))) + .WillByDefault(Return(directoryPaths[1])); + ON_CALL(mockFilePathCache, directoryPathId(TypedEq<FilePathId>(pathIds[4]))) + .WillByDefault(Return(directoryPaths[2])); + ON_CALL(mockFileSystem, lastModified(_)).WillByDefault(Return(1)); + ON_CALL(mockFilePathCache, + directoryPathId(TypedEq<Utils::SmallStringView>(directoryPathString))) + .WillByDefault(Return(directoryPaths[0])); + ON_CALL(mockFilePathCache, + directoryPathId(TypedEq<Utils::SmallStringView>(directoryPathString2))) + .WillByDefault(Return(directoryPaths[1])); + ON_CALL(mockFilePathCache, directoryPath(Eq(directoryPaths[0]))) + .WillByDefault(Return(directoryPath)); + ON_CALL(mockFilePathCache, directoryPath(Eq(directoryPaths[1]))) + .WillByDefault(Return(directoryPath2)); + ON_CALL(mockFilePathCache, directoryPath(Eq(directoryPaths[2]))) + .WillByDefault(Return(directoryPath3)); + ON_CALL(mockFileSystem, directoryEntries(Eq(directoryPath))) + .WillByDefault(Return(FilePathIds{pathIds[0], pathIds[1]})); + ON_CALL(mockFileSystem, directoryEntries(Eq(directoryPath2))) + .WillByDefault(Return(FilePathIds{pathIds[2], pathIds[3]})); + ON_CALL(mockFileSystem, directoryEntries(Eq(directoryPath3))) + .WillByDefault(Return(FilePathIds{pathIds[4]})); + } static WatcherEntries sorted(WatcherEntries &&entries) { std::stable_sort(entries.begin(), entries.end()); - return entries; + return std::move(entries); } protected: - NiceMock<MockFilePathCaching> filePathCache; + NiceMock<MockFilePathCaching> mockFilePathCache; NiceMock<MockClangPathWatcherNotifier> notifier; - Watcher watcher{filePathCache, ¬ifier}; + NiceMock<MockFileSystem> mockFileSystem; + Watcher watcher{mockFilePathCache, mockFileSystem, ¬ifier}; NiceMock<MockQFileSytemWatcher> &mockQFileSytemWatcher = watcher.fileSystemWatcher(); ProjectPartId id1{2}; ProjectPartId id2{3}; ProjectPartId id3{4}; FilePathView path1{"/path/path1"}; FilePathView path2{"/path/path2"}; + FilePathView path3{"/path2/path1"}; + FilePathView path4{"/path2/path2"}; + FilePathView path5{"/path3/path"}; QString path1QString = QString(path1.toStringView()); QString path2QString = QString(path2.toStringView()); - FilePathIds pathIds = {1, 2}; + QString directoryPath = "/path"; + QString directoryPath2 = "/path2"; + QString directoryPath3 = "/path3"; + Utils::PathString directoryPathString = directoryPath; + 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], pathIds[0]}; - WatcherEntry watcherEntry2{ids[1], pathIds[0]}; - WatcherEntry watcherEntry3{ids[0], pathIds[1]}; - WatcherEntry watcherEntry4{ids[1], pathIds[1]}; - WatcherEntry watcherEntry5{ids[2], pathIds[1]}; + 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]}; }; -TEST_F(ClangPathWatcher, ConvertWatcherEntriesToQStringList) -{ - auto convertedList = watcher.convertWatcherEntriesToQStringList(sorted({watcherEntry1, watcherEntry3})); - - ASSERT_THAT(convertedList, ElementsAre(path1QString, path2QString)); -} - -TEST_F(ClangPathWatcher, UniquePaths) -{ - auto uniqueEntries = watcher.uniquePaths(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4})); - - ASSERT_THAT(uniqueEntries, ElementsAre(watcherEntry1, watcherEntry3)); -} - -TEST_F(ClangPathWatcher, NotWatchedEntries) -{ - watcher.addEntries({watcherEntry1, watcherEntry4}); - - auto newEntries = watcher.notWatchedEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4})); - - ASSERT_THAT(newEntries, ElementsAre(watcherEntry2, watcherEntry3)); -} - TEST_F(ClangPathWatcher, AddIdPaths) { - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString, path2QString})); + EXPECT_CALL(mockQFileSytemWatcher, + addPaths(UnorderedElementsAre(QString(directoryPath), QString(directoryPath2)))); - watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}}); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); } TEST_F(ClangPathWatcher, UpdateIdPathsCallsAddPathInFileWatcher) { - watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}}); - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path2QString})); + EXPECT_CALL(mockQFileSytemWatcher, addPaths(UnorderedElementsAre(QString(directoryPath2)))); - watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}}); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); } TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsCallsRemovePathInFileWatcher) { - watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0]}}}); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString})); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(UnorderedElementsAre(QString(directoryPath2)))); - watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}}); } TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPathsDoNotCallsRemovePathInFileWatcher) { - watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}}, + {id2, {pathIds[0], pathIds[1], pathIds[3]}}, + {id3, {pathIds[0]}}}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString})) - .Times(0); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)).Times(0); - watcher.updateIdPaths({{id1, {pathIds[1]}}, {id2, {pathIds[0]}}}); + watcher.updateIdPaths({{id1, {pathIds[1]}}, {id2, {pathIds[3]}}}); } TEST_F(ClangPathWatcher, UpdateIdPathsAndRemoveUnusedPaths) @@ -165,36 +201,18 @@ TEST_F(ClangPathWatcher, ExtractSortedIdsFromConvertIdPaths) ASSERT_THAT(entriesAndIds.second, ElementsAre(ids[0], ids[1], ids[2])); } -TEST_F(ClangPathWatcher, NotWatchedPaths) -{ - watcher.mergeToWatchedEntries(sorted({watcherEntry1})); - - auto newEntries = watcher.notWatchedPaths({watcherEntry2, watcherEntry3}); - - ASSERT_THAT(newEntries, ElementsAre(watcherEntry3)); -} - -TEST_F(ClangPathWatcher, AddedPaths) -{ - watcher.mergeToWatchedEntries(sorted({watcherEntry1, watcherEntry2})); - - auto filteredEntries = watcher.filterNotWatchedPaths({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4}); - - ASSERT_THAT(filteredEntries, ElementsAre(watcherEntry3)); -} - TEST_F(ClangPathWatcher, MergeEntries) { - watcher.mergeToWatchedEntries(sorted({watcherEntry1, watcherEntry4})); + watcher.updateIdPaths({{id1, {pathIds[0]}}, {id2, {pathIds[1]}}}); ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4)); } TEST_F(ClangPathWatcher, MergeMoreEntries) { - watcher.mergeToWatchedEntries(sorted({watcherEntry1, watcherEntry4})); + watcher.updateIdPaths({{id2, {pathIds[0], pathIds[1]}}}); - watcher.mergeToWatchedEntries(sorted({watcherEntry2, watcherEntry3})); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}}); ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4)); } @@ -204,48 +222,48 @@ TEST_F(ClangPathWatcher, AddEmptyEntries) EXPECT_CALL(mockQFileSytemWatcher, addPaths(_)) .Times(0); - watcher.addEntries({}); + watcher.updateIdPaths({}); } TEST_F(ClangPathWatcher, AddEntriesWithSameIdAndDifferentPaths) { - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString, path2QString})); + EXPECT_CALL(mockQFileSytemWatcher, + addPaths(ElementsAre(directoryPath, directoryPath2, directoryPath3))); - watcher.addEntries({watcherEntry1, watcherEntry3}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2], pathIds[4]}}}); } TEST_F(ClangPathWatcher, AddEntriesWithDifferentIdAndSamePaths) { - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString})); + EXPECT_CALL(mockQFileSytemWatcher, addPaths(ElementsAre(directoryPath))); - watcher.addEntries({watcherEntry1, watcherEntry2}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1]}}}); } TEST_F(ClangPathWatcher, DontAddNewEntriesWithSameIdAndSamePaths) { - watcher.addEntries({watcherEntry1}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}}}); - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString})) - .Times(0); + EXPECT_CALL(mockQFileSytemWatcher, addPaths(_)).Times(0); - watcher.addEntries({watcherEntry1}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}}}); } TEST_F(ClangPathWatcher, DontAddNewEntriesWithDifferentIdAndSamePaths) { - watcher.addEntries({watcherEntry1}); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}}}); - EXPECT_CALL(mockQFileSytemWatcher, addPaths(QStringList{path1QString})) - .Times(0); + EXPECT_CALL(mockQFileSytemWatcher, addPaths(_)).Times(0); - watcher.addEntries({watcherEntry2}); + watcher.updateIdPaths({{id2, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}}}); } TEST_F(ClangPathWatcher, RemoveEntriesWithId) { - watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5})); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[1]}}}); - watcher.removeIdsFromWatchedEntries({ids[0]}); + watcher.removeIds({id1}); ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry2, watcherEntry4, watcherEntry5)); } @@ -260,37 +278,52 @@ TEST_F(ClangPathWatcher, RemoveNoPathsForEmptyIds) TEST_F(ClangPathWatcher, RemoveNoPathsForOneId) { - watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4})); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)) .Times(0); - watcher.removeIds({id1}); + watcher.removeIds({id3}); } TEST_F(ClangPathWatcher, RemovePathForOneId) { - watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3})); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path2QString})); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath2))); - watcher.removeIds({id1}); + watcher.removeIds({id2}); +} + +TEST_F(ClangPathWatcher, RemoveNoPathSecondTime) +{ + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); + watcher.removeIds({id2}); + + EXPECT_CALL(mockQFileSytemWatcher, removePaths(_)).Times(0); + + watcher.removeIds({id2}); } TEST_F(ClangPathWatcher, RemoveAllPathsForThreeId) { - watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5})); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1QString, path2QString})); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath, directoryPath2))); watcher.removeIds({id1, id2, id3}); } TEST_F(ClangPathWatcher, RemoveOnePathForTwoId) { - watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5})); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1]}}, {id2, {pathIds[0], pathIds[1]}}, {id3, {pathIds[3]}}}); - EXPECT_CALL(mockQFileSytemWatcher, removePaths(QStringList{path1QString})); + EXPECT_CALL(mockQFileSytemWatcher, removePaths(ElementsAre(directoryPath))); watcher.removeIds({id1, id2}); } @@ -313,71 +346,51 @@ TEST_F(ClangPathWatcher, RemoveUnusedEntries) ASSERT_THAT(watcher.watchedEntries(), ElementsAre(watcherEntry1, watcherEntry4, watcherEntry5)); } -TEST_F(ClangPathWatcher, EmptyVectorNotifyFileChange) -{ - watcher.addEntries({watcherEntry3}); - - EXPECT_CALL(notifier, pathsWithIdsChanged(IsEmpty())); - - mockQFileSytemWatcher.fileChanged(path1QString); -} - -TEST_F(ClangPathWatcher, NotifyFileChange) -{ - watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5})); - - EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id1, id2))); - - mockQFileSytemWatcher.fileChanged(path1QString); -} - TEST_F(ClangPathWatcher, TwoNotifyFileChanges) { - watcher.addEntries(sorted({watcherEntry1, watcherEntry2, watcherEntry3, watcherEntry4, watcherEntry5})); + watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}}, + {id2, {pathIds[0], pathIds[1], pathIds[3]}}, + {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, id3))); + EXPECT_CALL(notifier, pathsWithIdsChanged(ElementsAre(id1, id2))); - mockQFileSytemWatcher.fileChanged(path2QString); - mockQFileSytemWatcher.fileChanged(path1QString); + mockQFileSytemWatcher.directoryChanged(directoryPath); + mockQFileSytemWatcher.directoryChanged(directoryPath2); } TEST_F(ClangPathWatcher, NotifyForPathChanges) { - watcher.addEntries({watcherEntry1}); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); + ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2)); + ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2)); EXPECT_CALL(notifier, pathsChanged(ElementsAre(pathIds[0]))); - mockQFileSytemWatcher.fileChanged(path1QString); + mockQFileSytemWatcher.directoryChanged(directoryPath); } TEST_F(ClangPathWatcher, NoNotifyForUnwatchedPathChanges) { - watcher.addEntries({watcherEntry3}); + watcher.updateIdPaths({{id1, {pathIds[3]}}, {id2, {pathIds[3]}}}); EXPECT_CALL(notifier, pathsChanged(IsEmpty())); - mockQFileSytemWatcher.fileChanged(path1QString); + mockQFileSytemWatcher.directoryChanged(directoryPath); } TEST_F(ClangPathWatcher, NoDuplicatePathChanges) { - watcher.addEntries({watcherEntry1}); + watcher.updateIdPaths( + {{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}}); + ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2)); EXPECT_CALL(notifier, pathsChanged(ElementsAre(pathIds[0]))); - mockQFileSytemWatcher.fileChanged(path1QString); - mockQFileSytemWatcher.fileChanged(path1QString); -} - -void ClangPathWatcher::SetUp() -{ - ON_CALL(filePathCache, filePathId(Eq(path1))) - .WillByDefault(Return(pathIds[0])); - ON_CALL(filePathCache, filePathId(Eq(path2))) - .WillByDefault(Return(pathIds[1])); - ON_CALL(filePathCache, filePath(pathIds[0])) - .WillByDefault(Return(FilePath{path1})); - ON_CALL(filePathCache, filePath(Eq(pathIds[1]))) - .WillByDefault(Return(FilePath{path2})); -} + mockQFileSytemWatcher.directoryChanged(directoryPath); + mockQFileSytemWatcher.directoryChanged(directoryPath); } +} // namespace diff --git a/tests/unit/unittest/directorypathcompressor-test.cpp b/tests/unit/unittest/directorypathcompressor-test.cpp new file mode 100644 index 0000000000..50853e8e1c --- /dev/null +++ b/tests/unit/unittest/directorypathcompressor-test.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "googletest.h" + +#include "mockfilesystem.h" +#include "mocktimer.h" + +#include <directorypathcompressor.h> + +namespace { + +using testing::ElementsAre; +using testing::Invoke; +using testing::IsEmpty; +using testing::NiceMock; + +using ClangBackEnd::DirectoryPathId; +using ClangBackEnd::DirectoryPathIds; + +class DirectoryPathCompressor : public testing::Test +{ +protected: + void SetUp() + { + compressor.setCallback(mockCompressorCallback.AsStdFunction()); + } + +protected: + NiceMock<MockFunction<void(const DirectoryPathIds &directoryPathIds)>> mockCompressorCallback; + ClangBackEnd::DirectoryPathCompressor<NiceMock<MockTimer>> compressor; + NiceMock<MockTimer> &mockTimer = compressor.timer(); + DirectoryPathId directoryPathId1{1}; + DirectoryPathId directoryPathId2{2}; +}; + +TEST_F(DirectoryPathCompressor, AddFilePath) +{ + compressor.addDirectoryPathId(directoryPathId1); + + ASSERT_THAT(compressor.takeDirectoryPathIds(), ElementsAre(directoryPathId1)); +} + +TEST_F(DirectoryPathCompressor, NoFilePathsAferTakenThem) +{ + compressor.addDirectoryPathId(directoryPathId1); + + compressor.takeDirectoryPathIds(); + + ASSERT_THAT(compressor.takeDirectoryPathIds(), IsEmpty()); +} + +TEST_F(DirectoryPathCompressor, CallRestartTimerAfterAddingPath) +{ + EXPECT_CALL(mockTimer, start(20)); + + compressor.addDirectoryPathId(directoryPathId1); +} + +TEST_F(DirectoryPathCompressor, CallTimeOutAfterAddingPath) +{ + EXPECT_CALL(mockCompressorCallback, Call(ElementsAre(directoryPathId1, directoryPathId2))); + + compressor.addDirectoryPathId(directoryPathId1); + compressor.addDirectoryPathId(directoryPathId2); +} + +TEST_F(DirectoryPathCompressor, RemoveDuplicates) +{ + EXPECT_CALL(mockCompressorCallback, Call(ElementsAre(directoryPathId1, directoryPathId2))); + + compressor.addDirectoryPathId(directoryPathId1); + compressor.addDirectoryPathId(directoryPathId2); + compressor.addDirectoryPathId(directoryPathId1); +} + +} diff --git a/tests/unit/unittest/filepathcache-test.cpp b/tests/unit/unittest/filepathcache-test.cpp index 43b5b026bb..478e5f0215 100644 --- a/tests/unit/unittest/filepathcache-test.cpp +++ b/tests/unit/unittest/filepathcache-test.cpp @@ -31,6 +31,7 @@ namespace { +using ClangBackEnd::DirectoryPathId; using ClangBackEnd::FilePathId; using Cache = ClangBackEnd::FilePathCache<NiceMock<MockFilePathStorage>>; using ClangBackEnd::FilePathId; @@ -166,4 +167,153 @@ TEST_F(FilePathCache, DuplicateFilePathsAreEqual) ASSERT_THAT(filePath2Id, Eq(filePath1Id)); } +TEST_F(FilePathCache, DirectoryPathIdCallsFetchDirectoryId) +{ + EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))); + + cache.directoryPathId(Utils::SmallString("/path/to")); +} + +TEST_F(FilePathCache, SecondDirectoryPathIdCallsNotFetchDirectoryId) +{ + cache.directoryPathId(Utils::SmallString("/path/to")); + + EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))).Times(0); + + cache.directoryPathId(Utils::SmallString("/path/to")); +} + +TEST_F(FilePathCache, DirectoryPathIdWithTrailingSlash) +{ + EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("/path/to"))); + + cache.directoryPathId(Utils::SmallString("/path/to/")); +} + +TEST_F(FilePathCache, DirectoryPathId) +{ + auto id = cache.directoryPathId(Utils::SmallString("/path/to")); + + ASSERT_THAT(id, Eq(DirectoryPathId{5})); +} + +TEST_F(FilePathCache, DirectoryPathIdIsAlreadyInCache) +{ + auto firstId = cache.directoryPathId(Utils::SmallString("/path/to")); + + auto secondId = cache.directoryPathId(Utils::SmallString("/path/to")); + + ASSERT_THAT(secondId, firstId); +} + +TEST_F(FilePathCache, DirectoryPathIdIsAlreadyInCacheWithTrailingSlash) +{ + auto firstId = cache.directoryPathId(Utils::SmallString("/path/to/")); + + auto secondId = cache.directoryPathId(Utils::SmallString("/path/to/")); + + ASSERT_THAT(secondId, firstId); +} + +TEST_F(FilePathCache, DirectoryPathIdIsAlreadyInCacheWithAndWithoutTrailingSlash) +{ + auto firstId = cache.directoryPathId(Utils::SmallString("/path/to/")); + + auto secondId = cache.directoryPathId(Utils::SmallString("/path/to")); + + ASSERT_THAT(secondId, firstId); +} + +TEST_F(FilePathCache, DirectoryPathIdIsAlreadyInCacheWithoutAndWithTrailingSlash) +{ + auto firstId = cache.directoryPathId(Utils::SmallString("/path/to")); + + auto secondId = cache.directoryPathId(Utils::SmallString("/path/to/")); + + ASSERT_THAT(secondId, firstId); +} + +TEST_F(FilePathCache, ThrowForGettingADirectoryPathWithAnInvalidId) +{ + DirectoryPathId directoryPathId; + + ASSERT_THROW(cache.directoryPath(directoryPathId), + ClangBackEnd::NoDirectoryPathForInvalidDirectoryPathId); +} + +TEST_F(FilePathCache, GetADirectoryPath) +{ + DirectoryPathId directoryPathId{5}; + + auto directoryPath = cache.directoryPath(directoryPathId); + + ASSERT_THAT(directoryPath, Eq(Utils::SmallStringView{"/path/to"})); +} + +TEST_F(FilePathCache, GetADirectoryPathWithCachedDirectoryPathId) +{ + DirectoryPathId directoryPathId{5}; + cache.directoryPath(directoryPathId); + + auto directoryPath = cache.directoryPath(directoryPathId); + + ASSERT_THAT(directoryPath, Eq(Utils::SmallStringView{"/path/to"})); +} + +TEST_F(FilePathCache, DirectoryPathCallsFetchDirectoryPath) +{ + EXPECT_CALL(mockStorage, fetchDirectoryPath(Eq(DirectoryPathId{5}))); + + cache.directoryPath(5); +} + +TEST_F(FilePathCache, SecondDirectoryPathCallsNotFetchDirectoryPath) +{ + cache.directoryPath(5); + + EXPECT_CALL(mockStorage, fetchDirectoryPath(_)).Times(0); + + cache.directoryPath(5); +} + +TEST_F(FilePathCache, ThrowForGettingADirectoryPathIdWithAnInvalidFilePathId) +{ + FilePathId filePathId; + + ASSERT_THROW(cache.directoryPathId(filePathId), ClangBackEnd::NoFilePathForInvalidFilePathId); +} + +TEST_F(FilePathCache, FetchDirectoryPathIdByFilePathId) +{ + auto directoryId = cache.directoryPathId(42); + + ASSERT_THAT(directoryId, Eq(5)); +} + +TEST_F(FilePathCache, FetchDirectoryPathIdByFilePathIdCached) +{ + cache.directoryPathId(42); + + auto directoryId = cache.directoryPathId(42); + + ASSERT_THAT(directoryId, Eq(5)); +} + +TEST_F(FilePathCache, FetchFilePathAfterFetchingDirectoryIdByFilePathId) +{ + cache.directoryPathId(42); + + auto filePath = cache.filePath(42); + + ASSERT_THAT(filePath, Eq("/path/to/file.cpp")); +} + +TEST_F(FilePathCache, FetchDirectoryPathIdAfterFetchingFilePathByFilePathId) +{ + cache.filePath(42); + + auto directoryId = cache.directoryPathId(42); + + ASSERT_THAT(directoryId, Eq(5)); } +} // namespace diff --git a/tests/unit/unittest/filepathstorage-test.cpp b/tests/unit/unittest/filepathstorage-test.cpp index 37f325daf0..fb60e32512 100644 --- a/tests/unit/unittest/filepathstorage-test.cpp +++ b/tests/unit/unittest/filepathstorage-test.cpp @@ -46,8 +46,8 @@ protected: void SetUp() { ON_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, - valueReturnInt32(_)) - .WillByDefault(Return(Utils::optional<int>())); + valueReturnInt32(A<Utils::SmallStringView>())) + .WillByDefault(Return(Utils::optional<int>())); ON_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, valueReturnInt32(Utils::SmallStringView(""))) .WillByDefault(Return(Utils::optional<int>(0))); @@ -77,9 +77,12 @@ protected: ON_CALL(selectSourceNameAndDirectoryIdFromSourcesBySourceId, valueReturnSourceNameAndDirectoryId(42)) .WillByDefault(Return(Utils::optional<ClangBackEnd::Sources::SourceNameAndDirectoryId>({"file.cpp", 5}))); + ON_CALL(selectDirectoryIdFromSourcesBySourceId, valueReturnInt32(TypedEq<int>(42))) + .WillByDefault(Return(Utils::optional<int>(5))); - EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, valueReturnInt32(_)) - .Times(AnyNumber()); + EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, + valueReturnInt32(A<Utils::SmallStringView>())) + .Times(AnyNumber()); EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, valueReturnInt32(_, _)) .Times(AnyNumber()); EXPECT_CALL(insertIntoDirectories, write(An<Utils::SmallStringView>())) @@ -107,6 +110,7 @@ protected: MockSqliteWriteStatement &insertIntoDirectories = factory.insertIntoDirectories; MockSqliteWriteStatement &insertIntoSources = factory.insertIntoSources; MockSqliteReadStatement &selectAllSources = factory.selectAllSources; + MockSqliteReadStatement &selectDirectoryIdFromSourcesBySourceId = factory.selectDirectoryIdFromSourcesBySourceId; Storage storage{factory}; }; @@ -229,7 +233,7 @@ TEST_F(FilePathStorage, CallSelectForFetchingDirectoryIdForKnownPath) EXPECT_CALL(mockDatabase, deferredBegin()); EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, - valueReturnInt32(Eq("/path/to"))); + valueReturnInt32(TypedEq<Utils::SmallStringView>("/path/to"))); EXPECT_CALL(mockDatabase, commit()); storage.fetchDirectoryId("/path/to"); @@ -267,7 +271,7 @@ TEST_F(FilePathStorage, CallSelectAndWriteForFetchingDirectoryIdForUnknownPath) EXPECT_CALL(mockDatabase, deferredBegin()); EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, - valueReturnInt32(Eq("/some/not/known/path"))); + valueReturnInt32(TypedEq<Utils::SmallStringView>("/some/not/known/path"))); EXPECT_CALL(insertIntoDirectories, write(TypedEq<Utils::SmallStringView>("/some/not/known/path"))); EXPECT_CALL(mockDatabase, commit()); @@ -296,7 +300,7 @@ TEST_F(FilePathStorage, RestartFetchDirectoryIDIfTheStatementIsBusyInBeginBecaus EXPECT_CALL(mockDatabase, rollback()).Times(0); EXPECT_CALL(mockDatabase, deferredBegin()); EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, - valueReturnInt32(Eq("/other/unknow/path"))); + valueReturnInt32(TypedEq<Utils::SmallStringView>("/other/unknow/path"))); EXPECT_CALL(insertIntoDirectories, write(TypedEq<Utils::SmallStringView>("/other/unknow/path"))); EXPECT_CALL(mockDatabase, commit()); @@ -310,13 +314,13 @@ TEST_F(FilePathStorage, EXPECT_CALL(mockDatabase, deferredBegin()); EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, - valueReturnInt32(Eq("/other/unknow/path"))); + valueReturnInt32(TypedEq<Utils::SmallStringView>("/other/unknow/path"))); EXPECT_CALL(insertIntoDirectories, write(TypedEq<Utils::SmallStringView>("/other/unknow/path"))) .WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(mockDatabase, rollback()); EXPECT_CALL(mockDatabase, deferredBegin()); EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, - valueReturnInt32(Eq("/other/unknow/path"))); + valueReturnInt32(TypedEq<Utils::SmallStringView>("/other/unknow/path"))); EXPECT_CALL(insertIntoDirectories, write(TypedEq<Utils::SmallStringView>("/other/unknow/path"))); EXPECT_CALL(mockDatabase, commit()); @@ -329,13 +333,13 @@ TEST_F(FilePathStorage, CallSelectAndWriteForFetchingDirectoryIdTwoTimesIfTheInd EXPECT_CALL(mockDatabase,deferredBegin()); EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, - valueReturnInt32(Eq("/other/unknow/path"))); + valueReturnInt32(TypedEq<Utils::SmallStringView>("/other/unknow/path"))); EXPECT_CALL(insertIntoDirectories, write(TypedEq<Utils::SmallStringView>("/other/unknow/path"))) .WillOnce(Throw(Sqlite::ConstraintPreventsModification("busy"))); EXPECT_CALL(mockDatabase, rollback()); EXPECT_CALL(mockDatabase,deferredBegin()); EXPECT_CALL(selectDirectoryIdFromDirectoriesByDirectoryPath, - valueReturnInt32(Eq("/other/unknow/path"))); + valueReturnInt32(TypedEq<Utils::SmallStringView>("/other/unknow/path"))); EXPECT_CALL(mockDatabase, commit()); storage.fetchDirectoryId("/other/unknow/path"); @@ -368,7 +372,6 @@ TEST_F(FilePathStorage, EXPECT_CALL(insertIntoSources, write(TypedEq<int>(5), TypedEq<Utils::SmallStringView>("otherunknownfile.h"))) .WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); - ; EXPECT_CALL(mockDatabase, rollback()); EXPECT_CALL(mockDatabase, deferredBegin()); EXPECT_CALL(selectSourceIdFromSourcesByDirectoryIdAndSourceName, @@ -545,4 +548,59 @@ TEST_F(FilePathStorage, RestartFetchAllSourcesIfBeginIsBusy) storage.fetchAllSources(); } +TEST_F(FilePathStorage, FetchDirectoryIdForUnknownFileID) +{ + ASSERT_THROW(storage.fetchDirectoryId(1111), ClangBackEnd::SourceNameIdDoesNotExists); +} + +TEST_F(FilePathStorage, FetchDirectoryId) +{ + auto directoryId = storage.fetchDirectoryId(42); + + ASSERT_THAT(directoryId, 5); +} + +TEST_F(FilePathStorage, FetchDirectoryIdCalls) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, lock()); + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(selectDirectoryIdFromSourcesBySourceId, valueReturnInt32(TypedEq<int>(42))); + EXPECT_CALL(mockDatabase, commit()); + EXPECT_CALL(mockDatabase, unlock()); + + storage.fetchDirectoryId(42); } + +TEST_F(FilePathStorage, FetchDirectoryIdCallsDatabaseIsBusy) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, lock()); + EXPECT_CALL(mockDatabase, deferredBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); + EXPECT_CALL(mockDatabase, rollback()).Times(0); + EXPECT_CALL(mockDatabase, unlock()); + EXPECT_CALL(mockDatabase, lock()); + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(selectDirectoryIdFromSourcesBySourceId, valueReturnInt32(TypedEq<int>(42))); + EXPECT_CALL(mockDatabase, commit()); + EXPECT_CALL(mockDatabase, unlock()); + + storage.fetchDirectoryId(42); +} + +TEST_F(FilePathStorage, FetchDirectoryIdCallsThrows) +{ + InSequence s; + + EXPECT_CALL(mockDatabase, lock()); + EXPECT_CALL(mockDatabase, deferredBegin()); + EXPECT_CALL(selectDirectoryIdFromSourcesBySourceId, valueReturnInt32(TypedEq<int>(41))); + EXPECT_CALL(mockDatabase, rollback()); + EXPECT_CALL(mockDatabase, unlock()); + + ASSERT_ANY_THROW(storage.fetchDirectoryId(41)); +} + +} // namespace diff --git a/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp b/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp index ac902fa700..40af2d99c3 100644 --- a/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp +++ b/tests/unit/unittest/filepathstoragesqlitestatementfactory-test.cpp @@ -61,7 +61,13 @@ TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceIdFromSourcesByDirecto Eq("SELECT sourceId FROM sources WHERE directoryId = ? AND sourceName = ?")); } -TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceNameFromSourcesByDirectoryIdAndSourceId) +TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceNameAndDirectoryIdFromSourcesByAndSourceId) +{ + ASSERT_THAT(factory.selectSourceNameAndDirectoryIdFromSourcesBySourceId.sqlStatement, + Eq("SELECT sourceName, directoryId FROM sources WHERE sourceId = ?")); +} + +TEST_F(FilePathStorageSqliteStatementFactory, SelectSourceNameAndDirectoryIdBySourceId) { ASSERT_THAT(factory.selectSourceNameAndDirectoryIdFromSourcesBySourceId.sqlStatement, Eq("SELECT sourceName, directoryId FROM sources WHERE sourceId = ?")); diff --git a/tests/unit/unittest/filestatuscache-test.cpp b/tests/unit/unittest/filestatuscache-test.cpp index db13bc28a7..07ba02655b 100644 --- a/tests/unit/unittest/filestatuscache-test.cpp +++ b/tests/unit/unittest/filestatuscache-test.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "googletest.h" +#include "mockfilesystem.h" #include <filepathcaching.h> #include <filestatuscache.h> @@ -37,31 +38,33 @@ namespace { using ClangBackEnd::FilePathId; +using ClangBackEnd::FilePathIds; class FileStatusCache : public testing::Test { protected: - FilePathId filePathId(Utils::SmallStringView path) const + FileStatusCache() { - return filePathCache.filePathId(ClangBackEnd::FilePathView(path)); - } - - void touchFile(FilePathId filePathId) - { - std::ofstream ostream(std::string(filePathCache.filePath(filePathId)), std::ios::binary); - ostream.write("\n", 1); - ostream.close(); + ON_CALL(fileSystem, lastModified(Eq(header))).WillByDefault(Return(headerLastModifiedTime)); + ON_CALL(fileSystem, lastModified(Eq(source))).WillByDefault(Return(sourceLastModifiedTime)); + ON_CALL(fileSystem, lastModified(Eq(header2))).WillByDefault(Return(header2LastModifiedTime)); + ON_CALL(fileSystem, lastModified(Eq(source2))).WillByDefault(Return(source2LastModifiedTime)); } protected: - Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; - ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database}; - ClangBackEnd::FilePathCaching filePathCache{database}; - ClangBackEnd::FileStatusCache cache{filePathCache}; - FilePathId header{filePathId(TESTDATA_DIR "/filestatuscache_header.h")}; - FilePathId source{filePathId(TESTDATA_DIR "/filestatuscache_header.cpp")}; - long long headerLastModifiedTime = QFileInfo(TESTDATA_DIR "/filestatuscache_header.h").lastModified().toSecsSinceEpoch(); - long long sourceLastModifiedTime = QFileInfo(TESTDATA_DIR "/filestatuscache_header.cpp").lastModified().toSecsSinceEpoch(); + NiceMock<MockFileSystem> fileSystem; + ClangBackEnd::FileStatusCache cache{fileSystem}; + FilePathId header{1}; + FilePathId source{2}; + FilePathId header2{3}; + FilePathId source2{4}; + FilePathIds entries{header, source, header2, source2}; + long long headerLastModifiedTime = 100; + long long headerLastModifiedTime2 = 110; + long long header2LastModifiedTime = 300; + long long header2LastModifiedTime2 = 310; + long long sourceLastModifiedTime = 200; + long long source2LastModifiedTime = 400; }; TEST_F(FileStatusCache, CreateEntry) @@ -134,18 +137,24 @@ TEST_F(FileStatusCache, AskNewEntryReverseOrderAddedForLastModifiedTime) TEST_F(FileStatusCache, UpdateFile) { - auto oldLastModified = cache.lastModifiedTime(header); - touchFile(header); + EXPECT_CALL(fileSystem, lastModified(Eq(header))) + .Times(2) + .WillOnce(Return(headerLastModifiedTime)) + .WillOnce(Return(headerLastModifiedTime2)); + cache.lastModifiedTime(header); cache.update(header); - ASSERT_THAT(cache.lastModifiedTime(header), Gt(oldLastModified)); + ASSERT_THAT(cache.lastModifiedTime(header), headerLastModifiedTime2); } TEST_F(FileStatusCache, UpdateFileDoesNotChangeEntryCount) { + EXPECT_CALL(fileSystem, lastModified(Eq(header))) + .Times(2) + .WillOnce(Return(headerLastModifiedTime)) + .WillOnce(Return(headerLastModifiedTime2)); cache.lastModifiedTime(header); - touchFile(header); cache.update(header); @@ -154,11 +163,136 @@ TEST_F(FileStatusCache, UpdateFileDoesNotChangeEntryCount) TEST_F(FileStatusCache, UpdateFileForNonExistingEntry) { - touchFile(header); - cache.update(header); ASSERT_THAT(cache, SizeIs(0)); } +TEST_F(FileStatusCache, UpdateFiles) +{ + EXPECT_CALL(fileSystem, lastModified(Eq(header))) + .Times(2) + .WillOnce(Return(headerLastModifiedTime)) + .WillOnce(Return(headerLastModifiedTime2)); + EXPECT_CALL(fileSystem, lastModified(Eq(header2))) + .Times(2) + .WillOnce(Return(header2LastModifiedTime)) + .WillOnce(Return(header2LastModifiedTime2)); + cache.lastModifiedTime(header); + cache.lastModifiedTime(header2); + + cache.update(entries); + + ASSERT_THAT(cache.lastModifiedTime(header), headerLastModifiedTime2); + ASSERT_THAT(cache.lastModifiedTime(header2), header2LastModifiedTime2); } + +TEST_F(FileStatusCache, UpdateFilesDoesNotChangeEntryCount) +{ + EXPECT_CALL(fileSystem, lastModified(Eq(header))) + .Times(2) + .WillOnce(Return(headerLastModifiedTime)) + .WillOnce(Return(headerLastModifiedTime2)); + EXPECT_CALL(fileSystem, lastModified(Eq(header2))) + .Times(2) + .WillOnce(Return(header2LastModifiedTime)) + .WillOnce(Return(header2LastModifiedTime2)); + cache.lastModifiedTime(header); + cache.lastModifiedTime(header2); + + cache.update(entries); + + ASSERT_THAT(cache, SizeIs(2)); +} + +TEST_F(FileStatusCache, UpdateFilesForNonExistingEntry) +{ + cache.update(entries); + + ASSERT_THAT(cache, SizeIs(0)); +} + +TEST_F(FileStatusCache, NewModifiedEntries) +{ + auto modifiedIds = cache.modified(entries); + + ASSERT_THAT(modifiedIds, entries); +} + +TEST_F(FileStatusCache, NoNewModifiedEntries) +{ + cache.modified(entries); + + auto modifiedIds = cache.modified(entries); + + ASSERT_THAT(modifiedIds, IsEmpty()); +} + +TEST_F(FileStatusCache, SomeNewModifiedEntries) +{ + cache.modified({source, header2}); + + auto modifiedIds = cache.modified(entries); + + ASSERT_THAT(modifiedIds, ElementsAre(header, source2)); +} + +TEST_F(FileStatusCache, SomeAlreadyExistingModifiedEntries) +{ + EXPECT_CALL(fileSystem, lastModified(Eq(header))) + .Times(2) + .WillOnce(Return(headerLastModifiedTime)) + .WillOnce(Return(headerLastModifiedTime2)); + EXPECT_CALL(fileSystem, lastModified(Eq(header2))) + .Times(2) + .WillOnce(Return(header2LastModifiedTime)) + .WillOnce(Return(header2LastModifiedTime2)); + EXPECT_CALL(fileSystem, lastModified(Eq(source))).Times(2).WillRepeatedly(Return(sourceLastModifiedTime)); + EXPECT_CALL(fileSystem, lastModified(Eq(source2))) + .Times(2) + .WillRepeatedly(Return(source2LastModifiedTime)); + cache.modified(entries); + + auto modifiedIds = cache.modified(entries); + + ASSERT_THAT(modifiedIds, ElementsAre(header, header2)); +} + +TEST_F(FileStatusCache, SomeAlreadyExistingAndSomeNewModifiedEntries) +{ + EXPECT_CALL(fileSystem, lastModified(Eq(header))).WillRepeatedly(Return(headerLastModifiedTime)); + EXPECT_CALL(fileSystem, lastModified(Eq(header2))) + .Times(2) + .WillOnce(Return(header2LastModifiedTime)) + .WillOnce(Return(header2LastModifiedTime2)); + EXPECT_CALL(fileSystem, lastModified(Eq(source))).Times(2).WillRepeatedly(Return(sourceLastModifiedTime)); + EXPECT_CALL(fileSystem, lastModified(Eq(source2))).WillRepeatedly(Return(source2LastModifiedTime)); + cache.modified({source, header2}); + + auto modifiedIds = cache.modified(entries); + + ASSERT_THAT(modifiedIds, ElementsAre(header, header2, source2)); +} + +TEST_F(FileStatusCache, TimeIsUpdatedForSomeAlreadyExistingModifiedEntries) +{ + EXPECT_CALL(fileSystem, lastModified(Eq(header))) + .Times(2) + .WillOnce(Return(headerLastModifiedTime)) + .WillOnce(Return(headerLastModifiedTime2)); + EXPECT_CALL(fileSystem, lastModified(Eq(header2))) + .Times(2) + .WillOnce(Return(header2LastModifiedTime)) + .WillOnce(Return(header2LastModifiedTime2)); + EXPECT_CALL(fileSystem, lastModified(Eq(source))).Times(2).WillRepeatedly(Return(sourceLastModifiedTime)); + EXPECT_CALL(fileSystem, lastModified(Eq(source2))) + .Times(2) + .WillRepeatedly(Return(source2LastModifiedTime)); + cache.modified(entries); + + cache.modified(entries); + + ASSERT_THAT(cache.lastModifiedTime(header), headerLastModifiedTime2); +} + +} // namespace diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 7ac4a676e3..0ab962dfa5 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -361,7 +361,7 @@ std::ostream &operator<<(std::ostream &out, const WatcherEntry &entry) { out << "(" << entry.id << ", " - << entry.pathId + << entry.filePathId << ")"; return out; diff --git a/tests/unit/unittest/mockfilepathcaching.h b/tests/unit/unittest/mockfilepathcaching.h index 1b22e910ee..ca7960513e 100644 --- a/tests/unit/unittest/mockfilepathcaching.h +++ b/tests/unit/unittest/mockfilepathcaching.h @@ -36,5 +36,11 @@ public: ClangBackEnd::FilePathId (ClangBackEnd::FilePathView filePath)); MOCK_CONST_METHOD1(filePath, ClangBackEnd::FilePath (ClangBackEnd::FilePathId filePathId)); + MOCK_CONST_METHOD1(directoryPathId, + ClangBackEnd::DirectoryPathId(Utils::SmallStringView directoryPath)); + MOCK_CONST_METHOD1(directoryPath, + Utils::PathString(ClangBackEnd::DirectoryPathId directoryPathId)); + MOCK_CONST_METHOD1(directoryPathId, + ClangBackEnd::DirectoryPathId(ClangBackEnd::FilePathId filePathId)); }; diff --git a/tests/unit/unittest/mockfilesystem.h b/tests/unit/unittest/mockfilesystem.h new file mode 100644 index 0000000000..688edbcae5 --- /dev/null +++ b/tests/unit/unittest/mockfilesystem.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "googletest.h" + +#include <filesysteminterface.h> + +class MockFileSystem : public ClangBackEnd::FileSystemInterface +{ +public: + MOCK_CONST_METHOD1(directoryEntries, ClangBackEnd::FilePathIds(const QString &directoryPath)); + MOCK_CONST_METHOD1(lastModified, long long(ClangBackEnd::FilePathId filePathId)); +}; diff --git a/tests/unit/unittest/mockqfilesystemwatcher.h b/tests/unit/unittest/mockqfilesystemwatcher.h index 1bb90b2c37..00f4c600b4 100644 --- a/tests/unit/unittest/mockqfilesystemwatcher.h +++ b/tests/unit/unittest/mockqfilesystemwatcher.h @@ -41,4 +41,5 @@ public: signals: void fileChanged(const QString &); + void directoryChanged(const QString &); }; diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp index b0df1ab75d..1e800e2be1 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -137,6 +137,12 @@ MockSqliteReadStatement::value<int>(const int &directoryId, const Utils::SmallSt return valueReturnInt32(directoryId, text); } +template<> +Utils::optional<int> MockSqliteReadStatement::value<int>(const int &value) +{ + return valueReturnInt32(value); +} + template <> Utils::optional<long long> MockSqliteReadStatement::value<long long>(const int &sourceId) diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index d952c90dec..191c38accd 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -92,11 +92,11 @@ public: MOCK_METHOD1(valueReturnInt32, Utils::optional<int>(Utils::SmallStringView)); - MOCK_METHOD2(valueReturnInt32, - Utils::optional<int>(int, Utils::SmallStringView)); + MOCK_METHOD2(valueReturnInt32, Utils::optional<int>(int, Utils::SmallStringView)); - MOCK_METHOD1(valueReturnInt64, - Utils::optional<long long>(int)); + MOCK_METHOD1(valueReturnInt32, Utils::optional<int>(int)); + + MOCK_METHOD1(valueReturnInt64, Utils::optional<long long>(int)); MOCK_METHOD1(valueReturnPathString, Utils::optional<Utils::PathString>(int)); @@ -244,6 +244,9 @@ template <> Utils::optional<int> MockSqliteReadStatement::value<int>(const int&, const Utils::SmallStringView&); +template<> +Utils::optional<int> MockSqliteReadStatement::value<int>(const int &); + template <> Utils::optional<long long> MockSqliteReadStatement::value<long long>(const ClangBackEnd::FilePathId&); diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index 2db11dc5fb..0bfcf13188 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -28,6 +28,7 @@ #include "mockbuilddependenciesstorage.h" #include "mockclangpathwatcher.h" #include "mockfilepathcaching.h" +#include "mockfilesystem.h" #include "mockmodifiedtimechecker.h" #include "mockprecompiledheaderstorage.h" #include "mockprojectpartsstorage.h" @@ -149,13 +150,6 @@ protected: data.reset(); } - void touchFile(FilePathId filePathId) - { - std::ofstream ostream(std::string(filePathCache.filePath(filePathId)), std::ios::binary); - ostream.write("\n", 1); - ostream.close(); - } - FilePathId filePathId(Utils::SmallStringView path) const { return filePathCache.filePathId(ClangBackEnd::FilePathView(path)); @@ -249,7 +243,8 @@ protected: NiceMock<MockPrecompiledHeaderStorage> mockPrecompiledHeaderStorage; NiceMock<MockProjectPartsStorage> mockProjectPartsStorage; NiceMock<MockClangPathWatcher> mockPathWatcher; - ClangBackEnd::FileStatusCache fileStatusCache{filePathCache}; + NiceMock<MockFileSystem> mockFileSystem; + ClangBackEnd::FileStatusCache fileStatusCache{mockFileSystem}; ClangBackEnd::GeneratedFiles generatedFiles; Manager collectorManger{generatedFiles}; NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback; @@ -1664,13 +1659,12 @@ TEST_F(SymbolIndexer, DISABLED_DontReparseInUpdateProjectPartsIfDefinesAreTheSam TEST_F(SymbolIndexer, PathsChangedUpdatesFileStatusCache) { auto sourceId = filePathId(TESTDATA_DIR "/symbolindexer_pathChanged.cpp"); - auto oldLastModified = fileStatusCache.lastModifiedTime(sourceId); - touchFile(sourceId); + ON_CALL(mockFileSystem, lastModified(Eq(sourceId))).WillByDefault(Return(65)); ON_CALL(mockSymbolStorage, fetchDependentSourceIds(_)).WillByDefault(Return(FilePathIds{sourceId})); indexer.pathsChanged({sourceId}); - ASSERT_THAT(fileStatusCache.lastModifiedTime(sourceId), Gt(oldLastModified)); + ASSERT_THAT(fileStatusCache.lastModifiedTime(sourceId), 65); } TEST_F(SymbolIndexer, GetUpdatableFilePathIdsIfCompilerMacrosAreDifferent) @@ -1706,6 +1700,7 @@ TEST_F(SymbolIndexer, GetNoUpdatableFilePathIdsIfArtefactsAreTheSame) TEST_F(SymbolIndexer, OutdatedFilesPassUpdatableFilePathIds) { + ON_CALL(mockFileSystem, lastModified(Eq(main1PathId))).WillByDefault(Return(65)); indexer.pathsChanged({main1PathId}); ON_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(A<ProjectPartId>())) .WillByDefault(Return(artefact)); diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 63980ab055..d9cef683e7 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -46,7 +46,7 @@ QMAKE_SUBSTITUTES += cpptoolsjson DEFINES += CPPTOOLS_JSON=\"R\\\"xxx($${cpptoolsjson.output})xxx\\\"\" SOURCES += \ - changedfilepathcompressor-test.cpp \ + directorypathcompressor-test.cpp \ clangpathwatcher-test.cpp \ clangqueryexamplehighlightmarker-test.cpp \ clangqueryhighlightmarker-test.cpp \ @@ -175,7 +175,7 @@ SOURCES += \ translationunitupdater-test.cpp \ unsavedfiles-test.cpp \ unsavedfile-test.cpp \ - utf8positionfromlinecolumn-test.cpp \ + utf8positionfromlinecolumn-test.cpp } !isEmpty(LIBTOOLING_LIBS) { @@ -226,6 +226,7 @@ HEADERS += \ mockclangcodemodelserver.h \ mockclangpathwatcher.h \ mockclangpathwatchernotifier.h \ + mockfilesystem.h \ mockpchcreator.h \ mockpchmanagerclient.h \ mockpchmanagernotifier.h \ |