diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h index 8baf1a3b230..8e29b389efc 100644 --- a/src/libs/sqlite/sqlitebasestatement.h +++ b/src/libs/sqlite/sqlitebasestatement.h @@ -195,23 +195,6 @@ public: resetter.reset(); } - template - std::vector values(std::size_t reserveSize) - { - Resetter resetter{this}; - std::vector resultValues; - resultValues.reserve(std::max(reserveSize, m_maximumResultCount)); - - while (BaseStatement::next()) - emplaceBackValues(resultValues); - - setMaximumResultCount(resultValues.size()); - - resetter.reset(); - - return resultValues; - } - template auto values(std::size_t reserveSize, const QueryTypes &...queryValues) { @@ -438,7 +421,10 @@ private: { Resetter(StatementImplementation *statement) : statement(statement) - {} + { + if (statement && !statement->database().isLocked()) + throw DatabaseIsNotLocked{"Database connection is not locked!"}; + } Resetter(Resetter &) = delete; Resetter &operator=(Resetter &) = delete; diff --git a/src/libs/sqlite/sqlitedatabase.cpp b/src/libs/sqlite/sqlitedatabase.cpp index 2cae9b2fc32..284fb9b5eac 100644 --- a/src/libs/sqlite/sqlitedatabase.cpp +++ b/src/libs/sqlite/sqlitedatabase.cpp @@ -70,6 +70,8 @@ Database::Database(Utils::PathString &&databaseFilePath, : m_databaseBackend(*this) , m_busyTimeout(busyTimeout) { + std::lock_guard lock{*this}; + setJournalMode(journalMode); open(std::move(databaseFilePath)); @@ -94,7 +96,6 @@ void Database::open() else m_databaseBackend.registerBusyHandler(); registerTransactionStatements(); - initializeTables(); m_isOpen = true; } @@ -127,18 +128,6 @@ bool Database::isOpen() const return m_isOpen; } -Table &Database::addTable() -{ - m_sqliteTables.emplace_back(); - - return m_sqliteTables.back(); -} - -const std::vector &Database::tables() const -{ - return m_sqliteTables; -} - void Database::setDatabaseFilePath(Utils::PathString &&databaseFilePath) { m_databaseFilePath = std::move(databaseFilePath); @@ -189,20 +178,6 @@ void Database::execute(Utils::SmallStringView sqlStatement) m_databaseBackend.execute(sqlStatement); } -void Database::initializeTables() -{ - try { - ExclusiveTransaction transaction(*this); - - for (Table &table : m_sqliteTables) - table.initialize(*this); - - transaction.commit(); - } catch (const StatementIsBusy &) { - initializeTables(); - } -} - void Database::registerTransactionStatements() { m_statements = std::make_unique(*this); @@ -257,9 +232,16 @@ void Database::sessionRollback() void Database::lock() { m_databaseMutex.lock(); +#ifdef UNIT_TESTS + m_isLocked = true; +#endif } + void Database::unlock() { +#ifdef UNIT_TESTS + m_isLocked = false; +#endif m_databaseMutex.unlock(); } diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h index 72686001245..f52e52777d3 100644 --- a/src/libs/sqlite/sqlitedatabase.h +++ b/src/libs/sqlite/sqlitedatabase.h @@ -87,9 +87,6 @@ public: bool isOpen() const; - Table &addTable(); - const std::vector
&tables() const; - void setDatabaseFilePath(Utils::PathString &&databaseFilePath); const Utils::PathString &databaseFilePath() const; @@ -148,14 +145,23 @@ public: SessionChangeSets changeSets() const; + bool isLocked() const + { +#ifdef UNIT_TESTS + return m_isLocked; +#else + return true; +#endif + } + void lock() override; + void unlock() override; + private: void deferredBegin() override; void immediateBegin() override; void exclusiveBegin() override; void commit() override; void rollback() override; - void lock() override; - void unlock() override; void immediateSessionBegin() override; void sessionCommit() override; void sessionRollback() override; @@ -170,7 +176,6 @@ private: private: Utils::PathString m_databaseFilePath; DatabaseBackend m_databaseBackend; - std::vector
m_sqliteTables; std::mutex m_databaseMutex; std::unique_ptr m_statements; std::chrono::milliseconds m_busyTimeout; @@ -178,6 +183,7 @@ private: OpenMode m_openMode = OpenMode::ReadWrite; bool m_isOpen = false; bool m_isInitialized = false; + bool m_isLocked = false; }; } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp index 9c096364cb5..d9ccd37066e 100644 --- a/src/libs/sqlite/sqlitedatabasebackend.cpp +++ b/src/libs/sqlite/sqlitedatabasebackend.cpp @@ -26,6 +26,7 @@ #include "sqlitedatabasebackend.h" #include "sqlitebasestatement.h" +#include "sqlitedatabase.h" #include "sqliteexception.h" #include "sqlitereadstatement.h" #include "sqlitereadwritestatement.h" diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h index f7004d966bb..12da835eace 100644 --- a/src/libs/sqlite/sqliteexception.h +++ b/src/libs/sqlite/sqliteexception.h @@ -410,4 +410,12 @@ public: {} }; +class DatabaseIsNotLocked : public Exception +{ +public: + DatabaseIsNotLocked(const char *whatErrorHasHappen) + : Exception(whatErrorHasHappen) + {} +}; + } // namespace Sqlite diff --git a/tests/unit/unittest/builddependenciesstorage-test.cpp b/tests/unit/unittest/builddependenciesstorage-test.cpp index f39d1dc2bbe..13a9a6b6ebd 100644 --- a/tests/unit/unittest/builddependenciesstorage-test.cpp +++ b/tests/unit/unittest/builddependenciesstorage-test.cpp @@ -442,7 +442,9 @@ TEST_F(BuildDependenciesStorageSlow, UpdateIndexingTimeStamp) TEST_F(BuildDependenciesStorageSlow, FetchIncludedIndexingTimeStamps) { storage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5}, 34); + database.lock(); storage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {3, 4}, {5, 3}}); + database.unlock(); auto timeStamps = storage.fetchIncludedIndexingTimeStamps(1); @@ -455,7 +457,9 @@ TEST_F(BuildDependenciesStorageSlow, FetchIncludedIndexingTimeStamps) TEST_F(BuildDependenciesStorageSlow, FetchDependentSourceIds) { + database.lock(); storage.insertOrUpdateSourceDependencies({{1, 2}, {1, 3}, {2, 3}, {4, 2}, {5, 6}, {7, 6}}); + database.unlock(); auto sourceIds = storage.fetchDependentSourceIds({3, 2, 7}); diff --git a/tests/unit/unittest/mocksqlitestatement.h b/tests/unit/unittest/mocksqlitestatement.h index 1f0da729d2b..a05c160371f 100644 --- a/tests/unit/unittest/mocksqlitestatement.h +++ b/tests/unit/unittest/mocksqlitestatement.h @@ -116,7 +116,6 @@ class MockSqliteStatement using Base = Sqlite::StatementImplementation, ResultCount>; public: - explicit MockSqliteStatement() {} explicit MockSqliteStatement(SqliteDatabaseMock &databaseMock) : Base{databaseMock} {} diff --git a/tests/unit/unittest/projectpartsstorage-test.cpp b/tests/unit/unittest/projectpartsstorage-test.cpp index 1039f55d35b..06a08533231 100644 --- a/tests/unit/unittest/projectpartsstorage-test.cpp +++ b/tests/unit/unittest/projectpartsstorage-test.cpp @@ -614,6 +614,7 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectPartId) TEST_F(ProjectPartsStorageSlow, FetchProjectPartIdUnguarded) { auto first = storage.fetchProjectPartId("test"); + std::lock_guard lock{database}; auto second = storage.fetchProjectPartIdUnguarded("test"); @@ -635,8 +636,10 @@ TEST_F(ProjectPartsStorageSlow, FetchProjectParts) TEST_F(ProjectPartsStorageSlow, ResetDependentIndexingTimeStamps) { buildDependenciesStorage.insertOrUpdateIndexingTimeStamps({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 34); + database.lock(); buildDependenciesStorage.insertOrUpdateSourceDependencies( {{3, 1}, {4, 1}, {1, 2}, {7, 5}, {8, 6}, {6, 5}, {9, 10}}); + database.unlock(); storage.resetIndexingTimeStamps({projectPart1, projectPart2}); diff --git a/tests/unit/unittest/sqlitedatabase-test.cpp b/tests/unit/unittest/sqlitedatabase-test.cpp index 7ba3648a1c5..3349b89cf72 100644 --- a/tests/unit/unittest/sqlitedatabase-test.cpp +++ b/tests/unit/unittest/sqlitedatabase-test.cpp @@ -55,20 +55,24 @@ class SqliteDatabase : public ::testing::Test protected: SqliteDatabase() { + database.lock(); database.setJournalMode(JournalMode::Memory); database.setDatabaseFilePath(databaseFilePath); - auto &table = database.addTable(); + Table table; table.setName("test"); table.addColumn("id", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); table.addColumn("name"); database.open(); + + table.initialize(database); } ~SqliteDatabase() { if (database.isOpen()) database.close(); + database.unlock(); } std::vector names() const @@ -157,13 +161,6 @@ TEST_F(SqliteDatabase, DatabaseIsNotInitializedIfDatabasePathDoesNotExistAtOpeni ASSERT_FALSE(database.isInitialized()); } -TEST_F(SqliteDatabase, AddTable) -{ - auto sqliteTable = database.addTable(); - - ASSERT_THAT(database.tables(), Contains(sqliteTable)); -} - TEST_F(SqliteDatabase, GetChangesCount) { Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database); @@ -188,18 +185,6 @@ TEST_F(SqliteDatabase, GetLastInsertedRowId) ASSERT_THAT(database.lastInsertedRowId(), 1); } -TEST_F(SqliteDatabase, TableIsReadyAfterOpenDatabase) -{ - database.close(); - auto &table = database.addTable(); - table.setName("foo"); - table.addColumn("name"); - - database.open(); - - ASSERT_TRUE(table.isReady()); -} - TEST_F(SqliteDatabase, LastRowId) { database.setLastInsertedRowId(42); @@ -329,10 +314,12 @@ TEST_F(SqliteDatabase, SessionsCommit) { database.setAttachedTables({"test"}); Sqlite::WriteStatement("INSERT INTO test(id, name) VALUES (?,?)", database).write(1, "foo"); + database.unlock(); Sqlite::ImmediateSessionTransaction transaction{database}; Sqlite::WriteStatement("INSERT INTO test(id, name) VALUES (?,?)", database).write(2, "bar"); transaction.commit(); + database.lock(); Sqlite::WriteStatement("INSERT OR REPLACE INTO test(id, name) VALUES (?,?)", database).write(2, "hoo"); database.applyAndUpdateSessions(); @@ -343,11 +330,13 @@ TEST_F(SqliteDatabase, SessionsRollback) { database.setAttachedTables({"test"}); Sqlite::WriteStatement("INSERT INTO test(id, name) VALUES (?,?)", database).write(1, "foo"); + database.unlock(); { Sqlite::ImmediateSessionTransaction transaction{database}; Sqlite::WriteStatement("INSERT INTO test(id, name) VALUES (?,?)", database).write(2, "bar"); } + database.lock(); Sqlite::WriteStatement("INSERT OR REPLACE INTO test(id, name) VALUES (?,?)", database).write(2, "hoo"); database.applyAndUpdateSessions(); diff --git a/tests/unit/unittest/sqlitedatabasebackend-test.cpp b/tests/unit/unittest/sqlitedatabasebackend-test.cpp index f6c6a62bb2a..fa35838aa82 100644 --- a/tests/unit/unittest/sqlitedatabasebackend-test.cpp +++ b/tests/unit/unittest/sqlitedatabasebackend-test.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -48,8 +49,18 @@ using Sqlite::WriteStatement; class SqliteDatabaseBackend : public ::testing::Test { protected: - void SetUp() override; - void TearDown() override; + SqliteDatabaseBackend() + { + database.lock(); + QDir::temp().remove(QStringLiteral("SqliteDatabaseBackendTest.db")); + databaseBackend.open(databaseFilePath, OpenMode::ReadWrite); + } + + ~SqliteDatabaseBackend() noexcept(true) + { + databaseBackend.closeWithoutException(); + database.unlock(); + } Utils::PathString databaseFilePath = UnitTest::temporaryDirPath() + "/SqliteDatabaseBackendTest.db"; Sqlite::Database database; @@ -123,15 +134,4 @@ TEST_F(SqliteDatabaseBackend, OpenModeReadWrite) ASSERT_THAT(mode, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE); } - -void SqliteDatabaseBackend::SetUp() -{ - QDir::temp().remove(QStringLiteral("SqliteDatabaseBackendTest.db")); - databaseBackend.open(databaseFilePath, OpenMode::ReadWrite); -} - -void SqliteDatabaseBackend::TearDown() -{ - databaseBackend.closeWithoutException(); -} -} +} // namespace diff --git a/tests/unit/unittest/sqlitedatabasemock.h b/tests/unit/unittest/sqlitedatabasemock.h index 28c373f4c4d..29e0a57a0c7 100644 --- a/tests/unit/unittest/sqlitedatabasemock.h +++ b/tests/unit/unittest/sqlitedatabasemock.h @@ -69,4 +69,5 @@ public: MOCK_METHOD(void, applyAndUpdateSessions, (), (override)); MOCK_METHOD(void, setAttachedTables, (const Utils::SmallStringVector &tables), (override)); + MOCK_METHOD(bool, isLocked, (), (const)); }; diff --git a/tests/unit/unittest/sqlitesessions-test.cpp b/tests/unit/unittest/sqlitesessions-test.cpp index 10575731fb5..296dd0cb743 100644 --- a/tests/unit/unittest/sqlitesessions-test.cpp +++ b/tests/unit/unittest/sqlitesessions-test.cpp @@ -119,16 +119,17 @@ MATCHER_P2(HasTag, return t.name == name && t.tag == tag; } -class Sessions : public testing::Test +class SqliteSessions : public testing::Test { protected: - Sessions() { sessions.setAttachedTables({"data", "tags"}); } + SqliteSessions() { sessions.setAttachedTables({"data", "tags"}); } std::vector fetchData() { return selectData.values(8); } std::vector fetchTags() { return selectTags.values(8); } protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; + std::lock_guard lock{database}; DatabaseExecute createTable{"CREATE TABLE data(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT " "UNIQUE, number NUMERIC, value NUMERIC)", database}; @@ -156,12 +157,12 @@ protected: Sqlite::ReadStatement<1> selectChangeSets{"SELECT changeset FROM testsessions", database}; }; -TEST_F(Sessions, DontThrowForCommittingWithoutSessionStart) +TEST_F(SqliteSessions, DontThrowForCommittingWithoutSessionStart) { ASSERT_NO_THROW(sessions.commit()); } -TEST_F(Sessions, CreateEmptySession) +TEST_F(SqliteSessions, CreateEmptySession) { sessions.create(); sessions.commit(); @@ -169,7 +170,7 @@ TEST_F(Sessions, CreateEmptySession) ASSERT_THAT(sessions.changeSets(), IsEmpty()); } -TEST_F(Sessions, CreateSessionWithInsert) +TEST_F(SqliteSessions, CreateSessionWithInsert) { sessions.create(); insertData.write("foo", 22, 3.14); @@ -178,7 +179,7 @@ TEST_F(Sessions, CreateSessionWithInsert) ASSERT_THAT(sessions.changeSets(), SizeIs(1)); } -TEST_F(Sessions, CreateSessionWithUpdate) +TEST_F(SqliteSessions, CreateSessionWithUpdate) { insertData.write("foo", 22, 3.14); @@ -189,7 +190,7 @@ TEST_F(Sessions, CreateSessionWithUpdate) ASSERT_THAT(sessions.changeSets(), SizeIs(1)); } -TEST_F(Sessions, CreateSessionWithDelete) +TEST_F(SqliteSessions, CreateSessionWithDelete) { insertData.write("foo", 22, 3.14); @@ -200,7 +201,7 @@ TEST_F(Sessions, CreateSessionWithDelete) ASSERT_THAT(sessions.changeSets(), SizeIs(1)); } -TEST_F(Sessions, CreateSessionWithInsertAndUpdate) +TEST_F(SqliteSessions, CreateSessionWithInsertAndUpdate) { sessions.create(); insertData.write("foo", 22, 3.14); @@ -213,7 +214,7 @@ TEST_F(Sessions, CreateSessionWithInsertAndUpdate) ASSERT_THAT(sessions.changeSets(), SizeIs(2)); } -TEST_F(Sessions, CreateSession) +TEST_F(SqliteSessions, CreateSession) { sessions.create(); insertData.write("foo", 22, 3.14); @@ -223,7 +224,7 @@ TEST_F(Sessions, CreateSession) ASSERT_THAT(sessions.changeSets(), SizeIs(1)); } -TEST_F(Sessions, RevertSession) +TEST_F(SqliteSessions, RevertSession) { sessions.create(); insertData.write("foo", 22, 3.14); @@ -234,7 +235,7 @@ TEST_F(Sessions, RevertSession) ASSERT_THAT(fetchData(), IsEmpty()); } -TEST_F(Sessions, RevertSessionToBase) +TEST_F(SqliteSessions, RevertSessionToBase) { insertData.write("bar", "foo", 99); sessions.create(); @@ -246,7 +247,7 @@ TEST_F(Sessions, RevertSessionToBase) ASSERT_THAT(fetchData(), ElementsAre(HasData("bar", "foo", 99))); } -TEST_F(Sessions, RevertMultipleSession) +TEST_F(SqliteSessions, RevertMultipleSession) { sessions.create(); insertData.write("foo", 22, 3.14); @@ -260,7 +261,7 @@ TEST_F(Sessions, RevertMultipleSession) ASSERT_THAT(fetchData(), IsEmpty()); } -TEST_F(Sessions, ApplySession) +TEST_F(SqliteSessions, ApplySession) { sessions.create(); insertData.write("foo", 22, 3.14); @@ -271,7 +272,7 @@ TEST_F(Sessions, ApplySession) ASSERT_THAT(fetchData(), ElementsAre(HasData("foo", 22, 3.14))); } -TEST_F(Sessions, ApplySessionAfterAddingNewEntries) +TEST_F(SqliteSessions, ApplySessionAfterAddingNewEntries) { sessions.create(); insertData.write("foo", 22, 3.14); @@ -284,7 +285,7 @@ TEST_F(Sessions, ApplySessionAfterAddingNewEntries) UnorderedElementsAre(HasData("foo", 22, 3.14), HasData("bar", "foo", 99))); } -TEST_F(Sessions, ApplyOverridesEntriesWithUniqueConstraint) +TEST_F(SqliteSessions, ApplyOverridesEntriesWithUniqueConstraint) { sessions.create(); insertData.write("foo", 22, 3.14); @@ -296,7 +297,7 @@ TEST_F(Sessions, ApplyOverridesEntriesWithUniqueConstraint) ASSERT_THAT(fetchData(), ElementsAre(HasData("foo", 22, 3.14))); } -TEST_F(Sessions, ApplyDoesNotOverrideDeletedEntries) +TEST_F(SqliteSessions, ApplyDoesNotOverrideDeletedEntries) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -309,7 +310,7 @@ TEST_F(Sessions, ApplyDoesNotOverrideDeletedEntries) ASSERT_THAT(fetchData(), IsEmpty()); } -TEST_F(Sessions, ApplyDoesOnlyOverwriteUpdatedValues) +TEST_F(SqliteSessions, ApplyDoesOnlyOverwriteUpdatedValues) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -322,7 +323,7 @@ TEST_F(Sessions, ApplyDoesOnlyOverwriteUpdatedValues) ASSERT_THAT(fetchData(), ElementsAre(HasData("foo", "poo", 1234))); } -TEST_F(Sessions, ApplyDoesDoesNotOverrideForeignKeyIfReferenceIsDeleted) +TEST_F(SqliteSessions, ApplyDoesDoesNotOverrideForeignKeyIfReferenceIsDeleted) { insertData.write("foo2", "bar", 3.14); insertData.write("foo", "bar", 3.14); @@ -337,7 +338,7 @@ TEST_F(Sessions, ApplyDoesDoesNotOverrideForeignKeyIfReferenceIsDeleted) ASSERT_THAT(fetchTags(), ElementsAre(HasTag("foo2", 4321))); } -TEST_F(Sessions, ApplyDoesDoesNotOverrideIfConstraintsIsApplied) +TEST_F(SqliteSessions, ApplyDoesDoesNotOverrideIfConstraintsIsApplied) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -351,8 +352,9 @@ TEST_F(Sessions, ApplyDoesDoesNotOverrideIfConstraintsIsApplied) ASSERT_THAT(fetchTags(), IsEmpty()); } -TEST_F(Sessions, ApplyDoesDoesNotOverrideForeignKeyIfReferenceIsDeletedDeferred) +TEST_F(SqliteSessions, ApplyDoesDoesNotOverrideForeignKeyIfReferenceIsDeletedDeferred) { + database.unlock(); Sqlite::DeferredTransaction transaction{database}; insertData.write("foo2", "bar", 3.14); insertData.write("foo", "bar", 3.14); @@ -365,10 +367,11 @@ TEST_F(Sessions, ApplyDoesDoesNotOverrideForeignKeyIfReferenceIsDeletedDeferred) sessions.apply(); transaction.commit(); + database.lock(); ASSERT_THAT(fetchTags(), ElementsAre(HasTag("foo2", 4321))); } -TEST_F(Sessions, EndSessionOnRollback) +TEST_F(SqliteSessions, EndSessionOnRollback) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -385,7 +388,7 @@ TEST_F(Sessions, EndSessionOnRollback) ASSERT_THAT(fetchData(), ElementsAre(HasData("foo", 333, 666))); } -TEST_F(Sessions, EndSessionOnCommit) +TEST_F(SqliteSessions, EndSessionOnCommit) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -399,7 +402,7 @@ TEST_F(Sessions, EndSessionOnCommit) ASSERT_THAT(fetchData(), ElementsAre(HasData("foo", "bar", 99))); } -TEST_F(Sessions, DeleteSessions) +TEST_F(SqliteSessions, DeleteSessions) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -413,7 +416,7 @@ TEST_F(Sessions, DeleteSessions) ASSERT_THAT(fetchData(), ElementsAre(HasData("foo", "bar", 3.14))); } -TEST_F(Sessions, DeleteAllSessions) +TEST_F(SqliteSessions, DeleteAllSessions) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -427,7 +430,7 @@ TEST_F(Sessions, DeleteAllSessions) ASSERT_THAT(fetchData(), ElementsAre(HasData("foo", "bar", 3.14))); } -TEST_F(Sessions, ApplyAndUpdateSessions) +TEST_F(SqliteSessions, ApplyAndUpdateSessions) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -442,7 +445,7 @@ TEST_F(Sessions, ApplyAndUpdateSessions) ASSERT_THAT(fetchData(), ElementsAre(HasData("foo", "bar", 22))); } -TEST_F(Sessions, ApplyAndUpdateSessionsHasOnlyOneChangeSet) +TEST_F(SqliteSessions, ApplyAndUpdateSessionsHasOnlyOneChangeSet) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -455,7 +458,7 @@ TEST_F(Sessions, ApplyAndUpdateSessionsHasOnlyOneChangeSet) ASSERT_THAT(sessions.changeSets(), SizeIs(1)); } -TEST_F(Sessions, ForEmptySessionBeginEqualsEnd) +TEST_F(SqliteSessions, ForEmptySessionBeginEqualsEnd) { auto changeSets = sessions.changeSets(); @@ -464,7 +467,7 @@ TEST_F(Sessions, ForEmptySessionBeginEqualsEnd) ASSERT_THAT(begin, Eq(changeSets.end())); } -TEST_F(Sessions, IteratorBeginUnequalsEndIfChangeSetHasContent) +TEST_F(SqliteSessions, IteratorBeginUnequalsEndIfChangeSetHasContent) { sessions.create(); insertData.write("foo", "bar", 3.14); @@ -477,7 +480,7 @@ TEST_F(Sessions, IteratorBeginUnequalsEndIfChangeSetHasContent) ASSERT_THAT(begin, Ne(changeSet.end())); } -TEST_F(Sessions, NextIteratorUnequalsBeginIfChangeSetHasContent) +TEST_F(SqliteSessions, NextIteratorUnequalsBeginIfChangeSetHasContent) { sessions.create(); insertData.write("foo", "bar", 3.14); @@ -490,7 +493,7 @@ TEST_F(Sessions, NextIteratorUnequalsBeginIfChangeSetHasContent) ASSERT_NE(next, changeSet.begin()); } -TEST_F(Sessions, NextIteratorEqualsEndIfChangeSetHasContent) +TEST_F(SqliteSessions, NextIteratorEqualsEndIfChangeSetHasContent) { sessions.create(); insertData.write("foo", "bar", 3.14); @@ -503,7 +506,7 @@ TEST_F(Sessions, NextIteratorEqualsEndIfChangeSetHasContent) ASSERT_THAT(next, Eq(changeSet.end())); } -TEST_F(Sessions, NextIteratorNotUnqualsEndIfChangeSetHasContent) +TEST_F(SqliteSessions, NextIteratorNotUnqualsEndIfChangeSetHasContent) { sessions.create(); insertData.write("foo", "bar", 3.14); @@ -516,7 +519,7 @@ TEST_F(Sessions, NextIteratorNotUnqualsEndIfChangeSetHasContent) ASSERT_THAT(next, Not(Ne(changeSet.end()))); } -TEST_F(Sessions, BeginIteratorHasInsertOperation) +TEST_F(SqliteSessions, BeginIteratorHasInsertOperation) { sessions.create(); insertData.write("foo", "bar", 3.14); @@ -530,7 +533,7 @@ TEST_F(Sessions, BeginIteratorHasInsertOperation) ASSERT_THAT(tuple.operation, Eq(Operation::Insert)); } -TEST_F(Sessions, BeginIteratorHasUpdateOperation) +TEST_F(SqliteSessions, BeginIteratorHasUpdateOperation) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -545,7 +548,7 @@ TEST_F(Sessions, BeginIteratorHasUpdateOperation) ASSERT_THAT(tuple.operation, Eq(Operation::Update)); } -TEST_F(Sessions, BeginIteratorHasDeleteOperation) +TEST_F(SqliteSessions, BeginIteratorHasDeleteOperation) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -560,7 +563,7 @@ TEST_F(Sessions, BeginIteratorHasDeleteOperation) ASSERT_THAT(tuple.operation, Eq(Operation::Delete)); } -TEST_F(Sessions, BeginIteratorHasDataTableName) +TEST_F(SqliteSessions, BeginIteratorHasDataTableName) { sessions.create(); insertData.write("foo", "bar", 3.14); @@ -574,7 +577,7 @@ TEST_F(Sessions, BeginIteratorHasDataTableName) ASSERT_THAT(tuple.table, Eq("data")); } -TEST_F(Sessions, ConvertAllValueTypesInChangeSet) +TEST_F(SqliteSessions, ConvertAllValueTypesInChangeSet) { sessions.create(); insertData.write("foo", "bar", 3.14); @@ -593,7 +596,7 @@ TEST_F(Sessions, ConvertAllValueTypesInChangeSet) HasValues(3.14, nullptr))); } -TEST_F(Sessions, InsertOneValueChangeSet) +TEST_F(SqliteSessions, InsertOneValueChangeSet) { sessions.create(); insertOneDatum.write("foo"); @@ -612,7 +615,7 @@ TEST_F(Sessions, InsertOneValueChangeSet) HasValues("foo", nullptr))); } -TEST_F(Sessions, UpdateOneValueChangeSet) +TEST_F(SqliteSessions, UpdateOneValueChangeSet) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -632,7 +635,7 @@ TEST_F(Sessions, UpdateOneValueChangeSet) HasValues(99, 3.14))); } -TEST_F(Sessions, DeleteRowChangeSet) +TEST_F(SqliteSessions, DeleteRowChangeSet) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -653,7 +656,7 @@ TEST_F(Sessions, DeleteRowChangeSet) HasValues(nullptr, 3.14))); } -TEST_F(Sessions, EmptyChangeSet) +TEST_F(SqliteSessions, EmptyChangeSet) { sessions.create(); sessions.commit(); @@ -663,7 +666,7 @@ TEST_F(Sessions, EmptyChangeSet) ASSERT_THAT(changeSets, ElementsAre()); } -TEST_F(Sessions, AccessInsertOneValueChangeSet) +TEST_F(SqliteSessions, AccessInsertOneValueChangeSet) { sessions.create(); insertOneDatum.write("foo"); @@ -678,7 +681,7 @@ TEST_F(Sessions, AccessInsertOneValueChangeSet) ASSERT_THAT(value, HasValues("foo", nullptr)); } -TEST_F(Sessions, AccessUpdateOneValueChangeSet) +TEST_F(SqliteSessions, AccessUpdateOneValueChangeSet) { insertData.write("foo", "bar", 3.14); sessions.create(); @@ -694,7 +697,7 @@ TEST_F(Sessions, AccessUpdateOneValueChangeSet) ASSERT_THAT(value, HasValues(99, 3.14)); } -TEST_F(Sessions, AccessDeleteRowChangeSet) +TEST_F(SqliteSessions, AccessDeleteRowChangeSet) { insertData.write("foo", "bar", 3.14); sessions.create(); diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index 10e5c609ae5..c6945ff5ec7 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -99,21 +100,35 @@ MATCHER_P(HasNullValues, rowid, std::string(negation ? "isn't null" : "is null") class SqliteStatement : public ::testing::Test { protected: - void SetUp() override + SqliteStatement() { + database.lock(); + database.execute("CREATE TABLE test(name TEXT UNIQUE, number NUMERIC, value NUMERIC)"); database.execute("INSERT INTO test VALUES ('bar', 'blah', 1)"); database.execute("INSERT INTO test VALUES ('foo', 23.3, 2)"); database.execute("INSERT INTO test VALUES ('poo', 40, 3)"); + + ON_CALL(databaseMock, isLocked()).WillByDefault(Return(true)); } - void TearDown() override + + ~SqliteStatement() { if (database.isOpen()) database.close(); + + database.unlock(); + } + + template + static auto toValues(Range &&range) + { + return std::vector{range.begin(), range.end()}; } protected: - Database database{":memory:", Sqlite::JournalMode::Memory}; + Database database{":memory:", Sqlite::JournalMode::Memory}; + NiceMock databaseMock; }; struct Output @@ -668,8 +683,7 @@ TEST_F(SqliteStatement, GetTupleRangeWithoutArguments) using Tuple = std::tuple; ReadStatement<3> statement("SELECT name, number, value FROM test", database); - auto range = statement.range(); - std::vector values{range.begin(), range.end()}; + std::vector values = toValues(statement.range()); ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3})); @@ -679,12 +693,13 @@ TEST_F(SqliteStatement, GetTupleRangeWithTransactionWithoutArguments) { using Tuple = std::tuple; ReadStatement<3> statement("SELECT name, number, value FROM test", database); + database.unlock(); - auto range = statement.rangeWithTransaction(); - std::vector values{range.begin(), range.end()}; + std::vector values = toValues(statement.rangeWithTransaction()); ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3})); + database.lock(); } TEST_F(SqliteStatement, GetTupleRangeInForRangeLoop) @@ -705,12 +720,14 @@ TEST_F(SqliteStatement, GetTupleRangeWithTransactionInForRangeLoop) using Tuple = std::tuple; ReadStatement<3> statement("SELECT name, number, value FROM test", database); std::vector values; + database.unlock(); for (auto value : statement.rangeWithTransaction()) values.push_back(value); ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3})); + database.lock(); } TEST_F(SqliteStatement, GetTupleRangeInForRangeLoopWithBreak) @@ -733,6 +750,7 @@ TEST_F(SqliteStatement, GetTupleRangeWithTransactionInForRangeLoopWithBreak) using Tuple = std::tuple; ReadStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database); std::vector values; + database.unlock(); for (auto value : statement.rangeWithTransaction()) { values.push_back(value); @@ -741,6 +759,7 @@ TEST_F(SqliteStatement, GetTupleRangeWithTransactionInForRangeLoopWithBreak) } ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2})); + database.lock(); } TEST_F(SqliteStatement, GetTupleRangeInForRangeLoopWithContinue) @@ -763,6 +782,7 @@ TEST_F(SqliteStatement, GetTupleRangeWithTransactionInForRangeLoopWithContinue) using Tuple = std::tuple; ReadStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database); std::vector values; + database.unlock(); for (auto value : statement.rangeWithTransaction()) { if (value == Tuple{"foo", 23.3, 2}) @@ -771,6 +791,7 @@ TEST_F(SqliteStatement, GetTupleRangeWithTransactionInForRangeLoopWithContinue) } ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"poo", 40.0, 3})); + database.lock(); } TEST_F(SqliteStatement, GetSingleValuesWithoutArguments) @@ -795,11 +816,13 @@ TEST_F(SqliteStatement, GetSingleRangeWithoutArguments) TEST_F(SqliteStatement, GetSingleRangeWithTransactionWithoutArguments) { ReadStatement<1> statement("SELECT name FROM test", database); + database.unlock(); - auto range = statement.rangeWithTransaction(); - std::vector values{range.begin(), range.end()}; + std::vector values = toValues( + statement.rangeWithTransaction()); ASSERT_THAT(values, UnorderedElementsAre("bar", "foo", "poo")); + database.lock(); } class FooValue @@ -843,11 +866,12 @@ TEST_F(SqliteStatement, GetSingleSqliteRangeWithTransactionWithoutArguments) { ReadStatement<1> statement("SELECT number FROM test", database); database.execute("INSERT INTO test VALUES (NULL, NULL, NULL)"); + database.unlock(); - auto range = statement.rangeWithTransaction(); - std::vector values{range.begin(), range.end()}; + std::vector values = toValues(statement.rangeWithTransaction()); ASSERT_THAT(values, UnorderedElementsAre(Eq("blah"), Eq(23.3), Eq(40), IsNull())); + database.lock(); } TEST_F(SqliteStatement, GetStructValuesWithoutArguments) @@ -878,14 +902,15 @@ TEST_F(SqliteStatement, GetStructRangeWithoutArguments) TEST_F(SqliteStatement, GetStructRangeWithTransactionWithoutArguments) { ReadStatement<3> statement("SELECT name, number, value FROM test", database); + database.unlock(); - auto range = statement.rangeWithTransaction(); - std::vector values{range.begin(), range.end()}; + std::vector values = toValues(statement.rangeWithTransaction()); ASSERT_THAT(values, UnorderedElementsAre(Output{"bar", "blah", 1}, Output{"foo", "23.3", 2}, Output{"poo", "40", 3})); + database.lock(); } TEST_F(SqliteStatement, GetValuesForSingleOutputWithBindingMultipleTimes) @@ -913,11 +938,13 @@ TEST_F(SqliteStatement, GetRangeWithTransactionForSingleOutputWithBindingMultipl { ReadStatement<1> statement("SELECT name FROM test WHERE number=?", database); statement.values(3, 40); + database.unlock(); - auto range = statement.rangeWithTransaction(40); - std::vector values{range.begin(), range.end()}; + std::vector values = toValues( + statement.rangeWithTransaction(40)); ASSERT_THAT(values, ElementsAre("poo")); + database.lock(); } TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndMultipleQueryValue) @@ -948,11 +975,12 @@ TEST_F(SqliteStatement, GetRangeWithTransactionForMultipleOutputValuesAndMultipl using Tuple = std::tuple; ReadStatement<3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); + database.unlock(); - auto range = statement.rangeWithTransaction("bar", "blah", 1); - std::vector values{range.begin(), range.end()}; + std::vector values = toValues(statement.rangeWithTransaction("bar", "blah", 1)); ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1})); + database.lock(); } TEST_F(SqliteStatement, CallGetValuesForMultipleOutputValuesAndMultipleQueryValueMultipleTimes) @@ -989,15 +1017,13 @@ TEST_F(SqliteStatement, using Tuple = std::tuple; ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", database); - { - auto range = statement.rangeWithTransaction("bar", "blah"); - std::vector values1{range.begin(), range.end()}; - } + database.unlock(); + std::vector values1 = toValues(statement.rangeWithTransaction("bar", "blah")); - auto range2 = statement.rangeWithTransaction("bar", "blah"); - std::vector values{range2.begin(), range2.end()}; + std::vector values = toValues(statement.rangeWithTransaction("bar", "blah")); ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1})); + database.lock(); } TEST_F(SqliteStatement, GetStructOutputValuesAndMultipleQueryValue) @@ -1083,7 +1109,7 @@ TEST_F(SqliteStatement, GetOptionalTupleValueAndMultipleQueryValue) TEST_F(SqliteStatement, GetOptionalValueCallsReset) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1092,7 +1118,7 @@ TEST_F(SqliteStatement, GetOptionalValueCallsReset) TEST_F(SqliteStatement, GetOptionalValueCallsResetIfExceptionIsThrown) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); @@ -1102,7 +1128,7 @@ TEST_F(SqliteStatement, GetOptionalValueCallsResetIfExceptionIsThrown) TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsReset) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1111,7 +1137,7 @@ TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsReset) TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsReset) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1121,7 +1147,6 @@ TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsReset) TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCalls) { InSequence s; - SqliteDatabaseMock databaseMock; MockSqliteStatement mockStatement{databaseMock}; EXPECT_CALL(databaseMock, lock()); @@ -1135,7 +1160,7 @@ TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCalls) TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsResetIfExceptionIsThrown) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); @@ -1145,7 +1170,7 @@ TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsResetIfExceptionIsThrown) TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsResetIfExceptionIsThrown) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); auto range = mockStatement.range(); @@ -1157,7 +1182,6 @@ TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsResetIfExceptionIsThrown) TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCallsResetIfExceptionIsThrown) { InSequence s; - SqliteDatabaseMock databaseMock; MockSqliteStatement mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); @@ -1177,7 +1201,7 @@ TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCallsResetIfExcep TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsReset) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1186,7 +1210,7 @@ TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsReset) TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsResetIfExceptionIsThrown) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); @@ -1196,7 +1220,7 @@ TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsResetIfExceptionIsThrow TEST_F(SqliteStatement, ResetIfWriteIsThrowingException) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; EXPECT_CALL(mockStatement, bind(1, TypedEq("bar"))) .WillOnce(Throw(Sqlite::StatementIsBusy(""))); @@ -1207,7 +1231,7 @@ TEST_F(SqliteStatement, ResetIfWriteIsThrowingException) TEST_F(SqliteStatement, ResetIfExecuteThrowsException) { - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; EXPECT_CALL(mockStatement, next()).WillOnce(Throw(Sqlite::StatementIsBusy(""))); EXPECT_CALL(mockStatement, reset()); @@ -1268,7 +1292,7 @@ TEST_F(SqliteStatement, ReadCallbackAborts) TEST_F(SqliteStatement, ReadCallbackCallsResetAfterCallbacks) { MockFunction callbackMock; - MockSqliteStatement<2> mockStatement; + MockSqliteStatement<2> mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1278,7 +1302,7 @@ TEST_F(SqliteStatement, ReadCallbackCallsResetAfterCallbacks) TEST_F(SqliteStatement, ReadCallbackCallsResetAfterCallbacksAborts) { MockFunction callbackMock; - MockSqliteStatement<2> mockStatement; + MockSqliteStatement<2> mockStatement{databaseMock}; ON_CALL(callbackMock, Call(_, _)).WillByDefault(Return(Sqlite::CallbackControl::Abort)); EXPECT_CALL(mockStatement, reset()); @@ -1289,7 +1313,7 @@ TEST_F(SqliteStatement, ReadCallbackCallsResetAfterCallbacksAborts) TEST_F(SqliteStatement, ReadCallbackThrowsForError) { MockFunction callbackMock; - MockSqliteStatement<2> mockStatement; + MockSqliteStatement<2> mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ASSERT_THROW(mockStatement.readCallback(callbackMock.AsStdFunction()), Sqlite::StatementHasError); @@ -1298,7 +1322,7 @@ TEST_F(SqliteStatement, ReadCallbackThrowsForError) TEST_F(SqliteStatement, ReadCallbackCallsResetIfExceptionIsThrown) { MockFunction callbackMock; - MockSqliteStatement<2> mockStatement; + MockSqliteStatement<2> mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); @@ -1329,7 +1353,7 @@ TEST_F(SqliteStatement, ReadToContainerCallCallbackWithArguments) TEST_F(SqliteStatement, ReadToCallsResetAfterPushingAllValuesBack) { std::deque values; - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1339,7 +1363,7 @@ TEST_F(SqliteStatement, ReadToCallsResetAfterPushingAllValuesBack) TEST_F(SqliteStatement, ReadToThrowsForError) { std::deque values; - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ASSERT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError); @@ -1348,7 +1372,7 @@ TEST_F(SqliteStatement, ReadToThrowsForError) TEST_F(SqliteStatement, ReadToCallsResetIfExceptionIsThrown) { std::deque values; - MockSqliteStatement mockStatement; + MockSqliteStatement mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); diff --git a/tests/unit/unittest/symbolquery-test.cpp b/tests/unit/unittest/symbolquery-test.cpp index e01891fa331..8484e827167 100644 --- a/tests/unit/unittest/symbolquery-test.cpp +++ b/tests/unit/unittest/symbolquery-test.cpp @@ -75,7 +75,7 @@ protected: class SymbolQuerySlowTest : public testing::Test { protected: - void SetUp() override + SymbolQuerySlowTest() { database.execute("INSERT INTO sources VALUES (1, 1, 'filename.h')"); database.execute("INSERT INTO sources VALUES (2, 1, 'filename.cpp')"); @@ -94,6 +94,7 @@ protected: protected: Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; + std::lock_guard lock{database}; RealStatementFactory realStatementFactory{database}; RealQuery query{realStatementFactory}; };