toolkit/components/places/tests/cpp/places_test_harness.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "TestHarness.h"
michael@0 8 #include "nsMemory.h"
michael@0 9 #include "nsThreadUtils.h"
michael@0 10 #include "nsNetUtil.h"
michael@0 11 #include "nsDocShellCID.h"
michael@0 12
michael@0 13 #include "nsToolkitCompsCID.h"
michael@0 14 #include "nsINavHistoryService.h"
michael@0 15 #include "nsIObserverService.h"
michael@0 16 #include "mozilla/IHistory.h"
michael@0 17 #include "mozIStorageConnection.h"
michael@0 18 #include "mozIStorageStatement.h"
michael@0 19 #include "mozIStorageAsyncStatement.h"
michael@0 20 #include "mozIStorageStatementCallback.h"
michael@0 21 #include "mozIStoragePendingStatement.h"
michael@0 22 #include "nsPIPlacesDatabase.h"
michael@0 23 #include "nsIObserver.h"
michael@0 24 #include "prinrval.h"
michael@0 25 #include "mozilla/Attributes.h"
michael@0 26
michael@0 27 #define WAITFORTOPIC_TIMEOUT_SECONDS 5
michael@0 28
michael@0 29
michael@0 30 static size_t gTotalTests = 0;
michael@0 31 static size_t gPassedTests = 0;
michael@0 32
michael@0 33 #define do_check_true(aCondition) \
michael@0 34 PR_BEGIN_MACRO \
michael@0 35 gTotalTests++; \
michael@0 36 if (aCondition) { \
michael@0 37 gPassedTests++; \
michael@0 38 } else { \
michael@0 39 fail("%s | Expected true, got false at line %d", __FILE__, __LINE__); \
michael@0 40 } \
michael@0 41 PR_END_MACRO
michael@0 42
michael@0 43 #define do_check_false(aCondition) \
michael@0 44 PR_BEGIN_MACRO \
michael@0 45 gTotalTests++; \
michael@0 46 if (!aCondition) { \
michael@0 47 gPassedTests++; \
michael@0 48 } else { \
michael@0 49 fail("%s | Expected false, got true at line %d", __FILE__, __LINE__); \
michael@0 50 } \
michael@0 51 PR_END_MACRO
michael@0 52
michael@0 53 #define do_check_success(aResult) \
michael@0 54 do_check_true(NS_SUCCEEDED(aResult))
michael@0 55
michael@0 56 #ifdef LINUX
michael@0 57 // XXX Linux opt builds on tinderbox are orange due to linking with stdlib.
michael@0 58 // This is sad and annoying, but it's a workaround that works.
michael@0 59 #define do_check_eq(aExpected, aActual) \
michael@0 60 do_check_true(aExpected == aActual)
michael@0 61 #else
michael@0 62 #include <sstream>
michael@0 63
michael@0 64 #define do_check_eq(aActual, aExpected) \
michael@0 65 PR_BEGIN_MACRO \
michael@0 66 gTotalTests++; \
michael@0 67 if (aExpected == aActual) { \
michael@0 68 gPassedTests++; \
michael@0 69 } else { \
michael@0 70 std::ostringstream temp; \
michael@0 71 temp << __FILE__ << " | Expected '" << aExpected << "', got '"; \
michael@0 72 temp << aActual <<"' at line " << __LINE__; \
michael@0 73 fail(temp.str().c_str()); \
michael@0 74 } \
michael@0 75 PR_END_MACRO
michael@0 76 #endif
michael@0 77
michael@0 78 struct Test
michael@0 79 {
michael@0 80 void (*func)(void);
michael@0 81 const char* const name;
michael@0 82 };
michael@0 83 #define TEST(aName) \
michael@0 84 {aName, #aName}
michael@0 85
michael@0 86 /**
michael@0 87 * Runs the next text.
michael@0 88 */
michael@0 89 void run_next_test();
michael@0 90
michael@0 91 /**
michael@0 92 * To be used around asynchronous work.
michael@0 93 */
michael@0 94 void do_test_pending();
michael@0 95 void do_test_finished();
michael@0 96
michael@0 97 /**
michael@0 98 * Spins current thread until a topic is received.
michael@0 99 */
michael@0 100 class WaitForTopicSpinner MOZ_FINAL : public nsIObserver
michael@0 101 {
michael@0 102 public:
michael@0 103 NS_DECL_ISUPPORTS
michael@0 104
michael@0 105 WaitForTopicSpinner(const char* const aTopic)
michael@0 106 : mTopicReceived(false)
michael@0 107 , mStartTime(PR_IntervalNow())
michael@0 108 {
michael@0 109 nsCOMPtr<nsIObserverService> observerService =
michael@0 110 do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
michael@0 111 do_check_true(observerService);
michael@0 112 (void)observerService->AddObserver(this, aTopic, false);
michael@0 113 }
michael@0 114
michael@0 115 void Spin() {
michael@0 116 while (!mTopicReceived) {
michael@0 117 if ((PR_IntervalNow() - mStartTime) > (WAITFORTOPIC_TIMEOUT_SECONDS * PR_USEC_PER_SEC)) {
michael@0 118 // Timed out waiting for the topic.
michael@0 119 do_check_true(false);
michael@0 120 break;
michael@0 121 }
michael@0 122 (void)NS_ProcessNextEvent();
michael@0 123 }
michael@0 124 }
michael@0 125
michael@0 126 NS_IMETHOD Observe(nsISupports* aSubject,
michael@0 127 const char* aTopic,
michael@0 128 const char16_t* aData)
michael@0 129 {
michael@0 130 mTopicReceived = true;
michael@0 131 nsCOMPtr<nsIObserverService> observerService =
michael@0 132 do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
michael@0 133 do_check_true(observerService);
michael@0 134 (void)observerService->RemoveObserver(this, aTopic);
michael@0 135 return NS_OK;
michael@0 136 }
michael@0 137
michael@0 138 private:
michael@0 139 bool mTopicReceived;
michael@0 140 PRIntervalTime mStartTime;
michael@0 141 };
michael@0 142 NS_IMPL_ISUPPORTS(
michael@0 143 WaitForTopicSpinner,
michael@0 144 nsIObserver
michael@0 145 )
michael@0 146
michael@0 147 /**
michael@0 148 * Spins current thread until an async statement is executed.
michael@0 149 */
michael@0 150 class AsyncStatementSpinner MOZ_FINAL : public mozIStorageStatementCallback
michael@0 151 {
michael@0 152 public:
michael@0 153 NS_DECL_ISUPPORTS
michael@0 154 NS_DECL_MOZISTORAGESTATEMENTCALLBACK
michael@0 155
michael@0 156 AsyncStatementSpinner();
michael@0 157 void SpinUntilCompleted();
michael@0 158 uint16_t completionReason;
michael@0 159
michael@0 160 protected:
michael@0 161 volatile bool mCompleted;
michael@0 162 };
michael@0 163
michael@0 164 NS_IMPL_ISUPPORTS(AsyncStatementSpinner,
michael@0 165 mozIStorageStatementCallback)
michael@0 166
michael@0 167 AsyncStatementSpinner::AsyncStatementSpinner()
michael@0 168 : completionReason(0)
michael@0 169 , mCompleted(false)
michael@0 170 {
michael@0 171 }
michael@0 172
michael@0 173 NS_IMETHODIMP
michael@0 174 AsyncStatementSpinner::HandleResult(mozIStorageResultSet *aResultSet)
michael@0 175 {
michael@0 176 return NS_OK;
michael@0 177 }
michael@0 178
michael@0 179 NS_IMETHODIMP
michael@0 180 AsyncStatementSpinner::HandleError(mozIStorageError *aError)
michael@0 181 {
michael@0 182 return NS_OK;
michael@0 183 }
michael@0 184
michael@0 185 NS_IMETHODIMP
michael@0 186 AsyncStatementSpinner::HandleCompletion(uint16_t aReason)
michael@0 187 {
michael@0 188 completionReason = aReason;
michael@0 189 mCompleted = true;
michael@0 190 return NS_OK;
michael@0 191 }
michael@0 192
michael@0 193 void AsyncStatementSpinner::SpinUntilCompleted()
michael@0 194 {
michael@0 195 nsCOMPtr<nsIThread> thread(::do_GetCurrentThread());
michael@0 196 nsresult rv = NS_OK;
michael@0 197 bool processed = true;
michael@0 198 while (!mCompleted && NS_SUCCEEDED(rv)) {
michael@0 199 rv = thread->ProcessNextEvent(true, &processed);
michael@0 200 }
michael@0 201 }
michael@0 202
michael@0 203 struct PlaceRecord
michael@0 204 {
michael@0 205 int64_t id;
michael@0 206 int32_t hidden;
michael@0 207 int32_t typed;
michael@0 208 int32_t visitCount;
michael@0 209 nsCString guid;
michael@0 210 };
michael@0 211
michael@0 212 struct VisitRecord
michael@0 213 {
michael@0 214 int64_t id;
michael@0 215 int64_t lastVisitId;
michael@0 216 int32_t transitionType;
michael@0 217 };
michael@0 218
michael@0 219 already_AddRefed<mozilla::IHistory>
michael@0 220 do_get_IHistory()
michael@0 221 {
michael@0 222 nsCOMPtr<mozilla::IHistory> history = do_GetService(NS_IHISTORY_CONTRACTID);
michael@0 223 do_check_true(history);
michael@0 224 return history.forget();
michael@0 225 }
michael@0 226
michael@0 227 already_AddRefed<nsINavHistoryService>
michael@0 228 do_get_NavHistory()
michael@0 229 {
michael@0 230 nsCOMPtr<nsINavHistoryService> serv =
michael@0 231 do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
michael@0 232 do_check_true(serv);
michael@0 233 return serv.forget();
michael@0 234 }
michael@0 235
michael@0 236 already_AddRefed<mozIStorageConnection>
michael@0 237 do_get_db()
michael@0 238 {
michael@0 239 nsCOMPtr<nsINavHistoryService> history = do_get_NavHistory();
michael@0 240 nsCOMPtr<nsPIPlacesDatabase> database = do_QueryInterface(history);
michael@0 241 do_check_true(database);
michael@0 242
michael@0 243 nsCOMPtr<mozIStorageConnection> dbConn;
michael@0 244 nsresult rv = database->GetDBConnection(getter_AddRefs(dbConn));
michael@0 245 do_check_success(rv);
michael@0 246 return dbConn.forget();
michael@0 247 }
michael@0 248
michael@0 249 /**
michael@0 250 * Get the place record from the database.
michael@0 251 *
michael@0 252 * @param aURI The unique URI of the place we are looking up
michael@0 253 * @param result Out parameter where the result is stored
michael@0 254 */
michael@0 255 void
michael@0 256 do_get_place(nsIURI* aURI, PlaceRecord& result)
michael@0 257 {
michael@0 258 nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
michael@0 259 nsCOMPtr<mozIStorageStatement> stmt;
michael@0 260
michael@0 261 nsCString spec;
michael@0 262 nsresult rv = aURI->GetSpec(spec);
michael@0 263 do_check_success(rv);
michael@0 264
michael@0 265 rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
michael@0 266 "SELECT id, hidden, typed, visit_count, guid FROM moz_places "
michael@0 267 "WHERE url=?1 "
michael@0 268 ), getter_AddRefs(stmt));
michael@0 269 do_check_success(rv);
michael@0 270
michael@0 271 rv = stmt->BindUTF8StringByIndex(0, spec);
michael@0 272 do_check_success(rv);
michael@0 273
michael@0 274 bool hasResults;
michael@0 275 rv = stmt->ExecuteStep(&hasResults);
michael@0 276 do_check_success(rv);
michael@0 277 if (!hasResults) {
michael@0 278 result.id = 0;
michael@0 279 return;
michael@0 280 }
michael@0 281
michael@0 282 rv = stmt->GetInt64(0, &result.id);
michael@0 283 do_check_success(rv);
michael@0 284 rv = stmt->GetInt32(1, &result.hidden);
michael@0 285 do_check_success(rv);
michael@0 286 rv = stmt->GetInt32(2, &result.typed);
michael@0 287 do_check_success(rv);
michael@0 288 rv = stmt->GetInt32(3, &result.visitCount);
michael@0 289 do_check_success(rv);
michael@0 290 rv = stmt->GetUTF8String(4, result.guid);
michael@0 291 do_check_success(rv);
michael@0 292 }
michael@0 293
michael@0 294 /**
michael@0 295 * Gets the most recent visit to a place.
michael@0 296 *
michael@0 297 * @param placeID ID from the moz_places table
michael@0 298 * @param result Out parameter where visit is stored
michael@0 299 */
michael@0 300 void
michael@0 301 do_get_lastVisit(int64_t placeId, VisitRecord& result)
michael@0 302 {
michael@0 303 nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
michael@0 304 nsCOMPtr<mozIStorageStatement> stmt;
michael@0 305
michael@0 306 nsresult rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
michael@0 307 "SELECT id, from_visit, visit_type FROM moz_historyvisits "
michael@0 308 "WHERE place_id=?1 "
michael@0 309 "LIMIT 1"
michael@0 310 ), getter_AddRefs(stmt));
michael@0 311 do_check_success(rv);
michael@0 312
michael@0 313 rv = stmt->BindInt64ByIndex(0, placeId);
michael@0 314 do_check_success(rv);
michael@0 315
michael@0 316 bool hasResults;
michael@0 317 rv = stmt->ExecuteStep(&hasResults);
michael@0 318 do_check_success(rv);
michael@0 319
michael@0 320 if (!hasResults) {
michael@0 321 result.id = 0;
michael@0 322 return;
michael@0 323 }
michael@0 324
michael@0 325 rv = stmt->GetInt64(0, &result.id);
michael@0 326 do_check_success(rv);
michael@0 327 rv = stmt->GetInt64(1, &result.lastVisitId);
michael@0 328 do_check_success(rv);
michael@0 329 rv = stmt->GetInt32(2, &result.transitionType);
michael@0 330 do_check_success(rv);
michael@0 331 }
michael@0 332
michael@0 333 void
michael@0 334 do_wait_async_updates() {
michael@0 335 nsCOMPtr<mozIStorageConnection> db = do_get_db();
michael@0 336 nsCOMPtr<mozIStorageAsyncStatement> stmt;
michael@0 337
michael@0 338 db->CreateAsyncStatement(NS_LITERAL_CSTRING("BEGIN EXCLUSIVE"),
michael@0 339 getter_AddRefs(stmt));
michael@0 340 nsCOMPtr<mozIStoragePendingStatement> pending;
michael@0 341 (void)stmt->ExecuteAsync(nullptr, getter_AddRefs(pending));
michael@0 342
michael@0 343 db->CreateAsyncStatement(NS_LITERAL_CSTRING("COMMIT"),
michael@0 344 getter_AddRefs(stmt));
michael@0 345 nsRefPtr<AsyncStatementSpinner> spinner = new AsyncStatementSpinner();
michael@0 346 (void)stmt->ExecuteAsync(spinner, getter_AddRefs(pending));
michael@0 347
michael@0 348 spinner->SpinUntilCompleted();
michael@0 349 }
michael@0 350
michael@0 351 /**
michael@0 352 * Adds a URI to the database.
michael@0 353 *
michael@0 354 * @param aURI
michael@0 355 * The URI to add to the database.
michael@0 356 */
michael@0 357 void
michael@0 358 addURI(nsIURI* aURI)
michael@0 359 {
michael@0 360 nsCOMPtr<mozilla::IHistory> history = do_GetService(NS_IHISTORY_CONTRACTID);
michael@0 361 do_check_true(history);
michael@0 362 nsresult rv = history->VisitURI(aURI, nullptr, mozilla::IHistory::TOP_LEVEL);
michael@0 363 do_check_success(rv);
michael@0 364
michael@0 365 do_wait_async_updates();
michael@0 366 }
michael@0 367
michael@0 368 static const char TOPIC_PROFILE_CHANGE[] = "profile-before-change";
michael@0 369 static const char TOPIC_PLACES_CONNECTION_CLOSED[] = "places-connection-closed";
michael@0 370
michael@0 371 class WaitForConnectionClosed MOZ_FINAL : public nsIObserver
michael@0 372 {
michael@0 373 nsRefPtr<WaitForTopicSpinner> mSpinner;
michael@0 374 public:
michael@0 375 NS_DECL_ISUPPORTS
michael@0 376
michael@0 377 WaitForConnectionClosed()
michael@0 378 {
michael@0 379 nsCOMPtr<nsIObserverService> os =
michael@0 380 do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
michael@0 381 MOZ_ASSERT(os);
michael@0 382 if (os) {
michael@0 383 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->AddObserver(this, TOPIC_PROFILE_CHANGE, false)));
michael@0 384 }
michael@0 385 mSpinner = new WaitForTopicSpinner(TOPIC_PLACES_CONNECTION_CLOSED);
michael@0 386 }
michael@0 387
michael@0 388 NS_IMETHOD Observe(nsISupports* aSubject,
michael@0 389 const char* aTopic,
michael@0 390 const char16_t* aData)
michael@0 391 {
michael@0 392 nsCOMPtr<nsIObserverService> os =
michael@0 393 do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
michael@0 394 MOZ_ASSERT(os);
michael@0 395 if (os) {
michael@0 396 MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->RemoveObserver(this, aTopic)));
michael@0 397 }
michael@0 398
michael@0 399 mSpinner->Spin();
michael@0 400
michael@0 401 return NS_OK;
michael@0 402 }
michael@0 403 };
michael@0 404
michael@0 405 NS_IMPL_ISUPPORTS(WaitForConnectionClosed, nsIObserver)

mercurial