1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/test/test_async_callbacks_with_spun_event_loops.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,172 @@ 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 +#include "prthread.h" 1.9 +#include "nsIEventTarget.h" 1.10 +#include "nsIInterfaceRequestorUtils.h" 1.11 +#include "mozilla/Attributes.h" 1.12 + 1.13 +#include "sqlite3.h" 1.14 + 1.15 +//////////////////////////////////////////////////////////////////////////////// 1.16 +//// Async Helpers 1.17 + 1.18 +/** 1.19 + * Spins the events loop for current thread until aCondition is true. 1.20 + */ 1.21 +void 1.22 +spin_events_loop_until_true(const bool* const aCondition) 1.23 +{ 1.24 + nsCOMPtr<nsIThread> thread(::do_GetCurrentThread()); 1.25 + nsresult rv = NS_OK; 1.26 + bool processed = true; 1.27 + while (!(*aCondition) && NS_SUCCEEDED(rv)) { 1.28 + rv = thread->ProcessNextEvent(true, &processed); 1.29 + } 1.30 +} 1.31 + 1.32 +//////////////////////////////////////////////////////////////////////////////// 1.33 +//// mozIStorageStatementCallback implementation 1.34 + 1.35 +class UnownedCallback MOZ_FINAL : public mozIStorageStatementCallback 1.36 +{ 1.37 +public: 1.38 + NS_DECL_ISUPPORTS 1.39 + 1.40 + // Whether the object has been destroyed. 1.41 + static bool sAlive; 1.42 + // Whether the first result was received. 1.43 + static bool sResult; 1.44 + // Whether an error was received. 1.45 + static bool sError; 1.46 + 1.47 + UnownedCallback(mozIStorageConnection* aDBConn) 1.48 + : mDBConn(aDBConn) 1.49 + , mCompleted(false) 1.50 + { 1.51 + sAlive = true; 1.52 + sResult = false; 1.53 + sError = false; 1.54 + } 1.55 + 1.56 + ~UnownedCallback() 1.57 + { 1.58 + sAlive = false; 1.59 + blocking_async_close(mDBConn); 1.60 + } 1.61 + 1.62 + NS_IMETHOD HandleResult(mozIStorageResultSet* aResultSet) 1.63 + { 1.64 + sResult = true; 1.65 + spin_events_loop_until_true(&mCompleted); 1.66 + if (!sAlive) { 1.67 + NS_RUNTIMEABORT("The statement callback was destroyed prematurely."); 1.68 + } 1.69 + return NS_OK; 1.70 + } 1.71 + 1.72 + NS_IMETHOD HandleError(mozIStorageError* aError) 1.73 + { 1.74 + sError = true; 1.75 + spin_events_loop_until_true(&mCompleted); 1.76 + if (!sAlive) { 1.77 + NS_RUNTIMEABORT("The statement callback was destroyed prematurely."); 1.78 + } 1.79 + return NS_OK; 1.80 + } 1.81 + 1.82 + NS_IMETHOD HandleCompletion(uint16_t aReason) 1.83 + { 1.84 + mCompleted = true; 1.85 + return NS_OK; 1.86 + } 1.87 + 1.88 +protected: 1.89 + nsCOMPtr<mozIStorageConnection> mDBConn; 1.90 + bool mCompleted; 1.91 +}; 1.92 + 1.93 +NS_IMPL_ISUPPORTS(UnownedCallback, mozIStorageStatementCallback) 1.94 + 1.95 +bool UnownedCallback::sAlive = false; 1.96 +bool UnownedCallback::sResult = false; 1.97 +bool UnownedCallback::sError = false; 1.98 + 1.99 +//////////////////////////////////////////////////////////////////////////////// 1.100 +//// Tests 1.101 + 1.102 +void 1.103 +test_SpinEventsLoopInHandleResult() 1.104 +{ 1.105 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.106 + 1.107 + // Create a test table and populate it. 1.108 + nsCOMPtr<mozIStorageStatement> stmt; 1.109 + db->CreateStatement(NS_LITERAL_CSTRING( 1.110 + "CREATE TABLE test (id INTEGER PRIMARY KEY)" 1.111 + ), getter_AddRefs(stmt)); 1.112 + stmt->Execute(); 1.113 + stmt->Finalize(); 1.114 + 1.115 + db->CreateStatement(NS_LITERAL_CSTRING( 1.116 + "INSERT INTO test (id) VALUES (?)" 1.117 + ), getter_AddRefs(stmt)); 1.118 + for (int32_t i = 0; i < 30; ++i) { 1.119 + stmt->BindInt32ByIndex(0, i); 1.120 + stmt->Execute(); 1.121 + stmt->Reset(); 1.122 + } 1.123 + stmt->Finalize(); 1.124 + 1.125 + db->CreateStatement(NS_LITERAL_CSTRING( 1.126 + "SELECT * FROM test" 1.127 + ), getter_AddRefs(stmt)); 1.128 + nsCOMPtr<mozIStoragePendingStatement> ps; 1.129 + do_check_success(stmt->ExecuteAsync(new UnownedCallback(db), 1.130 + getter_AddRefs(ps))); 1.131 + stmt->Finalize(); 1.132 + 1.133 + spin_events_loop_until_true(&UnownedCallback::sResult); 1.134 +} 1.135 + 1.136 +void 1.137 +test_SpinEventsLoopInHandleError() 1.138 +{ 1.139 + nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase()); 1.140 + 1.141 + // Create a test table and populate it. 1.142 + nsCOMPtr<mozIStorageStatement> stmt; 1.143 + db->CreateStatement(NS_LITERAL_CSTRING( 1.144 + "CREATE TABLE test (id INTEGER PRIMARY KEY)" 1.145 + ), getter_AddRefs(stmt)); 1.146 + stmt->Execute(); 1.147 + stmt->Finalize(); 1.148 + 1.149 + db->CreateStatement(NS_LITERAL_CSTRING( 1.150 + "INSERT INTO test (id) VALUES (1)" 1.151 + ), getter_AddRefs(stmt)); 1.152 + stmt->Execute(); 1.153 + stmt->Finalize(); 1.154 + 1.155 + // This will cause a constraint error. 1.156 + db->CreateStatement(NS_LITERAL_CSTRING( 1.157 + "INSERT INTO test (id) VALUES (1)" 1.158 + ), getter_AddRefs(stmt)); 1.159 + nsCOMPtr<mozIStoragePendingStatement> ps; 1.160 + do_check_success(stmt->ExecuteAsync(new UnownedCallback(db), 1.161 + getter_AddRefs(ps))); 1.162 + stmt->Finalize(); 1.163 + 1.164 + spin_events_loop_until_true(&UnownedCallback::sError); 1.165 +} 1.166 + 1.167 +void (*gTests[])(void) = { 1.168 + test_SpinEventsLoopInHandleResult, 1.169 + test_SpinEventsLoopInHandleError, 1.170 +}; 1.171 + 1.172 +const char *file = __FILE__; 1.173 +#define TEST_NAME "test async callbacks with spun event loops" 1.174 +#define TEST_FILE file 1.175 +#include "storage_test_harness_tail.h"