1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/test/storage_test_harness.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,226 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "TestHarness.h" 1.11 +#include "nsMemory.h" 1.12 +#include "nsThreadUtils.h" 1.13 +#include "nsDirectoryServiceDefs.h" 1.14 +#include "mozIStorageService.h" 1.15 +#include "mozIStorageConnection.h" 1.16 +#include "mozIStorageStatementCallback.h" 1.17 +#include "mozIStorageCompletionCallback.h" 1.18 +#include "mozIStorageBindingParamsArray.h" 1.19 +#include "mozIStorageBindingParams.h" 1.20 +#include "mozIStorageAsyncStatement.h" 1.21 +#include "mozIStorageStatement.h" 1.22 +#include "mozIStoragePendingStatement.h" 1.23 +#include "mozIStorageError.h" 1.24 +#include "nsThreadUtils.h" 1.25 + 1.26 +static int gTotalTests = 0; 1.27 +static int gPassedTests = 0; 1.28 + 1.29 +#define do_check_true(aCondition) \ 1.30 + PR_BEGIN_MACRO \ 1.31 + gTotalTests++; \ 1.32 + if (aCondition) { \ 1.33 + gPassedTests++; \ 1.34 + } else { \ 1.35 + fail("%s | Expected true, got false at line %d", __FILE__, __LINE__); \ 1.36 + } \ 1.37 + PR_END_MACRO 1.38 + 1.39 +#define do_check_false(aCondition) \ 1.40 + PR_BEGIN_MACRO \ 1.41 + gTotalTests++; \ 1.42 + if (!aCondition) { \ 1.43 + gPassedTests++; \ 1.44 + } else { \ 1.45 + fail("%s | Expected false, got true at line %d", __FILE__, __LINE__); \ 1.46 + } \ 1.47 + PR_END_MACRO 1.48 + 1.49 +#define do_check_success(aResult) \ 1.50 + do_check_true(NS_SUCCEEDED(aResult)) 1.51 + 1.52 +#ifdef LINUX 1.53 +// XXX Linux opt builds on tinderbox are orange due to linking with stdlib. 1.54 +// This is sad and annoying, but it's a workaround that works. 1.55 +#define do_check_eq(aExpected, aActual) \ 1.56 + do_check_true(aExpected == aActual) 1.57 +#else 1.58 +#include <sstream> 1.59 + 1.60 +// Print nsresult as uint32_t 1.61 +std::ostream& operator<<(std::ostream& aStream, const nsresult aInput) 1.62 +{ 1.63 + return aStream << static_cast<uint32_t>(aInput); 1.64 +} 1.65 + 1.66 +#define do_check_eq(aExpected, aActual) \ 1.67 + PR_BEGIN_MACRO \ 1.68 + gTotalTests++; \ 1.69 + if (aExpected == aActual) { \ 1.70 + gPassedTests++; \ 1.71 + } else { \ 1.72 + std::ostringstream temp; \ 1.73 + temp << __FILE__ << " | Expected '" << aExpected << "', got '"; \ 1.74 + temp << aActual <<"' at line " << __LINE__; \ 1.75 + fail(temp.str().c_str()); \ 1.76 + } \ 1.77 + PR_END_MACRO 1.78 +#endif 1.79 + 1.80 +already_AddRefed<mozIStorageService> 1.81 +getService() 1.82 +{ 1.83 + nsCOMPtr<mozIStorageService> ss = 1.84 + do_GetService("@mozilla.org/storage/service;1"); 1.85 + do_check_true(ss); 1.86 + return ss.forget(); 1.87 +} 1.88 + 1.89 +already_AddRefed<mozIStorageConnection> 1.90 +getMemoryDatabase() 1.91 +{ 1.92 + nsCOMPtr<mozIStorageService> ss = getService(); 1.93 + nsCOMPtr<mozIStorageConnection> conn; 1.94 + nsresult rv = ss->OpenSpecialDatabase("memory", getter_AddRefs(conn)); 1.95 + do_check_success(rv); 1.96 + return conn.forget(); 1.97 +} 1.98 + 1.99 +already_AddRefed<mozIStorageConnection> 1.100 +getDatabase() 1.101 +{ 1.102 + nsCOMPtr<nsIFile> dbFile; 1.103 + (void)NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, 1.104 + getter_AddRefs(dbFile)); 1.105 + NS_ASSERTION(dbFile, "The directory doesn't exists?!"); 1.106 + 1.107 + nsresult rv = dbFile->Append(NS_LITERAL_STRING("storage_test_db.sqlite")); 1.108 + do_check_success(rv); 1.109 + 1.110 + nsCOMPtr<mozIStorageService> ss = getService(); 1.111 + nsCOMPtr<mozIStorageConnection> conn; 1.112 + rv = ss->OpenDatabase(dbFile, getter_AddRefs(conn)); 1.113 + do_check_success(rv); 1.114 + return conn.forget(); 1.115 +} 1.116 + 1.117 + 1.118 +class AsyncStatementSpinner : public mozIStorageStatementCallback 1.119 + , public mozIStorageCompletionCallback 1.120 +{ 1.121 +public: 1.122 + NS_DECL_ISUPPORTS 1.123 + NS_DECL_MOZISTORAGESTATEMENTCALLBACK 1.124 + NS_DECL_MOZISTORAGECOMPLETIONCALLBACK 1.125 + 1.126 + AsyncStatementSpinner(); 1.127 + 1.128 + void SpinUntilCompleted(); 1.129 + 1.130 + uint16_t completionReason; 1.131 + 1.132 +protected: 1.133 + virtual ~AsyncStatementSpinner() {} 1.134 + volatile bool mCompleted; 1.135 +}; 1.136 + 1.137 +NS_IMPL_ISUPPORTS(AsyncStatementSpinner, 1.138 + mozIStorageStatementCallback, 1.139 + mozIStorageCompletionCallback) 1.140 + 1.141 +AsyncStatementSpinner::AsyncStatementSpinner() 1.142 +: completionReason(0) 1.143 +, mCompleted(false) 1.144 +{ 1.145 +} 1.146 + 1.147 +NS_IMETHODIMP 1.148 +AsyncStatementSpinner::HandleResult(mozIStorageResultSet *aResultSet) 1.149 +{ 1.150 + return NS_OK; 1.151 +} 1.152 + 1.153 +NS_IMETHODIMP 1.154 +AsyncStatementSpinner::HandleError(mozIStorageError *aError) 1.155 +{ 1.156 + int32_t result; 1.157 + nsresult rv = aError->GetResult(&result); 1.158 + NS_ENSURE_SUCCESS(rv, rv); 1.159 + nsAutoCString message; 1.160 + rv = aError->GetMessage(message); 1.161 + NS_ENSURE_SUCCESS(rv, rv); 1.162 + 1.163 + nsAutoCString warnMsg; 1.164 + warnMsg.Append("An error occurred while executing an async statement: "); 1.165 + warnMsg.AppendInt(result); 1.166 + warnMsg.Append(" "); 1.167 + warnMsg.Append(message); 1.168 + NS_WARNING(warnMsg.get()); 1.169 + 1.170 + return NS_OK; 1.171 +} 1.172 + 1.173 +NS_IMETHODIMP 1.174 +AsyncStatementSpinner::HandleCompletion(uint16_t aReason) 1.175 +{ 1.176 + completionReason = aReason; 1.177 + mCompleted = true; 1.178 + return NS_OK; 1.179 +} 1.180 + 1.181 +NS_IMETHODIMP 1.182 +AsyncStatementSpinner::Complete(nsresult, nsISupports*) 1.183 +{ 1.184 + mCompleted = true; 1.185 + return NS_OK; 1.186 +} 1.187 + 1.188 +void AsyncStatementSpinner::SpinUntilCompleted() 1.189 +{ 1.190 + nsCOMPtr<nsIThread> thread(::do_GetCurrentThread()); 1.191 + nsresult rv = NS_OK; 1.192 + bool processed = true; 1.193 + while (!mCompleted && NS_SUCCEEDED(rv)) { 1.194 + rv = thread->ProcessNextEvent(true, &processed); 1.195 + } 1.196 +} 1.197 + 1.198 +#define NS_DECL_ASYNCSTATEMENTSPINNER \ 1.199 + NS_IMETHOD HandleResult(mozIStorageResultSet *aResultSet); 1.200 + 1.201 +//////////////////////////////////////////////////////////////////////////////// 1.202 +//// Async Helpers 1.203 + 1.204 +/** 1.205 + * Execute an async statement, blocking the main thread until we get the 1.206 + * callback completion notification. 1.207 + */ 1.208 +void 1.209 +blocking_async_execute(mozIStorageBaseStatement *stmt) 1.210 +{ 1.211 + nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner()); 1.212 + 1.213 + nsCOMPtr<mozIStoragePendingStatement> pendy; 1.214 + (void)stmt->ExecuteAsync(spinner, getter_AddRefs(pendy)); 1.215 + spinner->SpinUntilCompleted(); 1.216 +} 1.217 + 1.218 +/** 1.219 + * Invoke AsyncClose on the given connection, blocking the main thread until we 1.220 + * get the completion notification. 1.221 + */ 1.222 +void 1.223 +blocking_async_close(mozIStorageConnection *db) 1.224 +{ 1.225 + nsRefPtr<AsyncStatementSpinner> spinner(new AsyncStatementSpinner()); 1.226 + 1.227 + db->AsyncClose(spinner); 1.228 + spinner->SpinUntilCompleted(); 1.229 +}