1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "storage_test_harness.h"
9 ////////////////////////////////////////////////////////////////////////////////
12 TEST(storage_true_async
, TrueAsyncStatement
)
16 nsCOMPtr
<mozIStorageConnection
> db(getMemoryDatabase());
18 // Start watching for forbidden mutex usage.
19 watch_for_mutex_use_on_this_thread();
21 // - statement with nothing to bind
22 nsCOMPtr
<mozIStorageAsyncStatement
> stmt
;
23 db
->CreateAsyncStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns
,
24 getter_AddRefs(stmt
));
25 blocking_async_execute(stmt
);
27 do_check_false(mutex_used_on_watched_thread
);
29 // - statement with something to bind ordinally
30 db
->CreateAsyncStatement("INSERT INTO test (id) VALUES (?)"_ns
,
31 getter_AddRefs(stmt
));
32 stmt
->BindInt32ByIndex(0, 1);
33 blocking_async_execute(stmt
);
35 do_check_false(mutex_used_on_watched_thread
);
37 // - statement with something to bind by name
38 db
->CreateAsyncStatement("INSERT INTO test (id) VALUES (:id)"_ns
,
39 getter_AddRefs(stmt
));
40 nsCOMPtr
<mozIStorageBindingParamsArray
> paramsArray
;
41 stmt
->NewBindingParamsArray(getter_AddRefs(paramsArray
));
42 nsCOMPtr
<mozIStorageBindingParams
> params
;
43 paramsArray
->NewBindingParams(getter_AddRefs(params
));
44 params
->BindInt32ByName("id"_ns
, 2);
45 paramsArray
->AddParams(params
);
47 stmt
->BindParameters(paramsArray
);
48 paramsArray
= nullptr;
49 blocking_async_execute(stmt
);
51 do_check_false(mutex_used_on_watched_thread
);
53 // - now, make sure creating a sync statement does trigger our guard.
54 // (If this doesn't happen, our test is bunk and it's important to know that.)
55 nsCOMPtr
<mozIStorageStatement
> syncStmt
;
56 db
->CreateStatement("SELECT * FROM test"_ns
, getter_AddRefs(syncStmt
));
58 do_check_true(mutex_used_on_watched_thread
);
60 blocking_async_close(db
);
64 * Test that cancellation before a statement is run successfully stops the
65 * statement from executing.
67 TEST(storage_true_async
, AsyncCancellation
)
71 nsCOMPtr
<mozIStorageConnection
> db(getMemoryDatabase());
73 // -- wedge the thread
74 nsCOMPtr
<nsIThread
> target(get_conn_async_thread(db
));
75 do_check_true(target
);
76 RefPtr
<ThreadWedger
> wedger(new ThreadWedger(target
));
78 // -- create statements and cancel them
80 nsCOMPtr
<mozIStorageAsyncStatement
> asyncStmt
;
81 db
->CreateAsyncStatement(
82 "CREATE TABLE asyncTable (id INTEGER PRIMARY KEY)"_ns
,
83 getter_AddRefs(asyncStmt
));
85 RefPtr
<AsyncStatementSpinner
> asyncSpin(new AsyncStatementSpinner());
86 nsCOMPtr
<mozIStoragePendingStatement
> asyncPend
;
87 (void)asyncStmt
->ExecuteAsync(asyncSpin
, getter_AddRefs(asyncPend
));
88 do_check_true(asyncPend
);
92 nsCOMPtr
<mozIStorageStatement
> syncStmt
;
93 db
->CreateStatement("CREATE TABLE syncTable (id INTEGER PRIMARY KEY)"_ns
,
94 getter_AddRefs(syncStmt
));
96 RefPtr
<AsyncStatementSpinner
> syncSpin(new AsyncStatementSpinner());
97 nsCOMPtr
<mozIStoragePendingStatement
> syncPend
;
98 (void)syncStmt
->ExecuteAsync(syncSpin
, getter_AddRefs(syncPend
));
99 do_check_true(syncPend
);
102 // -- unwedge the async thread
105 // -- verify that both statements report they were canceled
106 asyncSpin
->SpinUntilCompleted();
107 do_check_true(asyncSpin
->completionReason
==
108 mozIStorageStatementCallback::REASON_CANCELED
);
110 syncSpin
->SpinUntilCompleted();
111 do_check_true(syncSpin
->completionReason
==
112 mozIStorageStatementCallback::REASON_CANCELED
);
114 // -- verify that neither statement constructed their tables
117 rv
= db
->TableExists("asyncTable"_ns
, &exists
);
118 do_check_true(rv
== NS_OK
);
119 do_check_false(exists
);
120 rv
= db
->TableExists("syncTable"_ns
, &exists
);
121 do_check_true(rv
== NS_OK
);
122 do_check_false(exists
);
125 asyncStmt
->Finalize();
126 syncStmt
->Finalize();
127 blocking_async_close(db
);
131 * Test that the destructor for an asynchronous statement which has a
132 * sqlite3_stmt will dispatch that statement to the async thread for
133 * finalization rather than trying to finalize it on the main thread
134 * (and thereby running afoul of our mutex use detector).
136 TEST(storage_true_async
, AsyncDestructorFinalizesOnAsyncThread
)
138 HookSqliteMutex hook
;
140 nsCOMPtr
<mozIStorageConnection
> db(getMemoryDatabase());
141 watch_for_mutex_use_on_this_thread();
143 // -- create an async statement
144 nsCOMPtr
<mozIStorageAsyncStatement
> stmt
;
145 db
->CreateAsyncStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns
,
146 getter_AddRefs(stmt
));
148 // -- execute it so it gets a sqlite3_stmt that needs to be finalized
149 blocking_async_execute(stmt
);
150 do_check_false(mutex_used_on_watched_thread
);
152 // -- forget our reference
155 // -- verify the mutex was not touched
156 do_check_false(mutex_used_on_watched_thread
);
158 // -- make sure the statement actually gets finalized / cleanup
159 // the close will assert if we failed to finalize!
160 blocking_async_close(db
);