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 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is storage test code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * The Mozilla Foundation.
20 : * Portions created by the Initial Developer are Copyright (C) 2009
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Shawn Wilsher <me@shawnwilsher.com> (Original Author)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "TestHarness.h"
41 : #include "nsMemory.h"
42 : #include "nsThreadUtils.h"
43 : #include "nsDirectoryServiceDefs.h"
44 : #include "mozIStorageService.h"
45 : #include "mozIStorageConnection.h"
46 : #include "mozIStorageStatementCallback.h"
47 : #include "mozIStorageCompletionCallback.h"
48 : #include "mozIStorageBindingParamsArray.h"
49 : #include "mozIStorageBindingParams.h"
50 : #include "mozIStorageAsyncStatement.h"
51 : #include "mozIStorageStatement.h"
52 : #include "mozIStoragePendingStatement.h"
53 : #include "mozIStorageError.h"
54 : #include "nsThreadUtils.h"
55 :
56 : static int gTotalTests = 0;
57 : static int gPassedTests = 0;
58 :
59 : #define do_check_true(aCondition) \
60 : PR_BEGIN_MACRO \
61 : gTotalTests++; \
62 : if (aCondition) { \
63 : gPassedTests++; \
64 : } else { \
65 : fail("%s | Expected true, got false at line %d", __FILE__, __LINE__); \
66 : } \
67 : PR_END_MACRO
68 :
69 : #define do_check_false(aCondition) \
70 : PR_BEGIN_MACRO \
71 : gTotalTests++; \
72 : if (!aCondition) { \
73 : gPassedTests++; \
74 : } else { \
75 : fail("%s | Expected false, got true at line %d", __FILE__, __LINE__); \
76 : } \
77 : PR_END_MACRO
78 :
79 : #define do_check_success(aResult) \
80 : do_check_true(NS_SUCCEEDED(aResult))
81 :
82 : #ifdef LINUX
83 : // XXX Linux opt builds on tinderbox are orange due to linking with stdlib.
84 : // This is sad and annoying, but it's a workaround that works.
85 : #define do_check_eq(aExpected, aActual) \
86 : do_check_true(aExpected == aActual)
87 : #else
88 : #include <sstream>
89 :
90 : #define do_check_eq(aExpected, aActual) \
91 : PR_BEGIN_MACRO \
92 : gTotalTests++; \
93 : if (aExpected == aActual) { \
94 : gPassedTests++; \
95 : } else { \
96 : std::ostringstream temp; \
97 : temp << __FILE__ << " | Expected '" << aExpected << "', got '"; \
98 : temp << aActual <<"' at line " << __LINE__; \
99 : fail(temp.str().c_str()); \
100 : } \
101 : PR_END_MACRO
102 : #endif
103 :
104 : already_AddRefed<mozIStorageService>
105 47 : getService()
106 : {
107 : nsCOMPtr<mozIStorageService> ss =
108 94 : do_GetService("@mozilla.org/storage/service;1");
109 47 : do_check_true(ss);
110 47 : return ss.forget();
111 : }
112 :
113 : already_AddRefed<mozIStorageConnection>
114 40 : getMemoryDatabase()
115 : {
116 80 : nsCOMPtr<mozIStorageService> ss = getService();
117 80 : nsCOMPtr<mozIStorageConnection> conn;
118 40 : nsresult rv = ss->OpenSpecialDatabase("memory", getter_AddRefs(conn));
119 40 : do_check_success(rv);
120 40 : return conn.forget();
121 : }
122 :
123 : already_AddRefed<mozIStorageConnection>
124 6 : getDatabase()
125 : {
126 12 : nsCOMPtr<nsIFile> dbFile;
127 : (void)NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
128 6 : getter_AddRefs(dbFile));
129 6 : NS_ASSERTION(dbFile, "The directory doesn't exists?!");
130 :
131 6 : nsresult rv = dbFile->Append(NS_LITERAL_STRING("storage_test_db.sqlite"));
132 6 : do_check_success(rv);
133 :
134 12 : nsCOMPtr<mozIStorageService> ss = getService();
135 12 : nsCOMPtr<mozIStorageConnection> conn;
136 6 : rv = ss->OpenDatabase(dbFile, getter_AddRefs(conn));
137 6 : do_check_success(rv);
138 6 : return conn.forget();
139 : }
140 :
141 :
142 : class AsyncStatementSpinner : public mozIStorageStatementCallback
143 : , public mozIStorageCompletionCallback
144 : {
145 : public:
146 : NS_DECL_ISUPPORTS
147 : NS_DECL_MOZISTORAGESTATEMENTCALLBACK
148 : NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
149 :
150 : AsyncStatementSpinner();
151 :
152 : void SpinUntilCompleted();
153 :
154 : PRUint16 completionReason;
155 :
156 : protected:
157 41 : ~AsyncStatementSpinner() {}
158 : volatile bool mCompleted;
159 : };
160 :
161 268 : NS_IMPL_ISUPPORTS2(AsyncStatementSpinner,
162 : mozIStorageStatementCallback,
163 : mozIStorageCompletionCallback)
164 :
165 41 : AsyncStatementSpinner::AsyncStatementSpinner()
166 : : completionReason(0)
167 41 : , mCompleted(false)
168 : {
169 41 : }
170 :
171 : NS_IMETHODIMP
172 1 : AsyncStatementSpinner::HandleResult(mozIStorageResultSet *aResultSet)
173 : {
174 1 : return NS_OK;
175 : }
176 :
177 : NS_IMETHODIMP
178 0 : AsyncStatementSpinner::HandleError(mozIStorageError *aError)
179 : {
180 : PRInt32 result;
181 0 : nsresult rv = aError->GetResult(&result);
182 0 : NS_ENSURE_SUCCESS(rv, rv);
183 0 : nsCAutoString message;
184 0 : rv = aError->GetMessage(message);
185 0 : NS_ENSURE_SUCCESS(rv, rv);
186 :
187 0 : nsCAutoString warnMsg;
188 0 : warnMsg.Append("An error occurred while executing an async statement: ");
189 0 : warnMsg.AppendInt(result);
190 0 : warnMsg.Append(" ");
191 0 : warnMsg.Append(message);
192 0 : NS_WARNING(warnMsg.get());
193 :
194 0 : return NS_OK;
195 : }
196 :
197 : NS_IMETHODIMP
198 21 : AsyncStatementSpinner::HandleCompletion(PRUint16 aReason)
199 : {
200 21 : completionReason = aReason;
201 21 : mCompleted = true;
202 21 : return NS_OK;
203 : }
204 :
205 : NS_IMETHODIMP
206 20 : AsyncStatementSpinner::Complete()
207 : {
208 20 : mCompleted = true;
209 20 : return NS_OK;
210 : }
211 :
212 41 : void AsyncStatementSpinner::SpinUntilCompleted()
213 : {
214 82 : nsCOMPtr<nsIThread> thread(::do_GetCurrentThread());
215 41 : nsresult rv = NS_OK;
216 41 : bool processed = true;
217 175 : while (!mCompleted && NS_SUCCEEDED(rv)) {
218 93 : rv = thread->ProcessNextEvent(true, &processed);
219 : }
220 41 : }
221 :
222 : #define NS_DECL_ASYNCSTATEMENTSPINNER \
223 : NS_IMETHOD HandleResult(mozIStorageResultSet *aResultSet);
224 :
225 : ////////////////////////////////////////////////////////////////////////////////
226 : //// Async Helpers
227 :
228 : /**
229 : * Execute an async statement, blocking the main thread until we get the
230 : * callback completion notification.
231 : */
232 : void
233 5 : blocking_async_execute(mozIStorageBaseStatement *stmt)
234 : {
235 10 : nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner());
236 :
237 10 : nsCOMPtr<mozIStoragePendingStatement> pendy;
238 5 : (void)stmt->ExecuteAsync(spinner, getter_AddRefs(pendy));
239 5 : spinner->SpinUntilCompleted();
240 5 : }
241 :
242 : /**
243 : * Invoke AsyncClose on the given connection, blocking the main thread until we
244 : * get the completion notification.
245 : */
246 : void
247 19 : blocking_async_close(mozIStorageConnection *db)
248 : {
249 38 : nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner());
250 :
251 19 : db->AsyncClose(spinner);
252 19 : spinner->SpinUntilCompleted();
253 19 : }
|