forked from qt-creator/qt-creator
Clang: Add fetchTimeStamps to PrecompiledHeaderStorage
Change-Id: I75552a971fbc39a81e14e3b9ec0c5125d3858025 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -59,6 +59,19 @@ public:
|
|||||||
int64 value = -1;
|
int64 value = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PrecompiledHeaderTimeStamps
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrecompiledHeaderTimeStamps() = default;
|
||||||
|
PrecompiledHeaderTimeStamps(long long projectTimeStamp, long long systemTimeStamp)
|
||||||
|
: project(projectTimeStamp)
|
||||||
|
, system(systemTimeStamp)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TimeStamp project;
|
||||||
|
TimeStamp system;
|
||||||
|
};
|
||||||
|
|
||||||
class SourceTimeStamp
|
class SourceTimeStamp
|
||||||
{
|
{
|
||||||
using int64 = long long;
|
using int64 = long long;
|
||||||
|
@@ -182,6 +182,26 @@ public:
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrecompiledHeaderTimeStamps fetchTimeStamps(ProjectPartId projectPartId) const override
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Sqlite::DeferredTransaction transaction{database};
|
||||||
|
|
||||||
|
auto value = fetchTimeStampsStatement.template value<PrecompiledHeaderTimeStamps, 2>(
|
||||||
|
projectPartId.projectPathId);
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
return *value;
|
||||||
|
|
||||||
|
} catch (const Sqlite::StatementIsBusy) {
|
||||||
|
return fetchTimeStamps(projectPartId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sqlite::ImmediateNonThrowingDestructorTransaction transaction;
|
Sqlite::ImmediateNonThrowingDestructorTransaction transaction;
|
||||||
Database &database;
|
Database &database;
|
||||||
@@ -216,6 +236,10 @@ public:
|
|||||||
mutable ReadStatement fetchPrecompiledHeadersStatement{
|
mutable ReadStatement fetchPrecompiledHeadersStatement{
|
||||||
"SELECT projectPchPath, systemPchPath FROM precompiledHeaders WHERE projectPartId = ?",
|
"SELECT projectPchPath, systemPchPath FROM precompiledHeaders WHERE projectPartId = ?",
|
||||||
database};
|
database};
|
||||||
|
mutable ReadStatement fetchTimeStampsStatement{
|
||||||
|
"SELECT projectPchBuildTime, systemPchBuildTime FROM precompiledHeaders WHERE "
|
||||||
|
"projectPartId = ?",
|
||||||
|
database};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -58,6 +58,7 @@ public:
|
|||||||
virtual FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) = 0;
|
virtual FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) = 0;
|
||||||
virtual FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0;
|
virtual FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0;
|
||||||
virtual PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const = 0;
|
virtual PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const = 0;
|
||||||
|
virtual PrecompiledHeaderTimeStamps fetchTimeStamps(ProjectPartId projectPartId) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~PrecompiledHeaderStorageInterface() = default;
|
~PrecompiledHeaderStorageInterface() = default;
|
||||||
|
@@ -52,4 +52,7 @@ public:
|
|||||||
ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId));
|
ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId));
|
||||||
MOCK_CONST_METHOD1(fetchPrecompiledHeaders,
|
MOCK_CONST_METHOD1(fetchPrecompiledHeaders,
|
||||||
ClangBackEnd::PchPaths(ClangBackEnd::ProjectPartId projectPartId));
|
ClangBackEnd::PchPaths(ClangBackEnd::ProjectPartId projectPartId));
|
||||||
|
MOCK_CONST_METHOD1(
|
||||||
|
fetchTimeStamps,
|
||||||
|
ClangBackEnd::PrecompiledHeaderTimeStamps(ClangBackEnd::ProjectPartId projectPartId));
|
||||||
};
|
};
|
||||||
|
@@ -253,3 +253,10 @@ MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int &
|
|||||||
{
|
{
|
||||||
return valueReturnSourceNameAndDirectoryId(id);
|
return valueReturnSourceNameAndDirectoryId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
Utils::optional<ClangBackEnd::PrecompiledHeaderTimeStamps>
|
||||||
|
MockSqliteReadStatement::value<ClangBackEnd::PrecompiledHeaderTimeStamps, 2>(const int &projectPartId)
|
||||||
|
{
|
||||||
|
return valuesReturnPrecompiledHeaderTimeStamps(projectPartId);
|
||||||
|
}
|
||||||
|
@@ -57,9 +57,10 @@ using ClangRefactoring::SourceLocation;
|
|||||||
using ClangRefactoring::SourceLocations;
|
using ClangRefactoring::SourceLocations;
|
||||||
using std::int64_t;
|
using std::int64_t;
|
||||||
namespace Sources = ClangBackEnd::Sources;
|
namespace Sources = ClangBackEnd::Sources;
|
||||||
|
using ClangBackEnd::PrecompiledHeaderTimeStamps;
|
||||||
|
using ClangBackEnd::UsedMacros;
|
||||||
using ClangRefactoring::Symbol;
|
using ClangRefactoring::Symbol;
|
||||||
using ClangRefactoring::Symbols;
|
using ClangRefactoring::Symbols;
|
||||||
using ClangBackEnd::UsedMacros;
|
|
||||||
|
|
||||||
class MockSqliteDatabase;
|
class MockSqliteDatabase;
|
||||||
|
|
||||||
@@ -142,10 +143,11 @@ public:
|
|||||||
MOCK_METHOD1(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t));
|
MOCK_METHOD1(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t));
|
||||||
MOCK_METHOD2(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t, int sourcePathId));
|
MOCK_METHOD2(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t, int sourcePathId));
|
||||||
|
|
||||||
template <typename ResultType,
|
MOCK_METHOD1(valuesReturnPrecompiledHeaderTimeStamps,
|
||||||
int ResultTypeCount = 1,
|
PrecompiledHeaderTimeStamps(int projectPartId));
|
||||||
typename... QueryType>
|
|
||||||
std::vector<ResultType> values(std::size_t reserveSize, const QueryType&... queryValues);
|
template<typename ResultType, int ResultTypeCount = 1, typename... QueryType>
|
||||||
|
std::vector<ResultType> values(std::size_t reserveSize, const QueryType &... queryValues);
|
||||||
|
|
||||||
template <typename ResultType,
|
template <typename ResultType,
|
||||||
int ResultTypeCount = 1,
|
int ResultTypeCount = 1,
|
||||||
@@ -306,3 +308,7 @@ SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t
|
|||||||
template <>
|
template <>
|
||||||
Utils::optional<Sources::SourceNameAndDirectoryId>
|
Utils::optional<Sources::SourceNameAndDirectoryId>
|
||||||
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int&);
|
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int&);
|
||||||
|
|
||||||
|
template<>
|
||||||
|
Utils::optional<ClangBackEnd::PrecompiledHeaderTimeStamps>
|
||||||
|
MockSqliteReadStatement::value<ClangBackEnd::PrecompiledHeaderTimeStamps, 2>(const int &);
|
||||||
|
@@ -51,6 +51,7 @@ protected:
|
|||||||
MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.fetchSystemPrecompiledHeaderPathStatement;
|
MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.fetchSystemPrecompiledHeaderPathStatement;
|
||||||
MockSqliteReadStatement &fetchPrecompiledHeaderStatement = storage.fetchPrecompiledHeaderStatement;
|
MockSqliteReadStatement &fetchPrecompiledHeaderStatement = storage.fetchPrecompiledHeaderStatement;
|
||||||
MockSqliteReadStatement &fetchPrecompiledHeadersStatement = storage.fetchPrecompiledHeadersStatement;
|
MockSqliteReadStatement &fetchPrecompiledHeadersStatement = storage.fetchPrecompiledHeadersStatement;
|
||||||
|
MockSqliteReadStatement &fetchTimeStampsStatement = storage.fetchTimeStampsStatement;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(PrecompiledHeaderStorage, UseTransaction)
|
TEST_F(PrecompiledHeaderStorage, UseTransaction)
|
||||||
@@ -339,4 +340,72 @@ TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeaders)
|
|||||||
Field(&ClangBackEnd::PchPaths::systemPchPath, IsEmpty())));
|
Field(&ClangBackEnd::PchPaths::systemPchPath, IsEmpty())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PrecompiledHeaderStorage, FetchTimeStamps)
|
||||||
|
{
|
||||||
|
ClangBackEnd::PrecompiledHeaderTimeStamps precompiledHeaderTimeStamps{22, 33};
|
||||||
|
ON_CALL(fetchTimeStampsStatement, valuesReturnPrecompiledHeaderTimeStamps(Eq(23)))
|
||||||
|
.WillByDefault(Return(precompiledHeaderTimeStamps));
|
||||||
|
|
||||||
|
auto timeStamps = storage.fetchTimeStamps(23);
|
||||||
|
|
||||||
|
ASSERT_THAT(timeStamps,
|
||||||
|
AllOf(Field(&ClangBackEnd::PrecompiledHeaderTimeStamps::project, Eq(22)),
|
||||||
|
Field(&ClangBackEnd::PrecompiledHeaderTimeStamps::system, Eq(33))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PrecompiledHeaderStorage, NoFetchTimeStamps)
|
||||||
|
{
|
||||||
|
auto timeStamps = storage.fetchTimeStamps(23);
|
||||||
|
|
||||||
|
ASSERT_THAT(timeStamps,
|
||||||
|
AllOf(Field(&ClangBackEnd::PrecompiledHeaderTimeStamps::project, Eq(-1)),
|
||||||
|
Field(&ClangBackEnd::PrecompiledHeaderTimeStamps::system, Eq(-1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PrecompiledHeaderStorage, FetchTimeStampsCalls)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(database, deferredBegin());
|
||||||
|
EXPECT_CALL(fetchTimeStampsStatement, valuesReturnPrecompiledHeaderTimeStamps(Eq(23)));
|
||||||
|
EXPECT_CALL(database, commit());
|
||||||
|
|
||||||
|
storage.fetchTimeStamps(23);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PrecompiledHeaderStorage, FetchTimeStampsBusy)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(database, deferredBegin());
|
||||||
|
EXPECT_CALL(fetchTimeStampsStatement, valuesReturnPrecompiledHeaderTimeStamps(Eq(23)))
|
||||||
|
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
|
||||||
|
EXPECT_CALL(database, rollback());
|
||||||
|
EXPECT_CALL(database, deferredBegin());
|
||||||
|
EXPECT_CALL(fetchTimeStampsStatement, valuesReturnPrecompiledHeaderTimeStamps(Eq(23)));
|
||||||
|
EXPECT_CALL(database, commit());
|
||||||
|
|
||||||
|
storage.fetchTimeStamps(23);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrecompiledHeaderStorageSlowTest : public testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||||
|
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
|
||||||
|
ClangBackEnd::PrecompiledHeaderStorage<> storage{database};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(PrecompiledHeaderStorageSlowTest, NoFetchTimeStamps)
|
||||||
|
{
|
||||||
|
storage.insertProjectPrecompiledHeader(23, {}, 22);
|
||||||
|
storage.insertSystemPrecompiledHeaders({23}, {}, 33);
|
||||||
|
|
||||||
|
auto timeStamps = storage.fetchTimeStamps(23);
|
||||||
|
|
||||||
|
ASSERT_THAT(timeStamps,
|
||||||
|
AllOf(Field(&ClangBackEnd::PrecompiledHeaderTimeStamps::project, Eq(22)),
|
||||||
|
Field(&ClangBackEnd::PrecompiledHeaderTimeStamps::system, Eq(33))));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
Reference in New Issue
Block a user