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