TestAsyncBlockers.cpp (4863B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "gtest/gtest.h" 7 8 #include "mozilla/SpinEventLoopUntil.h" 9 #include "mozilla/ipc/AsyncBlockers.h" 10 #include "mozilla/gtest/MozHelpers.h" 11 12 #include "nsCOMPtr.h" 13 #include "nsITimer.h" 14 #include "nsINamed.h" 15 16 using namespace mozilla; 17 using namespace mozilla::ipc; 18 19 #define PROCESS_EVENTS_UNTIL(_done) \ 20 SpinEventLoopUntil("TestAsyncBlockers"_ns, [&]() { return _done; }); 21 22 class TestAsyncBlockers : public ::testing::Test { 23 protected: 24 void SetUp() override { 25 SAVE_GDB_SLEEP(mOldSleepDuration); 26 return; 27 } 28 29 void TearDown() final { RESTORE_GDB_SLEEP(mOldSleepDuration); } 30 31 private: 32 #if defined(HAS_GDB_SLEEP_DURATION) 33 unsigned int mOldSleepDuration = 0; 34 #endif // defined(HAS_GDB_SLEEP_DURATION) 35 }; 36 37 class Blocker {}; 38 39 TEST_F(TestAsyncBlockers, Register) { 40 AsyncBlockers blockers; 41 Blocker* blocker = new Blocker(); 42 blockers.Register(blocker); 43 EXPECT_TRUE(true); 44 } 45 46 TEST_F(TestAsyncBlockers, Register_Deregister) { 47 AsyncBlockers blockers; 48 Blocker* blocker = new Blocker(); 49 blockers.Register(blocker); 50 blockers.Deregister(blocker); 51 EXPECT_TRUE(true); 52 } 53 54 TEST_F(TestAsyncBlockers, Register_WaitUntilClear) { 55 AsyncBlockers blockers; 56 bool done = false; 57 58 Blocker* blocker = new Blocker(); 59 blockers.Register(blocker); 60 61 blockers.WaitUntilClear(5 * 1000)->Then(GetCurrentSerialEventTarget(), 62 __func__, [&]() { 63 EXPECT_TRUE(true); 64 done = true; 65 }); 66 67 NS_ProcessPendingEvents(nullptr); 68 69 blockers.Deregister(blocker); 70 71 PROCESS_EVENTS_UNTIL(done); 72 } 73 74 class AsyncBlockerTimerCallback : public nsITimerCallback, public nsINamed { 75 protected: 76 virtual ~AsyncBlockerTimerCallback(); 77 78 public: 79 explicit AsyncBlockerTimerCallback() {} 80 81 NS_DECL_THREADSAFE_ISUPPORTS 82 NS_DECL_NSITIMERCALLBACK 83 NS_DECL_NSINAMED 84 }; 85 86 NS_IMPL_ISUPPORTS(AsyncBlockerTimerCallback, nsITimerCallback, nsINamed) 87 88 AsyncBlockerTimerCallback::~AsyncBlockerTimerCallback() = default; 89 90 NS_IMETHODIMP 91 AsyncBlockerTimerCallback::Notify(nsITimer* timer) { 92 // If we resolve through this, it means 93 // blockers.WaitUntilClear() started to wait for 94 // the completion of the timeout which is not 95 // good. 96 EXPECT_TRUE(false); 97 return NS_OK; 98 } 99 100 NS_IMETHODIMP 101 AsyncBlockerTimerCallback::GetName(nsACString& aName) { 102 aName.AssignLiteral("AsyncBlockerTimerCallback"); 103 return NS_OK; 104 } 105 106 TEST_F(TestAsyncBlockers, NoRegister_WaitUntilClear) { 107 AsyncBlockers blockers; 108 bool done = false; 109 110 nsCOMPtr<nsITimer> timer = NS_NewTimer(); 111 ASSERT_TRUE(timer); 112 113 RefPtr<AsyncBlockerTimerCallback> timerCb = new AsyncBlockerTimerCallback(); 114 timer->InitWithCallback(timerCb, 1 * 1000, nsITimer::TYPE_ONE_SHOT); 115 116 blockers.WaitUntilClear(10 * 1000)->Then(GetCurrentSerialEventTarget(), 117 __func__, [&]() { 118 // If we resolve through this 119 // before the nsITimer it means we 120 // have been resolved before the 5s 121 // timeout 122 EXPECT_TRUE(true); 123 timer->Cancel(); 124 done = true; 125 }); 126 127 PROCESS_EVENTS_UNTIL(done); 128 } 129 130 TEST_F(TestAsyncBlockers, Register_WaitUntilClear_0s) { 131 AsyncBlockers blockers; 132 bool done = false; 133 134 Blocker* blocker = new Blocker(); 135 blockers.Register(blocker); 136 137 blockers.WaitUntilClear(0)->Then(GetCurrentSerialEventTarget(), __func__, 138 [&]() { 139 EXPECT_TRUE(true); 140 done = true; 141 }); 142 143 NS_ProcessPendingEvents(nullptr); 144 145 blockers.Deregister(blocker); 146 147 PROCESS_EVENTS_UNTIL(done); 148 } 149 150 #if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) && !defined(ANDROID) && \ 151 !(defined(XP_DARWIN) && !defined(MOZ_DEBUG)) 152 static void DeregisterEmpty_Test() { 153 mozilla::gtest::DisableCrashReporter(); 154 155 AsyncBlockers blockers; 156 Blocker* blocker = new Blocker(); 157 blockers.Deregister(blocker); 158 } 159 160 TEST_F(TestAsyncBlockers, DeregisterEmpty) { 161 ASSERT_DEATH_IF_SUPPORTED(DeregisterEmpty_Test(), ""); 162 } 163 #endif // defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) && !defined(ANDROID) && 164 // !(defined(XP_DARWIN) && !defined(MOZ_DEBUG)) 165 166 #undef PROCESS_EVENTS_UNTIL