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 }