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/. */
6
7 #include "storage_test_harness.h"
8
9 #include "mozStorageHelper.h"
10 #include "mozStorageConnection.h"
11
12 using namespace mozilla;
13 using namespace mozilla::storage;
14
has_transaction(mozIStorageConnection * aDB)15 bool has_transaction(mozIStorageConnection* aDB) {
16 return !(static_cast<Connection*>(aDB)->getAutocommit());
17 }
18
19 /**
20 * This file tests our Transaction helper in mozStorageHelper.h.
21 */
22
TEST(storage_transaction_helper,Commit)23 TEST(storage_transaction_helper, Commit)
24 {
25 nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
26
27 // Create a table in a transaction, call Commit, and make sure that it does
28 // exists after the transaction falls out of scope.
29 {
30 mozStorageTransaction transaction(db, false);
31 do_check_success(transaction.Start());
32 do_check_true(has_transaction(db));
33 (void)db->ExecuteSimpleSQL("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns);
34 (void)transaction.Commit();
35 }
36 do_check_false(has_transaction(db));
37
38 bool exists = false;
39 (void)db->TableExists("test"_ns, &exists);
40 do_check_true(exists);
41 }
42
TEST(storage_transaction_helper,Rollback)43 TEST(storage_transaction_helper, Rollback)
44 {
45 nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
46
47 // Create a table in a transaction, call Rollback, and make sure that it does
48 // not exists after the transaction falls out of scope.
49 {
50 mozStorageTransaction transaction(db, true);
51 do_check_success(transaction.Start());
52 do_check_true(has_transaction(db));
53 (void)db->ExecuteSimpleSQL("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns);
54 (void)transaction.Rollback();
55 }
56 do_check_false(has_transaction(db));
57
58 bool exists = true;
59 (void)db->TableExists("test"_ns, &exists);
60 do_check_false(exists);
61 }
62
TEST(storage_transaction_helper,AutoCommit)63 TEST(storage_transaction_helper, AutoCommit)
64 {
65 nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
66
67 // Create a table in a transaction, and make sure that it exists after the
68 // transaction falls out of scope. This means the Commit was successful.
69 {
70 mozStorageTransaction transaction(db, true);
71 do_check_success(transaction.Start());
72 do_check_true(has_transaction(db));
73 (void)db->ExecuteSimpleSQL("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns);
74 }
75 do_check_false(has_transaction(db));
76
77 bool exists = false;
78 (void)db->TableExists("test"_ns, &exists);
79 do_check_true(exists);
80 }
81
TEST(storage_transaction_helper,AutoRollback)82 TEST(storage_transaction_helper, AutoRollback)
83 {
84 nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
85
86 // Create a table in a transaction, and make sure that it does not exists
87 // after the transaction falls out of scope. This means the Rollback was
88 // successful.
89 {
90 mozStorageTransaction transaction(db, false);
91 do_check_success(transaction.Start());
92 do_check_true(has_transaction(db));
93 (void)db->ExecuteSimpleSQL("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns);
94 }
95 do_check_false(has_transaction(db));
96
97 bool exists = true;
98 (void)db->TableExists("test"_ns, &exists);
99 do_check_false(exists);
100 }
101
TEST(storage_transaction_helper,null_database_connection)102 TEST(storage_transaction_helper, null_database_connection)
103 {
104 // We permit the use of the Transaction helper when passing a null database
105 // in, so we need to make sure this still works without crashing.
106 mozStorageTransaction transaction(nullptr, false);
107 do_check_success(transaction.Start());
108 do_check_true(NS_SUCCEEDED(transaction.Commit()));
109 do_check_true(NS_SUCCEEDED(transaction.Rollback()));
110 }
111
TEST(storage_transaction_helper,async_Commit)112 TEST(storage_transaction_helper, async_Commit)
113 {
114 HookSqliteMutex hook;
115
116 nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
117
118 // -- wedge the thread
119 nsCOMPtr<nsIThread> target(get_conn_async_thread(db));
120 do_check_true(target);
121 RefPtr<ThreadWedger> wedger(new ThreadWedger(target));
122
123 {
124 mozStorageTransaction transaction(
125 db, false, mozIStorageConnection::TRANSACTION_DEFERRED, true);
126 do_check_success(transaction.Start());
127 do_check_true(has_transaction(db));
128 (void)db->ExecuteSimpleSQL("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns);
129 (void)transaction.Commit();
130 }
131 do_check_true(has_transaction(db));
132
133 // -- unwedge the async thread
134 wedger->unwedge();
135
136 // Ensure the transaction has done its job by enqueueing an async execution.
137 nsCOMPtr<mozIStorageAsyncStatement> stmt;
138 (void)db->CreateAsyncStatement("SELECT NULL"_ns, getter_AddRefs(stmt));
139 blocking_async_execute(stmt);
140 stmt->Finalize();
141 do_check_false(has_transaction(db));
142 bool exists = false;
143 (void)db->TableExists("test"_ns, &exists);
144 do_check_true(exists);
145
146 blocking_async_close(db);
147 }
148
TEST(storage_transaction_helper,Nesting)149 TEST(storage_transaction_helper, Nesting)
150 {
151 nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
152
153 {
154 mozStorageTransaction transaction(db, false);
155 do_check_success(transaction.Start());
156 do_check_true(has_transaction(db));
157 do_check_success(
158 db->ExecuteSimpleSQL("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns));
159
160 {
161 mozStorageTransaction nestedTransaction(db, false);
162 do_check_success(nestedTransaction.Start());
163 do_check_true(has_transaction(db));
164 do_check_success(db->ExecuteSimpleSQL(
165 "CREATE TABLE nested_test (id INTEGER PRIMARY KEY)"_ns));
166
167 #ifndef MOZ_DIAGNOSTIC_ASSERT_ENABLED
168 do_check_true(transaction.Commit() == NS_ERROR_NOT_AVAILABLE);
169 do_check_true(transaction.Rollback() == NS_ERROR_NOT_AVAILABLE);
170 #endif
171 }
172
173 bool exists = false;
174 do_check_success(db->TableExists("nested_test"_ns, &exists));
175 do_check_false(exists);
176
177 (void)transaction.Commit();
178 }
179 do_check_false(has_transaction(db));
180
181 bool exists = false;
182 do_check_success(db->TableExists("test"_ns, &exists));
183 do_check_true(exists);
184 }
185