tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_true_async.cpp (5520B)


      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 ////////////////////////////////////////////////////////////////////////////////
     10 //// Tests
     11 
     12 TEST(storage_true_async, TrueAsyncStatement)
     13 {
     14  HookSqliteMutex hook;
     15 
     16  nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
     17 
     18  // Start watching for forbidden mutex usage.
     19  watch_for_mutex_use_on_this_thread();
     20 
     21  // - statement with nothing to bind
     22  nsCOMPtr<mozIStorageAsyncStatement> stmt;
     23  db->CreateAsyncStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns,
     24                           getter_AddRefs(stmt));
     25  blocking_async_execute(stmt);
     26  stmt->Finalize();
     27  do_check_false(mutex_used_on_watched_thread);
     28 
     29  // - statement with something to bind ordinally
     30  db->CreateAsyncStatement("INSERT INTO test (id) VALUES (?)"_ns,
     31                           getter_AddRefs(stmt));
     32  stmt->BindInt32ByIndex(0, 1);
     33  blocking_async_execute(stmt);
     34  stmt->Finalize();
     35  do_check_false(mutex_used_on_watched_thread);
     36 
     37  // - statement with something to bind by name
     38  db->CreateAsyncStatement("INSERT INTO test (id) VALUES (:id)"_ns,
     39                           getter_AddRefs(stmt));
     40  nsCOMPtr<mozIStorageBindingParamsArray> paramsArray;
     41  stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
     42  nsCOMPtr<mozIStorageBindingParams> params;
     43  paramsArray->NewBindingParams(getter_AddRefs(params));
     44  params->BindInt32ByName("id"_ns, 2);
     45  paramsArray->AddParams(params);
     46  params = nullptr;
     47  stmt->BindParameters(paramsArray);
     48  paramsArray = nullptr;
     49  blocking_async_execute(stmt);
     50  stmt->Finalize();
     51  do_check_false(mutex_used_on_watched_thread);
     52 
     53  // - now, make sure creating a sync statement does trigger our guard.
     54  // (If this doesn't happen, our test is bunk and it's important to know that.)
     55  nsCOMPtr<mozIStorageStatement> syncStmt;
     56  db->CreateStatement("SELECT * FROM test"_ns, getter_AddRefs(syncStmt));
     57  syncStmt->Finalize();
     58  do_check_true(mutex_used_on_watched_thread);
     59 
     60  blocking_async_close(db);
     61 }
     62 
     63 /**
     64 * Test that cancellation before a statement is run successfully stops the
     65 * statement from executing.
     66 */
     67 TEST(storage_true_async, AsyncCancellation)
     68 {
     69  HookSqliteMutex hook;
     70 
     71  nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
     72 
     73  // -- wedge the thread
     74  nsCOMPtr<nsIThread> target(get_conn_async_thread(db));
     75  do_check_true(target);
     76  RefPtr<ThreadWedger> wedger(new ThreadWedger(target));
     77 
     78  // -- create statements and cancel them
     79  // - async
     80  nsCOMPtr<mozIStorageAsyncStatement> asyncStmt;
     81  db->CreateAsyncStatement(
     82      "CREATE TABLE asyncTable (id INTEGER PRIMARY KEY)"_ns,
     83      getter_AddRefs(asyncStmt));
     84 
     85  RefPtr<AsyncStatementSpinner> asyncSpin(new AsyncStatementSpinner());
     86  nsCOMPtr<mozIStoragePendingStatement> asyncPend;
     87  (void)asyncStmt->ExecuteAsync(asyncSpin, getter_AddRefs(asyncPend));
     88  do_check_true(asyncPend);
     89  asyncPend->Cancel();
     90 
     91  // - sync
     92  nsCOMPtr<mozIStorageStatement> syncStmt;
     93  db->CreateStatement("CREATE TABLE syncTable (id INTEGER PRIMARY KEY)"_ns,
     94                      getter_AddRefs(syncStmt));
     95 
     96  RefPtr<AsyncStatementSpinner> syncSpin(new AsyncStatementSpinner());
     97  nsCOMPtr<mozIStoragePendingStatement> syncPend;
     98  (void)syncStmt->ExecuteAsync(syncSpin, getter_AddRefs(syncPend));
     99  do_check_true(syncPend);
    100  syncPend->Cancel();
    101 
    102  // -- unwedge the async thread
    103  wedger->unwedge();
    104 
    105  // -- verify that both statements report they were canceled
    106  asyncSpin->SpinUntilCompleted();
    107  do_check_true(asyncSpin->completionReason ==
    108                mozIStorageStatementCallback::REASON_CANCELED);
    109 
    110  syncSpin->SpinUntilCompleted();
    111  do_check_true(syncSpin->completionReason ==
    112                mozIStorageStatementCallback::REASON_CANCELED);
    113 
    114  // -- verify that neither statement constructed their tables
    115  nsresult rv;
    116  bool exists;
    117  rv = db->TableExists("asyncTable"_ns, &exists);
    118  do_check_true(rv == NS_OK);
    119  do_check_false(exists);
    120  rv = db->TableExists("syncTable"_ns, &exists);
    121  do_check_true(rv == NS_OK);
    122  do_check_false(exists);
    123 
    124  // -- cleanup
    125  asyncStmt->Finalize();
    126  syncStmt->Finalize();
    127  blocking_async_close(db);
    128 }
    129 
    130 /**
    131 * Test that the destructor for an asynchronous statement which has a
    132 *  sqlite3_stmt will dispatch that statement to the async thread for
    133 *  finalization rather than trying to finalize it on the main thread
    134 *  (and thereby running afoul of our mutex use detector).
    135 */
    136 TEST(storage_true_async, AsyncDestructorFinalizesOnAsyncThread)
    137 {
    138  HookSqliteMutex hook;
    139 
    140  nsCOMPtr<mozIStorageConnection> db(getMemoryDatabase());
    141  watch_for_mutex_use_on_this_thread();
    142 
    143  // -- create an async statement
    144  nsCOMPtr<mozIStorageAsyncStatement> stmt;
    145  db->CreateAsyncStatement("CREATE TABLE test (id INTEGER PRIMARY KEY)"_ns,
    146                           getter_AddRefs(stmt));
    147 
    148  // -- execute it so it gets a sqlite3_stmt that needs to be finalized
    149  blocking_async_execute(stmt);
    150  do_check_false(mutex_used_on_watched_thread);
    151 
    152  // -- forget our reference
    153  stmt = nullptr;
    154 
    155  // -- verify the mutex was not touched
    156  do_check_false(mutex_used_on_watched_thread);
    157 
    158  // -- make sure the statement actually gets finalized / cleanup
    159  // the close will assert if we failed to finalize!
    160  blocking_async_close(db);
    161 }