Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 #include "storage_test_harness.h"
5 #include "prthread.h"
6 #include "nsIEventTarget.h"
7 #include "nsIInterfaceRequestorUtils.h"
8 #include "mozilla/Attributes.h"
10 #include "sqlite3.h"
12 ////////////////////////////////////////////////////////////////////////////////
13 //// Async Helpers
15 /**
16 * Spins the events loop for current thread until aCondition is true.
17 */
18 void
19 spin_events_loop_until_true(const bool* const aCondition)
20 {
21 nsCOMPtr<nsIThread> thread(::do_GetCurrentThread());
22 nsresult rv = NS_OK;
23 bool processed = true;
24 while (!(*aCondition) && NS_SUCCEEDED(rv)) {
25 rv = thread->ProcessNextEvent(true, &processed);
26 }
27 }
29 ////////////////////////////////////////////////////////////////////////////////
30 //// mozIStorageStatementCallback implementation
32 class UnownedCallback MOZ_FINAL : public mozIStorageStatementCallback
33 {
34 public:
35 NS_DECL_ISUPPORTS
37 // Whether the object has been destroyed.
38 static bool sAlive;
39 // Whether the first result was received.
40 static bool sResult;
41 // Whether an error was received.
42 static bool sError;
44 UnownedCallback(mozIStorageConnection* aDBConn)
45 : mDBConn(aDBConn)
46 , mCompleted(false)
47 {
48 sAlive = true;
49 sResult = false;
50 sError = false;
51 }
53 ~UnownedCallback()
54 {
55 sAlive = false;
56 blocking_async_close(mDBConn);
57 }
59 NS_IMETHOD HandleResult(mozIStorageResultSet* aResultSet)
60 {
61 sResult = true;
62 spin_events_loop_until_true(&mCompleted);
63 if (!sAlive) {
64 NS_RUNTIMEABORT("The statement callback was destroyed prematurely.");
65 }
66 return NS_OK;
67 }
69 NS_IMETHOD HandleError(mozIStorageError* aError)
70 {
71 sError = true;
72 spin_events_loop_until_true(&mCompleted);
73 if (!sAlive) {
74 NS_RUNTIMEABORT("The statement callback was destroyed prematurely.");
75 }
76 return NS_OK;
77 }
79 NS_IMETHOD HandleCompletion(uint16_t aReason)
80 {
81 mCompleted = true;
82 return NS_OK;
83 }
85 protected:
86 nsCOMPtr<mozIStorageConnection> mDBConn;
87 bool mCompleted;
88 };
90 NS_IMPL_ISUPPORTS(UnownedCallback, mozIStorageStatementCallback)
92 bool UnownedCallback::sAlive = false;
93 bool UnownedCallback::sResult = false;
94 bool UnownedCallback::sError = false;
96 ////////////////////////////////////////////////////////////////////////////////
97 //// Tests
99 void
100 test_SpinEventsLoopInHandleResult()
101 {
102 nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
104 // Create a test table and populate it.
105 nsCOMPtr<mozIStorageStatement> stmt;
106 db->CreateStatement(NS_LITERAL_CSTRING(
107 "CREATE TABLE test (id INTEGER PRIMARY KEY)"
108 ), getter_AddRefs(stmt));
109 stmt->Execute();
110 stmt->Finalize();
112 db->CreateStatement(NS_LITERAL_CSTRING(
113 "INSERT INTO test (id) VALUES (?)"
114 ), getter_AddRefs(stmt));
115 for (int32_t i = 0; i < 30; ++i) {
116 stmt->BindInt32ByIndex(0, i);
117 stmt->Execute();
118 stmt->Reset();
119 }
120 stmt->Finalize();
122 db->CreateStatement(NS_LITERAL_CSTRING(
123 "SELECT * FROM test"
124 ), getter_AddRefs(stmt));
125 nsCOMPtr<mozIStoragePendingStatement> ps;
126 do_check_success(stmt->ExecuteAsync(new UnownedCallback(db),
127 getter_AddRefs(ps)));
128 stmt->Finalize();
130 spin_events_loop_until_true(&UnownedCallback::sResult);
131 }
133 void
134 test_SpinEventsLoopInHandleError()
135 {
136 nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
138 // Create a test table and populate it.
139 nsCOMPtr<mozIStorageStatement> stmt;
140 db->CreateStatement(NS_LITERAL_CSTRING(
141 "CREATE TABLE test (id INTEGER PRIMARY KEY)"
142 ), getter_AddRefs(stmt));
143 stmt->Execute();
144 stmt->Finalize();
146 db->CreateStatement(NS_LITERAL_CSTRING(
147 "INSERT INTO test (id) VALUES (1)"
148 ), getter_AddRefs(stmt));
149 stmt->Execute();
150 stmt->Finalize();
152 // This will cause a constraint error.
153 db->CreateStatement(NS_LITERAL_CSTRING(
154 "INSERT INTO test (id) VALUES (1)"
155 ), getter_AddRefs(stmt));
156 nsCOMPtr<mozIStoragePendingStatement> ps;
157 do_check_success(stmt->ExecuteAsync(new UnownedCallback(db),
158 getter_AddRefs(ps)));
159 stmt->Finalize();
161 spin_events_loop_until_true(&UnownedCallback::sError);
162 }
164 void (*gTests[])(void) = {
165 test_SpinEventsLoopInHandleResult,
166 test_SpinEventsLoopInHandleError,
167 };
169 const char *file = __FILE__;
170 #define TEST_NAME "test async callbacks with spun event loops"
171 #define TEST_FILE file
172 #include "storage_test_harness_tail.h"