Clang: Add fetchTimeStamps to PrecompiledHeaderStorage

Change-Id: I75552a971fbc39a81e14e3b9ec0c5125d3858025
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-07-25 15:01:25 +02:00
parent 0fe6811acd
commit 578b70e998
7 changed files with 128 additions and 5 deletions

View File

@@ -59,6 +59,19 @@ public:
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
{
using int64 = long long;

View File

@@ -182,6 +182,26 @@ public:
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:
Sqlite::ImmediateNonThrowingDestructorTransaction transaction;
Database &database;
@@ -216,6 +236,10 @@ public:
mutable ReadStatement fetchPrecompiledHeadersStatement{
"SELECT projectPchPath, systemPchPath FROM precompiledHeaders WHERE projectPartId = ?",
database};
mutable ReadStatement fetchTimeStampsStatement{
"SELECT projectPchBuildTime, systemPchBuildTime FROM precompiledHeaders WHERE "
"projectPartId = ?",
database};
};
}

View File

@@ -58,6 +58,7 @@ public:
virtual FilePath fetchSystemPrecompiledHeaderPath(ProjectPartId projectPartId) = 0;
virtual FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const = 0;
virtual PchPaths fetchPrecompiledHeaders(ProjectPartId projectPartId) const = 0;
virtual PrecompiledHeaderTimeStamps fetchTimeStamps(ProjectPartId projectPartId) const = 0;
protected:
~PrecompiledHeaderStorageInterface() = default;

View File

@@ -52,4 +52,7 @@ public:
ClangBackEnd::FilePath(ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(fetchPrecompiledHeaders,
ClangBackEnd::PchPaths(ClangBackEnd::ProjectPartId projectPartId));
MOCK_CONST_METHOD1(
fetchTimeStamps,
ClangBackEnd::PrecompiledHeaderTimeStamps(ClangBackEnd::ProjectPartId projectPartId));
};

View File

@@ -253,3 +253,10 @@ MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int &
{
return valueReturnSourceNameAndDirectoryId(id);
}
template<>
Utils::optional<ClangBackEnd::PrecompiledHeaderTimeStamps>
MockSqliteReadStatement::value<ClangBackEnd::PrecompiledHeaderTimeStamps, 2>(const int &projectPartId)
{
return valuesReturnPrecompiledHeaderTimeStamps(projectPartId);
}

View File

@@ -57,9 +57,10 @@ using ClangRefactoring::SourceLocation;
using ClangRefactoring::SourceLocations;
using std::int64_t;
namespace Sources = ClangBackEnd::Sources;
using ClangBackEnd::PrecompiledHeaderTimeStamps;
using ClangBackEnd::UsedMacros;
using ClangRefactoring::Symbol;
using ClangRefactoring::Symbols;
using ClangBackEnd::UsedMacros;
class MockSqliteDatabase;
@@ -142,10 +143,11 @@ public:
MOCK_METHOD1(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t));
MOCK_METHOD2(valuesReturnSourceTimeStamps, SourceTimeStamps(std::size_t, int sourcePathId));
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryType>
std::vector<ResultType> values(std::size_t reserveSize, const QueryType&... queryValues);
MOCK_METHOD1(valuesReturnPrecompiledHeaderTimeStamps,
PrecompiledHeaderTimeStamps(int projectPartId));
template<typename ResultType, int ResultTypeCount = 1, typename... QueryType>
std::vector<ResultType> values(std::size_t reserveSize, const QueryType &... queryValues);
template <typename ResultType,
int ResultTypeCount = 1,
@@ -306,3 +308,7 @@ SourceTimeStamps MockSqliteReadStatement::values<SourceTimeStamp, 2>(std::size_t
template <>
Utils::optional<Sources::SourceNameAndDirectoryId>
MockSqliteReadStatement::value<Sources::SourceNameAndDirectoryId, 2>(const int&);
template<>
Utils::optional<ClangBackEnd::PrecompiledHeaderTimeStamps>
MockSqliteReadStatement::value<ClangBackEnd::PrecompiledHeaderTimeStamps, 2>(const int &);

View File

@@ -51,6 +51,7 @@ protected:
MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.fetchSystemPrecompiledHeaderPathStatement;
MockSqliteReadStatement &fetchPrecompiledHeaderStatement = storage.fetchPrecompiledHeaderStatement;
MockSqliteReadStatement &fetchPrecompiledHeadersStatement = storage.fetchPrecompiledHeadersStatement;
MockSqliteReadStatement &fetchTimeStampsStatement = storage.fetchTimeStampsStatement;
};
TEST_F(PrecompiledHeaderStorage, UseTransaction)
@@ -339,4 +340,72 @@ TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeaders)
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