1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/test/test_asyncStatementExecution_transaction.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,509 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +#include "storage_test_harness.h" 1.8 + 1.9 +#include "nsIEventTarget.h" 1.10 +#include "mozStorageConnection.h" 1.11 + 1.12 +#include "sqlite3.h" 1.13 + 1.14 +using namespace mozilla; 1.15 +using namespace mozilla::storage; 1.16 + 1.17 +//////////////////////////////////////////////////////////////////////////////// 1.18 +//// Helpers 1.19 + 1.20 +/** 1.21 + * Commit hook to detect transactions. 1.22 + * 1.23 + * @param aArg 1.24 + * An integer pointer that will be incremented for each commit. 1.25 + */ 1.26 +int commit_hook(void *aArg) 1.27 +{ 1.28 + int *arg = static_cast<int *>(aArg); 1.29 + (*arg)++; 1.30 + return 0; 1.31 +} 1.32 + 1.33 +/** 1.34 + * Executes the passed-in statements and checks if a transaction is created. 1.35 + * When done statements are finalized and database connection is closed. 1.36 + * 1.37 + * @param aDB 1.38 + * The database connection. 1.39 + * @param aStmts 1.40 + * Vector of statements. 1.41 + * @param aStmtsLen 1.42 + * Number of statements. 1.43 + * @param aTransactionExpected 1.44 + * Whether a transaction is expected or not. 1.45 + */ 1.46 +void 1.47 +check_transaction(mozIStorageConnection *aDB, 1.48 + mozIStorageBaseStatement **aStmts, 1.49 + uint32_t aStmtsLen, 1.50 + bool aTransactionExpected) 1.51 +{ 1.52 + // -- install a transaction commit hook. 1.53 + int commit = 0; 1.54 + static_cast<Connection *>(aDB)->setCommitHook(commit_hook, &commit); 1.55 + 1.56 + nsRefPtr<AsyncStatementSpinner> asyncSpin(new AsyncStatementSpinner()); 1.57 + nsCOMPtr<mozIStoragePendingStatement> asyncPend; 1.58 + do_check_success(aDB->ExecuteAsync(aStmts, aStmtsLen, asyncSpin, 1.59 + getter_AddRefs(asyncPend))); 1.60 + do_check_true(asyncPend); 1.61 + 1.62 + // -- complete the execution 1.63 + asyncSpin->SpinUntilCompleted(); 1.64 + 1.65 + // -- uninstall the transaction commit hook. 1.66 + static_cast<Connection *>(aDB)->setCommitHook(nullptr); 1.67 + 1.68 + // -- check transaction 1.69 + do_check_eq(aTransactionExpected, !!commit); 1.70 + 1.71 + // -- check that only one transaction was created. 1.72 + if (aTransactionExpected) { 1.73 + do_check_eq(1, commit); 1.74 + } 1.75 + 1.76 + // -- cleanup 1.77 + for (uint32_t i = 0; i < aStmtsLen; ++i) { 1.78 + aStmts[i]->Finalize(); 1.79 + } 1.80 + blocking_async_close(aDB); 1.81 +} 1.82 + 1.83 +//////////////////////////////////////////////////////////////////////////////// 1.84 +//// Tests 1.85 + 1.86 +/** 1.87 + * Test that executing multiple readonly AsyncStatements doesn't create a 1.88 + * transaction. 1.89 + */ 1.90 +void 1.91 +test_MultipleAsyncReadStatements() 1.92 +{ 1.93 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.94 + 1.95 + // -- create statements and execute them 1.96 + nsCOMPtr<mozIStorageAsyncStatement> stmt1; 1.97 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.98 + "SELECT * FROM sqlite_master" 1.99 + ), getter_AddRefs(stmt1)); 1.100 + 1.101 + nsCOMPtr<mozIStorageAsyncStatement> stmt2; 1.102 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.103 + "SELECT * FROM sqlite_master" 1.104 + ), getter_AddRefs(stmt2)); 1.105 + 1.106 + mozIStorageBaseStatement *stmts[] = { 1.107 + stmt1, 1.108 + stmt2, 1.109 + }; 1.110 + 1.111 + check_transaction(db, stmts, ArrayLength(stmts), false); 1.112 +} 1.113 + 1.114 +/** 1.115 + * Test that executing multiple readonly Statements doesn't create a 1.116 + * transaction. 1.117 + */ 1.118 +void 1.119 +test_MultipleReadStatements() 1.120 +{ 1.121 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.122 + 1.123 + // -- create statements and execute them 1.124 + nsCOMPtr<mozIStorageStatement> stmt1; 1.125 + db->CreateStatement(NS_LITERAL_CSTRING( 1.126 + "SELECT * FROM sqlite_master" 1.127 + ), getter_AddRefs(stmt1)); 1.128 + 1.129 + nsCOMPtr<mozIStorageStatement> stmt2; 1.130 + db->CreateStatement(NS_LITERAL_CSTRING( 1.131 + "SELECT * FROM sqlite_master" 1.132 + ), getter_AddRefs(stmt2)); 1.133 + 1.134 + mozIStorageBaseStatement *stmts[] = { 1.135 + stmt1, 1.136 + stmt2, 1.137 + }; 1.138 + 1.139 + check_transaction(db, stmts, ArrayLength(stmts), false); 1.140 +} 1.141 + 1.142 +/** 1.143 + * Test that executing multiple AsyncStatements causing writes creates a 1.144 + * transaction. 1.145 + */ 1.146 +void 1.147 +test_MultipleAsyncReadWriteStatements() 1.148 +{ 1.149 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.150 + 1.151 + // -- create statements and execute them 1.152 + nsCOMPtr<mozIStorageAsyncStatement> stmt1; 1.153 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.154 + "SELECT * FROM sqlite_master" 1.155 + ), getter_AddRefs(stmt1)); 1.156 + 1.157 + nsCOMPtr<mozIStorageAsyncStatement> stmt2; 1.158 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.159 + "CREATE TABLE test (id INTEGER PRIMARY KEY)" 1.160 + ), getter_AddRefs(stmt2)); 1.161 + 1.162 + mozIStorageBaseStatement *stmts[] = { 1.163 + stmt1, 1.164 + stmt2, 1.165 + }; 1.166 + 1.167 + check_transaction(db, stmts, ArrayLength(stmts), true); 1.168 +} 1.169 + 1.170 +/** 1.171 + * Test that executing multiple Statements causing writes creates a transaction. 1.172 + */ 1.173 +void 1.174 +test_MultipleReadWriteStatements() 1.175 +{ 1.176 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.177 + 1.178 + // -- create statements and execute them 1.179 + nsCOMPtr<mozIStorageStatement> stmt1; 1.180 + db->CreateStatement(NS_LITERAL_CSTRING( 1.181 + "SELECT * FROM sqlite_master" 1.182 + ), getter_AddRefs(stmt1)); 1.183 + 1.184 + nsCOMPtr<mozIStorageStatement> stmt2; 1.185 + db->CreateStatement(NS_LITERAL_CSTRING( 1.186 + "CREATE TABLE test (id INTEGER PRIMARY KEY)" 1.187 + ), getter_AddRefs(stmt2)); 1.188 + 1.189 + mozIStorageBaseStatement *stmts[] = { 1.190 + stmt1, 1.191 + stmt2, 1.192 + }; 1.193 + 1.194 + check_transaction(db, stmts, ArrayLength(stmts), true); 1.195 +} 1.196 + 1.197 +/** 1.198 + * Test that executing multiple AsyncStatements causing writes creates a 1.199 + * single transaction. 1.200 + */ 1.201 +void 1.202 +test_MultipleAsyncWriteStatements() 1.203 +{ 1.204 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.205 + 1.206 + // -- create statements and execute them 1.207 + nsCOMPtr<mozIStorageAsyncStatement> stmt1; 1.208 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.209 + "CREATE TABLE test1 (id INTEGER PRIMARY KEY)" 1.210 + ), getter_AddRefs(stmt1)); 1.211 + 1.212 + nsCOMPtr<mozIStorageAsyncStatement> stmt2; 1.213 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.214 + "CREATE TABLE test2 (id INTEGER PRIMARY KEY)" 1.215 + ), getter_AddRefs(stmt2)); 1.216 + 1.217 + mozIStorageBaseStatement *stmts[] = { 1.218 + stmt1, 1.219 + stmt2, 1.220 + }; 1.221 + 1.222 + check_transaction(db, stmts, ArrayLength(stmts), true); 1.223 +} 1.224 + 1.225 +/** 1.226 + * Test that executing multiple Statements causing writes creates a 1.227 + * single transaction. 1.228 + */ 1.229 +void 1.230 +test_MultipleWriteStatements() 1.231 +{ 1.232 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.233 + 1.234 + // -- create statements and execute them 1.235 + nsCOMPtr<mozIStorageStatement> stmt1; 1.236 + db->CreateStatement(NS_LITERAL_CSTRING( 1.237 + "CREATE TABLE test1 (id INTEGER PRIMARY KEY)" 1.238 + ), getter_AddRefs(stmt1)); 1.239 + 1.240 + nsCOMPtr<mozIStorageStatement> stmt2; 1.241 + db->CreateStatement(NS_LITERAL_CSTRING( 1.242 + "CREATE TABLE test2 (id INTEGER PRIMARY KEY)" 1.243 + ), getter_AddRefs(stmt2)); 1.244 + 1.245 + mozIStorageBaseStatement *stmts[] = { 1.246 + stmt1, 1.247 + stmt2, 1.248 + }; 1.249 + 1.250 + check_transaction(db, stmts, ArrayLength(stmts), true); 1.251 +} 1.252 + 1.253 +/** 1.254 + * Test that executing a single read-only AsyncStatement doesn't create a 1.255 + * transaction. 1.256 + */ 1.257 +void 1.258 +test_SingleAsyncReadStatement() 1.259 +{ 1.260 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.261 + 1.262 + // -- create statements and execute them 1.263 + nsCOMPtr<mozIStorageAsyncStatement> stmt; 1.264 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.265 + "SELECT * FROM sqlite_master" 1.266 + ), getter_AddRefs(stmt)); 1.267 + 1.268 + mozIStorageBaseStatement *stmts[] = { 1.269 + stmt, 1.270 + }; 1.271 + 1.272 + check_transaction(db, stmts, ArrayLength(stmts), false); 1.273 +} 1.274 + 1.275 +/** 1.276 + * Test that executing a single read-only Statement doesn't create a 1.277 + * transaction. 1.278 + */ 1.279 +void 1.280 +test_SingleReadStatement() 1.281 +{ 1.282 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.283 + 1.284 + // -- create statements and execute them 1.285 + nsCOMPtr<mozIStorageStatement> stmt; 1.286 + db->CreateStatement(NS_LITERAL_CSTRING( 1.287 + "SELECT * FROM sqlite_master" 1.288 + ), getter_AddRefs(stmt)); 1.289 + 1.290 + mozIStorageBaseStatement *stmts[] = { 1.291 + stmt, 1.292 + }; 1.293 + 1.294 + check_transaction(db, stmts, ArrayLength(stmts), false); 1.295 +} 1.296 + 1.297 +/** 1.298 + * Test that executing a single AsyncStatement causing writes creates a 1.299 + * transaction. 1.300 + */ 1.301 +void 1.302 +test_SingleAsyncWriteStatement() 1.303 +{ 1.304 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.305 + 1.306 + // -- create statements and execute them 1.307 + nsCOMPtr<mozIStorageAsyncStatement> stmt; 1.308 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.309 + "CREATE TABLE test (id INTEGER PRIMARY KEY)" 1.310 + ), getter_AddRefs(stmt)); 1.311 + 1.312 + mozIStorageBaseStatement *stmts[] = { 1.313 + stmt, 1.314 + }; 1.315 + 1.316 + check_transaction(db, stmts, ArrayLength(stmts), true); 1.317 +} 1.318 + 1.319 +/** 1.320 + * Test that executing a single Statement causing writes creates a transaction. 1.321 + */ 1.322 +void 1.323 +test_SingleWriteStatement() 1.324 +{ 1.325 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.326 + 1.327 + // -- create statements and execute them 1.328 + nsCOMPtr<mozIStorageStatement> stmt; 1.329 + db->CreateStatement(NS_LITERAL_CSTRING( 1.330 + "CREATE TABLE test (id INTEGER PRIMARY KEY)" 1.331 + ), getter_AddRefs(stmt)); 1.332 + 1.333 + mozIStorageBaseStatement *stmts[] = { 1.334 + stmt, 1.335 + }; 1.336 + 1.337 + check_transaction(db, stmts, ArrayLength(stmts), true); 1.338 +} 1.339 + 1.340 +/** 1.341 + * Test that executing a single read-only AsyncStatement with multiple params 1.342 + * doesn't create a transaction. 1.343 + */ 1.344 +void 1.345 +test_MultipleParamsAsyncReadStatement() 1.346 +{ 1.347 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.348 + 1.349 + // -- create statements and execute them 1.350 + nsCOMPtr<mozIStorageAsyncStatement> stmt; 1.351 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.352 + "SELECT :param FROM sqlite_master" 1.353 + ), getter_AddRefs(stmt)); 1.354 + 1.355 + // -- bind multiple BindingParams 1.356 + nsCOMPtr<mozIStorageBindingParamsArray> paramsArray; 1.357 + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); 1.358 + for (int32_t i = 0; i < 2; i++) { 1.359 + nsCOMPtr<mozIStorageBindingParams> params; 1.360 + paramsArray->NewBindingParams(getter_AddRefs(params)); 1.361 + params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1); 1.362 + paramsArray->AddParams(params); 1.363 + } 1.364 + stmt->BindParameters(paramsArray); 1.365 + paramsArray = nullptr; 1.366 + 1.367 + mozIStorageBaseStatement *stmts[] = { 1.368 + stmt, 1.369 + }; 1.370 + 1.371 + check_transaction(db, stmts, ArrayLength(stmts), false); 1.372 +} 1.373 + 1.374 +/** 1.375 + * Test that executing a single read-only Statement with multiple params 1.376 + * doesn't create a transaction. 1.377 + */ 1.378 +void 1.379 +test_MultipleParamsReadStatement() 1.380 +{ 1.381 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.382 + 1.383 + // -- create statements and execute them 1.384 + nsCOMPtr<mozIStorageStatement> stmt; 1.385 + db->CreateStatement(NS_LITERAL_CSTRING( 1.386 + "SELECT :param FROM sqlite_master" 1.387 + ), getter_AddRefs(stmt)); 1.388 + 1.389 + // -- bind multiple BindingParams 1.390 + nsCOMPtr<mozIStorageBindingParamsArray> paramsArray; 1.391 + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); 1.392 + for (int32_t i = 0; i < 2; i++) { 1.393 + nsCOMPtr<mozIStorageBindingParams> params; 1.394 + paramsArray->NewBindingParams(getter_AddRefs(params)); 1.395 + params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1); 1.396 + paramsArray->AddParams(params); 1.397 + } 1.398 + stmt->BindParameters(paramsArray); 1.399 + paramsArray = nullptr; 1.400 + 1.401 + mozIStorageBaseStatement *stmts[] = { 1.402 + stmt, 1.403 + }; 1.404 + 1.405 + check_transaction(db, stmts, ArrayLength(stmts), false); 1.406 +} 1.407 + 1.408 +/** 1.409 + * Test that executing a single write AsyncStatement with multiple params 1.410 + * creates a transaction. 1.411 + */ 1.412 +void 1.413 +test_MultipleParamsAsyncWriteStatement() 1.414 +{ 1.415 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.416 + 1.417 + // -- create a table for writes 1.418 + nsCOMPtr<mozIStorageStatement> tableStmt; 1.419 + db->CreateStatement(NS_LITERAL_CSTRING( 1.420 + "CREATE TABLE test (id INTEGER PRIMARY KEY)" 1.421 + ), getter_AddRefs(tableStmt)); 1.422 + tableStmt->Execute(); 1.423 + tableStmt->Finalize(); 1.424 + 1.425 + // -- create statements and execute them 1.426 + nsCOMPtr<mozIStorageAsyncStatement> stmt; 1.427 + db->CreateAsyncStatement(NS_LITERAL_CSTRING( 1.428 + "DELETE FROM test WHERE id = :param" 1.429 + ), getter_AddRefs(stmt)); 1.430 + 1.431 + // -- bind multiple BindingParams 1.432 + nsCOMPtr<mozIStorageBindingParamsArray> paramsArray; 1.433 + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); 1.434 + for (int32_t i = 0; i < 2; i++) { 1.435 + nsCOMPtr<mozIStorageBindingParams> params; 1.436 + paramsArray->NewBindingParams(getter_AddRefs(params)); 1.437 + params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1); 1.438 + paramsArray->AddParams(params); 1.439 + } 1.440 + stmt->BindParameters(paramsArray); 1.441 + paramsArray = nullptr; 1.442 + 1.443 + mozIStorageBaseStatement *stmts[] = { 1.444 + stmt, 1.445 + }; 1.446 + 1.447 + check_transaction(db, stmts, ArrayLength(stmts), true); 1.448 +} 1.449 + 1.450 +/** 1.451 + * Test that executing a single write Statement with multiple params 1.452 + * creates a transaction. 1.453 + */ 1.454 +void 1.455 +test_MultipleParamsWriteStatement() 1.456 +{ 1.457 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.458 + 1.459 + // -- create a table for writes 1.460 + nsCOMPtr<mozIStorageStatement> tableStmt; 1.461 + db->CreateStatement(NS_LITERAL_CSTRING( 1.462 + "CREATE TABLE test (id INTEGER PRIMARY KEY)" 1.463 + ), getter_AddRefs(tableStmt)); 1.464 + tableStmt->Execute(); 1.465 + tableStmt->Finalize(); 1.466 + 1.467 + // -- create statements and execute them 1.468 + nsCOMPtr<mozIStorageStatement> stmt; 1.469 + db->CreateStatement(NS_LITERAL_CSTRING( 1.470 + "DELETE FROM test WHERE id = :param" 1.471 + ), getter_AddRefs(stmt)); 1.472 + 1.473 + // -- bind multiple BindingParams 1.474 + nsCOMPtr<mozIStorageBindingParamsArray> paramsArray; 1.475 + stmt->NewBindingParamsArray(getter_AddRefs(paramsArray)); 1.476 + for (int32_t i = 0; i < 2; i++) { 1.477 + nsCOMPtr<mozIStorageBindingParams> params; 1.478 + paramsArray->NewBindingParams(getter_AddRefs(params)); 1.479 + params->BindInt32ByName(NS_LITERAL_CSTRING("param"), 1); 1.480 + paramsArray->AddParams(params); 1.481 + } 1.482 + stmt->BindParameters(paramsArray); 1.483 + paramsArray = nullptr; 1.484 + 1.485 + mozIStorageBaseStatement *stmts[] = { 1.486 + stmt, 1.487 + }; 1.488 + 1.489 + check_transaction(db, stmts, ArrayLength(stmts), true); 1.490 +} 1.491 + 1.492 +void (*gTests[])(void) = { 1.493 + test_MultipleAsyncReadStatements, 1.494 + test_MultipleReadStatements, 1.495 + test_MultipleAsyncReadWriteStatements, 1.496 + test_MultipleReadWriteStatements, 1.497 + test_MultipleAsyncWriteStatements, 1.498 + test_MultipleWriteStatements, 1.499 + test_SingleAsyncReadStatement, 1.500 + test_SingleReadStatement, 1.501 + test_SingleAsyncWriteStatement, 1.502 + test_SingleWriteStatement, 1.503 + test_MultipleParamsAsyncReadStatement, 1.504 + test_MultipleParamsReadStatement, 1.505 + test_MultipleParamsAsyncWriteStatement, 1.506 + test_MultipleParamsWriteStatement, 1.507 +}; 1.508 + 1.509 +const char *file = __FILE__; 1.510 +#define TEST_NAME "async statement execution transaction" 1.511 +#define TEST_FILE file 1.512 +#include "storage_test_harness_tail.h"