diff options
Diffstat (limited to 'storage/test/test_asyncStatementExecution_transaction.cpp')
-rw-r--r-- | storage/test/test_asyncStatementExecution_transaction.cpp | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/storage/test/test_asyncStatementExecution_transaction.cpp b/storage/test/test_asyncStatementExecution_transaction.cpp new file mode 100644 index 000000000..7e94bd80e --- /dev/null +++ b/storage/test/test_asyncStatementExecution_transaction.cpp @@ -0,0 +1,509 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +#include "storage_test_harness.h" + +#include "nsIEventTarget.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<int *>(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, + mozIStorageBaseStatement **aStmts, + uint32_t aStmtsLen, + bool aTransactionExpected) +{ + // -- install a transaction commit hook. + int commit = 0; + static_cast<Connection *>(aDB)->setCommitHook(commit_hook, &commit); + + RefPtr<AsyncStatementSpinner> asyncSpin(new AsyncStatementSpinner()); + nsCOMPtr<mozIStoragePendingStatement> asyncPend; + do_check_success(aDB->ExecuteAsync(aStmts, aStmtsLen, asyncSpin, + getter_AddRefs(asyncPend))); + do_check_true(asyncPend); + + // -- complete the execution + asyncSpin->SpinUntilCompleted(); + + // -- uninstall the transaction commit hook. + static_cast<Connection *>(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 < aStmtsLen; ++i) { + aStmts[i]->Finalize(); + } + blocking_async_close(aDB); +} + +//////////////////////////////////////////////////////////////////////////////// +//// Tests + +/** + * Test that executing multiple readonly AsyncStatements doesn't create a + * transaction. + */ +void +test_MultipleAsyncReadStatements() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageAsyncStatement> stmt1; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "SELECT * FROM sqlite_master" + ), getter_AddRefs(stmt1)); + + nsCOMPtr<mozIStorageAsyncStatement> stmt2; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "SELECT * FROM sqlite_master" + ), getter_AddRefs(stmt2)); + + mozIStorageBaseStatement *stmts[] = { + stmt1, + stmt2, + }; + + check_transaction(db, stmts, ArrayLength(stmts), false); +} + +/** + * Test that executing multiple readonly Statements doesn't create a + * transaction. + */ +void +test_MultipleReadStatements() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageStatement> stmt1; + db->CreateStatement(NS_LITERAL_CSTRING( + "SELECT * FROM sqlite_master" + ), getter_AddRefs(stmt1)); + + nsCOMPtr<mozIStorageStatement> stmt2; + db->CreateStatement(NS_LITERAL_CSTRING( + "SELECT * FROM sqlite_master" + ), getter_AddRefs(stmt2)); + + mozIStorageBaseStatement *stmts[] = { + stmt1, + stmt2, + }; + + check_transaction(db, stmts, ArrayLength(stmts), false); +} + +/** + * Test that executing multiple AsyncStatements causing writes creates a + * transaction. + */ +void +test_MultipleAsyncReadWriteStatements() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageAsyncStatement> stmt1; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "SELECT * FROM sqlite_master" + ), getter_AddRefs(stmt1)); + + nsCOMPtr<mozIStorageAsyncStatement> stmt2; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt2)); + + mozIStorageBaseStatement *stmts[] = { + stmt1, + stmt2, + }; + + check_transaction(db, stmts, ArrayLength(stmts), true); +} + +/** + * Test that executing multiple Statements causing writes creates a transaction. + */ +void +test_MultipleReadWriteStatements() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageStatement> stmt1; + db->CreateStatement(NS_LITERAL_CSTRING( + "SELECT * FROM sqlite_master" + ), getter_AddRefs(stmt1)); + + nsCOMPtr<mozIStorageStatement> stmt2; + db->CreateStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt2)); + + mozIStorageBaseStatement *stmts[] = { + stmt1, + stmt2, + }; + + check_transaction(db, stmts, ArrayLength(stmts), true); +} + +/** + * Test that executing multiple AsyncStatements causing writes creates a + * single transaction. + */ +void +test_MultipleAsyncWriteStatements() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageAsyncStatement> stmt1; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test1 (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt1)); + + nsCOMPtr<mozIStorageAsyncStatement> stmt2; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test2 (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt2)); + + mozIStorageBaseStatement *stmts[] = { + stmt1, + stmt2, + }; + + check_transaction(db, stmts, ArrayLength(stmts), true); +} + +/** + * Test that executing multiple Statements causing writes creates a + * single transaction. + */ +void +test_MultipleWriteStatements() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageStatement> stmt1; + db->CreateStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test1 (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt1)); + + nsCOMPtr<mozIStorageStatement> stmt2; + db->CreateStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test2 (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt2)); + + mozIStorageBaseStatement *stmts[] = { + stmt1, + stmt2, + }; + + check_transaction(db, stmts, ArrayLength(stmts), true); +} + +/** + * Test that executing a single read-only AsyncStatement doesn't create a + * transaction. + */ +void +test_SingleAsyncReadStatement() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageAsyncStatement> stmt; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "SELECT * FROM sqlite_master" + ), getter_AddRefs(stmt)); + + mozIStorageBaseStatement *stmts[] = { + stmt, + }; + + check_transaction(db, stmts, ArrayLength(stmts), false); +} + +/** + * Test that executing a single read-only Statement doesn't create a + * transaction. + */ +void +test_SingleReadStatement() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageStatement> stmt; + db->CreateStatement(NS_LITERAL_CSTRING( + "SELECT * FROM sqlite_master" + ), getter_AddRefs(stmt)); + + mozIStorageBaseStatement *stmts[] = { + stmt, + }; + + check_transaction(db, stmts, ArrayLength(stmts), false); +} + +/** + * Test that executing a single AsyncStatement causing writes creates a + * transaction. + */ +void +test_SingleAsyncWriteStatement() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageAsyncStatement> stmt; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt)); + + mozIStorageBaseStatement *stmts[] = { + stmt, + }; + + check_transaction(db, stmts, ArrayLength(stmts), true); +} + +/** + * Test that executing a single Statement causing writes creates a transaction. + */ +void +test_SingleWriteStatement() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageStatement> stmt; + db->CreateStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(stmt)); + + mozIStorageBaseStatement *stmts[] = { + stmt, + }; + + check_transaction(db, stmts, ArrayLength(stmts), true); +} + +/** + * Test that executing a single read-only AsyncStatement with multiple params + * doesn't create a transaction. + */ +void +test_MultipleParamsAsyncReadStatement() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageAsyncStatement> stmt; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "SELECT :param FROM sqlite_master" + ), getter_AddRefs(stmt)); + + // -- bind multiple BindingParams + nsCOMPtr<mozIStorageBindingParamsArray> paramsArray; + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); + for (int32_t i = 0; i < 2; i++) { + nsCOMPtr<mozIStorageBindingParams> params; + paramsArray->NewBindingParams(getter_AddRefs(params)); + params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1); + paramsArray->AddParams(params); + } + stmt->BindParameters(paramsArray); + paramsArray = nullptr; + + mozIStorageBaseStatement *stmts[] = { + stmt, + }; + + check_transaction(db, stmts, ArrayLength(stmts), false); +} + +/** + * Test that executing a single read-only Statement with multiple params + * doesn't create a transaction. + */ +void +test_MultipleParamsReadStatement() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create statements and execute them + nsCOMPtr<mozIStorageStatement> stmt; + db->CreateStatement(NS_LITERAL_CSTRING( + "SELECT :param FROM sqlite_master" + ), getter_AddRefs(stmt)); + + // -- bind multiple BindingParams + nsCOMPtr<mozIStorageBindingParamsArray> paramsArray; + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); + for (int32_t i = 0; i < 2; i++) { + nsCOMPtr<mozIStorageBindingParams> params; + paramsArray->NewBindingParams(getter_AddRefs(params)); + params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1); + paramsArray->AddParams(params); + } + stmt->BindParameters(paramsArray); + paramsArray = nullptr; + + mozIStorageBaseStatement *stmts[] = { + stmt, + }; + + check_transaction(db, stmts, ArrayLength(stmts), false); +} + +/** + * Test that executing a single write AsyncStatement with multiple params + * creates a transaction. + */ +void +test_MultipleParamsAsyncWriteStatement() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create a table for writes + nsCOMPtr<mozIStorageStatement> tableStmt; + db->CreateStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(tableStmt)); + tableStmt->Execute(); + tableStmt->Finalize(); + + // -- create statements and execute them + nsCOMPtr<mozIStorageAsyncStatement> stmt; + db->CreateAsyncStatement(NS_LITERAL_CSTRING( + "DELETE FROM test WHERE id = :param" + ), getter_AddRefs(stmt)); + + // -- bind multiple BindingParams + nsCOMPtr<mozIStorageBindingParamsArray> paramsArray; + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); + for (int32_t i = 0; i < 2; i++) { + nsCOMPtr<mozIStorageBindingParams> params; + paramsArray->NewBindingParams(getter_AddRefs(params)); + params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1); + paramsArray->AddParams(params); + } + stmt->BindParameters(paramsArray); + paramsArray = nullptr; + + mozIStorageBaseStatement *stmts[] = { + stmt, + }; + + check_transaction(db, stmts, ArrayLength(stmts), true); +} + +/** + * Test that executing a single write Statement with multiple params + * creates a transaction. + */ +void +test_MultipleParamsWriteStatement() +{ + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); + + // -- create a table for writes + nsCOMPtr<mozIStorageStatement> tableStmt; + db->CreateStatement(NS_LITERAL_CSTRING( + "CREATE TABLE test (id INTEGER PRIMARY KEY)" + ), getter_AddRefs(tableStmt)); + tableStmt->Execute(); + tableStmt->Finalize(); + + // -- create statements and execute them + nsCOMPtr<mozIStorageStatement> stmt; + db->CreateStatement(NS_LITERAL_CSTRING( + "DELETE FROM test WHERE id = :param" + ), getter_AddRefs(stmt)); + + // -- bind multiple BindingParams + nsCOMPtr<mozIStorageBindingParamsArray> paramsArray; + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); + for (int32_t i = 0; i < 2; i++) { + nsCOMPtr<mozIStorageBindingParams> params; + paramsArray->NewBindingParams(getter_AddRefs(params)); + params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1); + paramsArray->AddParams(params); + } + stmt->BindParameters(paramsArray); + paramsArray = nullptr; + + mozIStorageBaseStatement *stmts[] = { + stmt, + }; + + check_transaction(db, stmts, ArrayLength(stmts), true); +} + +void (*gTests[])(void) = { + test_MultipleAsyncReadStatements, + test_MultipleReadStatements, + test_MultipleAsyncReadWriteStatements, + test_MultipleReadWriteStatements, + test_MultipleAsyncWriteStatements, + test_MultipleWriteStatements, + test_SingleAsyncReadStatement, + test_SingleReadStatement, + test_SingleAsyncWriteStatement, + test_SingleWriteStatement, + test_MultipleParamsAsyncReadStatement, + test_MultipleParamsReadStatement, + test_MultipleParamsAsyncWriteStatement, + test_MultipleParamsWriteStatement, +}; + +const char *file = __FILE__; +#define TEST_NAME "async statement execution transaction" +#define TEST_FILE file +#include "storage_test_harness_tail.h" |