tor-browser

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

test_interruptSynchronousConnection.cpp (2901B)


      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 "gtest/gtest.h"
      8 
      9 #include "storage_test_harness.h"
     10 
     11 #include "mozilla/Atomics.h"
     12 #include "mozilla/SpinEventLoopUntil.h"
     13 
     14 class SynchronousConnectionInterruptionTest : public ::testing::Test {
     15 protected:
     16  void SetUp() override {
     17    mConnection =
     18        getDatabase(nullptr, mozIStorageService::CONNECTION_INTERRUPTIBLE);
     19    ASSERT_TRUE(mConnection);
     20 
     21    ASSERT_EQ(NS_OK, NS_NewNamedThread("Test Thread", getter_AddRefs(mThread)));
     22  }
     23 
     24  void TearDown() override {
     25    // We might close the database connection early in test cases.
     26    (void)mConnection->Close();
     27 
     28    ASSERT_EQ(NS_OK, mThread->Shutdown());
     29  }
     30 
     31  nsCOMPtr<mozIStorageConnection> mConnection;
     32 
     33  nsCOMPtr<nsIThread> mThread;
     34 
     35  mozilla::Atomic<nsresult> mRv = mozilla::Atomic<nsresult>(NS_ERROR_FAILURE);
     36 
     37  mozilla::Atomic<bool> mDone{false};
     38 };
     39 
     40 TEST_F(SynchronousConnectionInterruptionTest,
     41       shouldBeAbleToInterruptInfiniteOperation) {
     42  // Delay is modest because we don't want to get interrupted by
     43  // some unrelated hang or memory guard
     44  const uint32_t delayMs = 500;
     45 
     46  ASSERT_EQ(NS_OK, mThread->DelayedDispatch(
     47                       NS_NewRunnableFunction("InterruptRunnable",
     48                                              [this]() {
     49                                                mRv = mConnection->Interrupt();
     50                                                mDone = true;
     51                                              }),
     52                       delayMs));
     53 
     54  const nsCString infiniteQuery =
     55      "WITH RECURSIVE test(n) "
     56      "AS (VALUES(1) UNION ALL SELECT n + 1 FROM test) "
     57      "SELECT t.n FROM test, test AS t;"_ns;
     58  nsCOMPtr<mozIStorageStatement> stmt;
     59  ASSERT_EQ(NS_OK,
     60            mConnection->CreateStatement(infiniteQuery, getter_AddRefs(stmt)));
     61 
     62  ASSERT_EQ(NS_ERROR_ABORT, stmt->Execute());
     63  ASSERT_EQ(NS_OK, stmt->Finalize());
     64 
     65  ASSERT_TRUE(mDone);
     66  ASSERT_EQ(NS_OK, mRv);
     67 
     68  ASSERT_EQ(NS_OK, mConnection->Close());
     69 }
     70 
     71 TEST_F(SynchronousConnectionInterruptionTest, interruptAfterCloseWillFail) {
     72  ASSERT_EQ(NS_OK, mConnection->Close());
     73 
     74  ASSERT_EQ(NS_OK, mThread->Dispatch(
     75                       NS_NewRunnableFunction("InterruptRunnable", [this]() {
     76                         mRv = mConnection->Interrupt();
     77                         mDone = true;
     78                       })));
     79 
     80  ASSERT_TRUE(mozilla::SpinEventLoopUntil("interruptAfterCloseWillFail"_ns,
     81                                          [this]() -> bool { return mDone; }));
     82 
     83  ASSERT_EQ(NS_ERROR_NOT_INITIALIZED, mRv);
     84 
     85  ASSERT_EQ(NS_ERROR_NOT_INITIALIZED, mConnection->Close());
     86 }