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_true(has_transaction(db));
32     (void)db->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
33       "CREATE TABLE test (id INTEGER PRIMARY KEY)"
34     ));
35     (void)transaction.Commit();
36   }
37   do_check_false(has_transaction(db));
38 
39   bool exists = false;
40   (void)db->TableExists(NS_LITERAL_CSTRING("test"), &exists);
41   do_check_true(exists);
42 }
43 
TEST(storage_transaction_helper,Rollback)44 TEST(storage_transaction_helper, Rollback)
45 {
46   nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
47 
48   // Create a table in a transaction, call Rollback, and make sure that it does
49   // not exists after the transaction falls out of scope.
50   {
51     mozStorageTransaction transaction(db, true);
52     do_check_true(has_transaction(db));
53     (void)db->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
54       "CREATE TABLE test (id INTEGER PRIMARY KEY)"
55     ));
56     (void)transaction.Rollback();
57   }
58   do_check_false(has_transaction(db));
59 
60   bool exists = true;
61   (void)db->TableExists(NS_LITERAL_CSTRING("test"), &exists);
62   do_check_false(exists);
63 }
64 
TEST(storage_transaction_helper,AutoCommit)65 TEST(storage_transaction_helper, AutoCommit)
66 {
67   nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
68 
69   // Create a table in a transaction, and make sure that it exists after the
70   // transaction falls out of scope.  This means the Commit was successful.
71   {
72     mozStorageTransaction transaction(db, true);
73     do_check_true(has_transaction(db));
74     (void)db->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
75       "CREATE TABLE test (id INTEGER PRIMARY KEY)"
76     ));
77   }
78   do_check_false(has_transaction(db));
79 
80   bool exists = false;
81   (void)db->TableExists(NS_LITERAL_CSTRING("test"), &exists);
82   do_check_true(exists);
83 }
84 
TEST(storage_transaction_helper,AutoRollback)85 TEST(storage_transaction_helper, AutoRollback)
86 {
87   nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
88 
89   // Create a table in a transaction, and make sure that it does not exists
90   // after the transaction falls out of scope.  This means the Rollback was
91   // successful.
92   {
93     mozStorageTransaction transaction(db, false);
94     do_check_true(has_transaction(db));
95     (void)db->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
96       "CREATE TABLE test (id INTEGER PRIMARY KEY)"
97     ));
98   }
99   do_check_false(has_transaction(db));
100 
101   bool exists = true;
102   (void)db->TableExists(NS_LITERAL_CSTRING("test"), &exists);
103   do_check_false(exists);
104 }
105 
TEST(storage_transaction_helper,null_database_connection)106 TEST(storage_transaction_helper, null_database_connection)
107 {
108   // We permit the use of the Transaction helper when passing a null database
109   // in, so we need to make sure this still works without crashing.
110   mozStorageTransaction transaction(nullptr, false);
111   do_check_true(NS_SUCCEEDED(transaction.Commit()));
112   do_check_true(NS_SUCCEEDED(transaction.Rollback()));
113 }
114 
TEST(storage_transaction_helper,async_Commit)115 TEST(storage_transaction_helper, async_Commit)
116 {
117   HookSqliteMutex hook;
118 
119   nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
120 
121   // -- wedge the thread
122   nsCOMPtr<nsIThread> target(get_conn_async_thread(db));
123   do_check_true(target);
124   RefPtr<ThreadWedger> wedger (new ThreadWedger(target));
125 
126   {
127     mozStorageTransaction transaction(db, false,
128                                       mozIStorageConnection::TRANSACTION_DEFERRED,
129                                       true);
130     do_check_true(has_transaction(db));
131     (void)db->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
132       "CREATE TABLE test (id INTEGER PRIMARY KEY)"
133     ));
134     (void)transaction.Commit();
135   }
136   do_check_true(has_transaction(db));
137 
138   // -- unwedge the async thread
139   wedger->unwedge();
140 
141   // Ensure the transaction has done its job by enqueueing an async execution.
142   nsCOMPtr<mozIStorageAsyncStatement> stmt;
143   (void)db->CreateAsyncStatement(NS_LITERAL_CSTRING(
144     "SELECT NULL"
145   ), getter_AddRefs(stmt));
146   blocking_async_execute(stmt);
147   stmt->Finalize();
148   do_check_false(has_transaction(db));
149   bool exists = false;
150   (void)db->TableExists(NS_LITERAL_CSTRING("test"), &exists);
151   do_check_true(exists);
152 
153   blocking_async_close(db);
154 }
155