/**************************************************************************** ** ** Copyright (C) 2017 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 "mocksqlitedatabase.h" #include #include #include #include #include #include namespace { using Storage = ClangBackEnd::PrecompiledHeaderStorage>; class PrecompiledHeaderStorage : public testing::Test { protected: NiceMock database; Storage storage{database}; MockSqliteWriteStatement &insertProjectPrecompiledHeaderStatement = storage.insertProjectPrecompiledHeaderStatement; MockSqliteWriteStatement &deleteProjectPrecompiledHeaderStatement = storage.deleteProjectPrecompiledHeaderStatement; MockSqliteWriteStatement &insertSystemPrecompiledHeaderStatement = storage.insertSystemPrecompiledHeaderStatement; MockSqliteWriteStatement &deleteSystemPrecompiledHeaderStatement = storage.deleteSystemPrecompiledHeaderStatement; MockSqliteReadStatement &fetchSystemPrecompiledHeaderPathStatement = storage.fetchSystemPrecompiledHeaderPathStatement; MockSqliteReadStatement &fetchPrecompiledHeaderStatement = storage.fetchPrecompiledHeaderStatement; MockSqliteReadStatement &fetchPrecompiledHeadersStatement = storage.fetchPrecompiledHeadersStatement; }; TEST_F(PrecompiledHeaderStorage, UseTransaction) { InSequence s; EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(database, commit()); Storage storage{database}; } TEST_F(PrecompiledHeaderStorage, InsertProjectPrecompiledHeader) { InSequence s; EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(insertProjectPrecompiledHeaderStatement, write(TypedEq(1), TypedEq("/path/to/pch"), TypedEq(22))); EXPECT_CALL(database, commit()); storage.insertProjectPrecompiledHeader(1, "/path/to/pch", 22); } TEST_F(PrecompiledHeaderStorage, InsertProjectPrecompiledHeaderStatementIsBusy) { InSequence s; EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(insertProjectPrecompiledHeaderStatement, write(TypedEq(1), TypedEq("/path/to/pch"), TypedEq(22))); EXPECT_CALL(database, commit()); storage.insertProjectPrecompiledHeader(1, "/path/to/pch", 22); } TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeader) { InSequence s; EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq(1))); EXPECT_CALL(database, commit()); storage.deleteProjectPrecompiledHeader(1); } TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeaderStatementIsBusy) { InSequence s; EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq(1))); EXPECT_CALL(database, commit()); storage.deleteProjectPrecompiledHeader(1); } TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeaders) { InSequence s; EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq(1))); EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq(2))); EXPECT_CALL(database, commit()); storage.deleteProjectPrecompiledHeaders({1, 2}); } TEST_F(PrecompiledHeaderStorage, DeleteProjectPrecompiledHeadersStatementIsBusy) { InSequence s; EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq(1))); EXPECT_CALL(deleteProjectPrecompiledHeaderStatement, write(TypedEq(2))); EXPECT_CALL(database, commit()); storage.deleteProjectPrecompiledHeaders({1, 2}); } TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeaders) { InSequence s; EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(insertSystemPrecompiledHeaderStatement, write(TypedEq(1), TypedEq("/path/to/pch"), TypedEq(22))); EXPECT_CALL(insertSystemPrecompiledHeaderStatement, write(TypedEq(2), TypedEq("/path/to/pch"), TypedEq(22))); EXPECT_CALL(database, commit()); storage.insertSystemPrecompiledHeaders({1, 2}, "/path/to/pch", 22); } TEST_F(PrecompiledHeaderStorage, InsertSystemPrecompiledHeadersStatementIsBusy) { InSequence s; EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(insertSystemPrecompiledHeaderStatement, write(TypedEq(1), TypedEq("/path/to/pch"), TypedEq(22))); EXPECT_CALL(insertSystemPrecompiledHeaderStatement, write(TypedEq(2), TypedEq("/path/to/pch"), TypedEq(22))); EXPECT_CALL(database, commit()); storage.insertSystemPrecompiledHeaders({1, 2}, "/path/to/pch", 22); } TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeaders) { InSequence s; EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq(1))); EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq(2))); EXPECT_CALL(database, commit()); storage.deleteSystemPrecompiledHeaders({1, 2}); } TEST_F(PrecompiledHeaderStorage, DeleteSystemPrecompiledHeadersStatementIsBusy) { InSequence s; EXPECT_CALL(database, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(database, immediateBegin()); EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq(1))); EXPECT_CALL(deleteSystemPrecompiledHeaderStatement, write(TypedEq(2))); EXPECT_CALL(database, commit()); storage.deleteSystemPrecompiledHeaders({1, 2}); } TEST_F(PrecompiledHeaderStorage, CompilePrecompiledHeaderStatements) { Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; ASSERT_NO_THROW(ClangBackEnd::PrecompiledHeaderStorage<>{database}); } TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderCalls) { InSequence s; EXPECT_CALL(database, deferredBegin()); EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement, valueReturnFilePath(TypedEq(1))); EXPECT_CALL(database, commit()); storage.fetchSystemPrecompiledHeaderPath(1); } TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeader) { EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement, valueReturnFilePath(TypedEq(1))) .WillOnce(Return(ClangBackEnd::FilePath{"/path/to/pch"})); auto path = storage.fetchSystemPrecompiledHeaderPath(1); ASSERT_THAT(path, "/path/to/pch"); } TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsEmptyPath) { EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement, valueReturnFilePath(TypedEq(1))) .WillOnce(Return(ClangBackEnd::FilePath{})); auto path = storage.fetchSystemPrecompiledHeaderPath(1); ASSERT_THAT(path, IsEmpty()); } TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsNullOptional) { EXPECT_CALL(fetchSystemPrecompiledHeaderPathStatement, valueReturnFilePath(TypedEq(1))) .WillOnce(Return(Utils::optional{})); auto path = storage.fetchSystemPrecompiledHeaderPath(1); ASSERT_THAT(path, IsEmpty()); } TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderCallsValueInStatement) { EXPECT_CALL(database, deferredBegin()); EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25))); EXPECT_CALL(database, commit()); storage.fetchPrecompiledHeader(25); } TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderIsBusy) { InSequence s; EXPECT_CALL(database, deferredBegin()); EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25))) .WillOnce(Throw(Sqlite::StatementIsBusy{""})); EXPECT_CALL(database, rollback()); EXPECT_CALL(database, deferredBegin()); EXPECT_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25))); EXPECT_CALL(database, commit()); storage.fetchPrecompiledHeader(25); } TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeader) { ClangBackEnd::FilePath pchFilePath{"/path/to/pch"}; ON_CALL(fetchPrecompiledHeaderStatement, valueReturnFilePath(Eq(25))) .WillByDefault(Return(pchFilePath)); auto path = storage.fetchPrecompiledHeader(25); ASSERT_THAT(path, Eq(pchFilePath)); } TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeader) { auto path = storage.fetchPrecompiledHeader(25); ASSERT_THAT(path, IsEmpty()); } TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderCalls) { EXPECT_CALL(database, deferredBegin()); EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25))); EXPECT_CALL(database, commit()); storage.fetchPrecompiledHeaders(25); } TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeadersIsBusy) { InSequence s; EXPECT_CALL(database, deferredBegin()); EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25))) .WillOnce(Throw(Sqlite::StatementIsBusy{""})); EXPECT_CALL(database, rollback()); EXPECT_CALL(database, deferredBegin()); EXPECT_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25))); EXPECT_CALL(database, commit()); storage.fetchPrecompiledHeaders(25); } TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaders) { ClangBackEnd::PchPaths pchFilePaths{"/project/pch", "/system/pch"}; ON_CALL(fetchPrecompiledHeadersStatement, valueReturnPchPaths(Eq(25))) .WillByDefault(Return(pchFilePaths)); auto paths = storage.fetchPrecompiledHeaders(25); ASSERT_THAT(paths, Eq(pchFilePaths)); } TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeaders) { auto paths = storage.fetchPrecompiledHeaders(25); ASSERT_THAT(paths, AllOf(Field(&ClangBackEnd::PchPaths::projectPchPath, IsEmpty()), Field(&ClangBackEnd::PchPaths::systemPchPath, IsEmpty()))); } } // namespace