From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../test_asyncStatementExecution_transaction.cpp | 445 +++++++++++++++++++++ 1 file changed, 445 insertions(+) create mode 100644 storage/test/gtest/test_asyncStatementExecution_transaction.cpp (limited to 'storage/test/gtest/test_asyncStatementExecution_transaction.cpp') diff --git a/storage/test/gtest/test_asyncStatementExecution_transaction.cpp b/storage/test/gtest/test_asyncStatementExecution_transaction.cpp new file mode 100644 index 0000000000..0e7dec1e8a --- /dev/null +++ b/storage/test/gtest/test_asyncStatementExecution_transaction.cpp @@ -0,0 +1,445 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +#include "storage_test_harness.h" + +#include "mozStorageConnection.h" + +#include "sqlite3.h" + +using namespace mozilla; +using namespace mozilla::storage; + +//////////////////////////////////////////////////////////////////////////////// +//// Helpers + +/** + * Commit hook to detect transactions. + * + * @param aArg + * An integer pointer that will be incremented for each commit. + */ +int commit_hook(void* aArg) { + int* arg = static_cast(aArg); + (*arg)++; + return 0; +} + +/** + * Executes the passed-in statements and checks if a transaction is created. + * When done statements are finalized and database connection is closed. + * + * @param aDB + * The database connection. + * @param aStmts + * Vector of statements. + * @param aStmtsLen + * Number of statements. + * @param aTransactionExpected + * Whether a transaction is expected or not. + */ +void check_transaction(mozIStorageConnection* aDB, + const nsTArray>& aStmts, + bool aTransactionExpected) { + // -- install a transaction commit hook. + int commit = 0; + static_cast(aDB)->setCommitHook(commit_hook, &commit); + + RefPtr asyncSpin(new AsyncStatementSpinner()); + nsCOMPtr asyncPend; + do_check_success( + aDB->ExecuteAsync(aStmts, asyncSpin, getter_AddRefs(asyncPend))); + do_check_true(asyncPend); + + // -- complete the execution + asyncSpin->SpinUntilCompleted(); + + // -- uninstall the transaction commit hook. + static_cast(aDB)->setCommitHook(nullptr); + + // -- check transaction + do_check_eq(aTransactionExpected, !!commit); + + // -- check that only one transaction was created. + if (aTransactionExpected) { + do_check_eq(1, commit); + } + + // -- cleanup + for (uint32_t i = 0; i < aStmts.Length(); ++i) { + aStmts[i]->Finalize(); + } + blocking_async_close(aDB); +} + +//////////////////////////////////////////////////////////////////////////////// +//// Tests + +/** + * Test that executing multiple readonly AsyncStatements doesn't create a + * transaction. + */ +TEST(storage_asyncStatementExecution_transaction, MultipleAsyncReadStatements) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt1; + db->CreateAsyncStatement("SELECT * FROM sqlite_master"_ns, + getter_AddRefs(stmt1)); + + nsCOMPtr stmt2; + db->CreateAsyncStatement("SELECT * FROM sqlite_master"_ns, + getter_AddRefs(stmt2)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt1)), + ToRefPtr(std::move(stmt2)), + }; + + check_transaction(db, stmts.Clone(), false); +} + +/** + * Test that executing multiple readonly Statements doesn't create a + * transaction. + */ +TEST(storage_asyncStatementExecution_transaction, MultipleReadStatements) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt1; + db->CreateStatement("SELECT * FROM sqlite_master"_ns, getter_AddRefs(stmt1)); + + nsCOMPtr stmt2; + db->CreateStatement("SELECT * FROM sqlite_master"_ns, getter_AddRefs(stmt2)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt1)), + ToRefPtr(std::move(stmt2)), + }; + + check_transaction(db, stmts, false); +} + +/** + * Test that executing multiple AsyncStatements causing writes creates a + * transaction. + */ +TEST(storage_asyncStatementExecution_transaction, + MultipleAsyncReadWriteStatements) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt1; + db->CreateAsyncStatement("SELECT * FROM sqlite_master"_ns, + getter_AddRefs(stmt1)); + + nsCOMPtr stmt2; + db->CreateAsyncStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(stmt2)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt1)), + ToRefPtr(std::move(stmt2)), + }; + + check_transaction(db, stmts, true); +} + +/** + * Test that executing multiple Statements causing writes creates a transaction. + */ +TEST(storage_asyncStatementExecution_transaction, MultipleReadWriteStatements) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt1; + db->CreateStatement("SELECT * FROM sqlite_master"_ns, getter_AddRefs(stmt1)); + + nsCOMPtr stmt2; + db->CreateStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(stmt2)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt1)), + ToRefPtr(std::move(stmt2)), + }; + + check_transaction(db, stmts, true); +} + +/** + * Test that executing multiple AsyncStatements causing writes creates a + * single transaction. + */ +TEST(storage_asyncStatementExecution_transaction, MultipleAsyncWriteStatements) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt1; + db->CreateAsyncStatement("CREATE TABLE test1 (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(stmt1)); + + nsCOMPtr stmt2; + db->CreateAsyncStatement("CREATE TABLE test2 (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(stmt2)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt1)), + ToRefPtr(std::move(stmt2)), + }; + + check_transaction(db, stmts, true); +} + +/** + * Test that executing multiple Statements causing writes creates a + * single transaction. + */ +TEST(storage_asyncStatementExecution_transaction, MultipleWriteStatements) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt1; + db->CreateStatement("CREATE TABLE test1 (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(stmt1)); + + nsCOMPtr stmt2; + db->CreateStatement("CREATE TABLE test2 (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(stmt2)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt1)), + ToRefPtr(std::move(stmt2)), + }; + + check_transaction(db, stmts, true); +} + +/** + * Test that executing a single read-only AsyncStatement doesn't create a + * transaction. + */ +TEST(storage_asyncStatementExecution_transaction, SingleAsyncReadStatement) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt; + db->CreateAsyncStatement("SELECT * FROM sqlite_master"_ns, + getter_AddRefs(stmt)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt)), + }; + + check_transaction(db, stmts, false); +} + +/** + * Test that executing a single read-only Statement doesn't create a + * transaction. + */ +TEST(storage_asyncStatementExecution_transaction, SingleReadStatement) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt; + db->CreateStatement("SELECT * FROM sqlite_master"_ns, getter_AddRefs(stmt)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt)), + }; + + check_transaction(db, stmts, false); +} + +/** + * Test that executing a single AsyncStatement causing writes creates a + * transaction. + */ +TEST(storage_asyncStatementExecution_transaction, SingleAsyncWriteStatement) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt; + db->CreateAsyncStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(stmt)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt)), + }; + + check_transaction(db, stmts, true); +} + +/** + * Test that executing a single Statement causing writes creates a transaction. + */ +TEST(storage_asyncStatementExecution_transaction, SingleWriteStatement) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt; + db->CreateStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(stmt)); + + nsTArray> stmts = { + ToRefPtr(std::move(stmt)), + }; + + check_transaction(db, stmts, true); +} + +/** + * Test that executing a single read-only AsyncStatement with multiple params + * doesn't create a transaction. + */ +TEST(storage_asyncStatementExecution_transaction, + MultipleParamsAsyncReadStatement) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt; + db->CreateAsyncStatement("SELECT :param FROM sqlite_master"_ns, + getter_AddRefs(stmt)); + + // -- bind multiple BindingParams + nsCOMPtr paramsArray; + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); + for (int32_t i = 0; i < 2; i++) { + nsCOMPtr params; + paramsArray->NewBindingParams(getter_AddRefs(params)); + params->BindInt32ByName("param"_ns, 1); + paramsArray->AddParams(params); + } + stmt->BindParameters(paramsArray); + paramsArray = nullptr; + + nsTArray> stmts = { + ToRefPtr(std::move(stmt)), + }; + + check_transaction(db, stmts, false); +} + +/** + * Test that executing a single read-only Statement with multiple params + * doesn't create a transaction. + */ +TEST(storage_asyncStatementExecution_transaction, MultipleParamsReadStatement) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr stmt; + db->CreateStatement("SELECT :param FROM sqlite_master"_ns, + getter_AddRefs(stmt)); + + // -- bind multiple BindingParams + nsCOMPtr paramsArray; + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); + for (int32_t i = 0; i < 2; i++) { + nsCOMPtr params; + paramsArray->NewBindingParams(getter_AddRefs(params)); + params->BindInt32ByName("param"_ns, 1); + paramsArray->AddParams(params); + } + stmt->BindParameters(paramsArray); + paramsArray = nullptr; + + nsTArray> stmts = { + ToRefPtr(std::move(stmt)), + }; + + check_transaction(db, stmts, false); +} + +/** + * Test that executing a single write AsyncStatement with multiple params + * creates a transaction. + */ +TEST(storage_asyncStatementExecution_transaction, + MultipleParamsAsyncWriteStatement) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create a table for writes + nsCOMPtr tableStmt; + db->CreateStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(tableStmt)); + tableStmt->Execute(); + tableStmt->Finalize(); + + // -- create statements and execute them + nsCOMPtr stmt; + db->CreateAsyncStatement("DELETE FROM test WHERE id = :param"_ns, + getter_AddRefs(stmt)); + + // -- bind multiple BindingParams + nsCOMPtr paramsArray; + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); + for (int32_t i = 0; i < 2; i++) { + nsCOMPtr params; + paramsArray->NewBindingParams(getter_AddRefs(params)); + params->BindInt32ByName("param"_ns, 1); + paramsArray->AddParams(params); + } + stmt->BindParameters(paramsArray); + paramsArray = nullptr; + + nsTArray> stmts = { + ToRefPtr(std::move(stmt)), + }; + + check_transaction(db, stmts, true); +} + +/** + * Test that executing a single write Statement with multiple params + * creates a transaction. + */ +TEST(storage_asyncStatementExecution_transaction, MultipleParamsWriteStatement) +{ + nsCOMPtr db(getMemoryDatabase()); + + // -- create a table for writes + nsCOMPtr tableStmt; + db->CreateStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns, + getter_AddRefs(tableStmt)); + tableStmt->Execute(); + tableStmt->Finalize(); + + // -- create statements and execute them + nsCOMPtr stmt; + db->CreateStatement("DELETE FROM test WHERE id = :param"_ns, + getter_AddRefs(stmt)); + + // -- bind multiple BindingParams + nsCOMPtr paramsArray; + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); + for (int32_t i = 0; i < 2; i++) { + nsCOMPtr params; + paramsArray->NewBindingParams(getter_AddRefs(params)); + params->BindInt32ByName("param"_ns, 1); + paramsArray->AddParams(params); + } + stmt->BindParameters(paramsArray); + paramsArray = nullptr; + + nsTArray> stmts = { + ToRefPtr(std::move(stmt)), + }; + + check_transaction(db, stmts, true); +} -- cgit v1.2.3