diff options
Diffstat (limited to 'ipc/glue/test/gtest/TestAsyncBlockers.cpp')
-rw-r--r-- | ipc/glue/test/gtest/TestAsyncBlockers.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/ipc/glue/test/gtest/TestAsyncBlockers.cpp b/ipc/glue/test/gtest/TestAsyncBlockers.cpp new file mode 100644 index 0000000000..6f8d298621 --- /dev/null +++ b/ipc/glue/test/gtest/TestAsyncBlockers.cpp @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gtest/gtest.h" + +#include "mozilla/SpinEventLoopUntil.h" +#include "mozilla/ipc/AsyncBlockers.h" +#include "mozilla/gtest/MozHelpers.h" + +#include "nsCOMPtr.h" +#include "nsITimer.h" +#include "nsINamed.h" + +using namespace mozilla; +using namespace mozilla::ipc; + +#define PROCESS_EVENTS_UNTIL(_done) \ + SpinEventLoopUntil("TestAsyncBlockers"_ns, [&]() { return _done; }); + +class TestAsyncBlockers : public ::testing::Test { + protected: + void SetUp() override { + SAVE_GDB_SLEEP(mOldSleepDuration); + return; + } + + void TearDown() final { RESTORE_GDB_SLEEP(mOldSleepDuration); } + + private: +#if defined(HAS_GDB_SLEEP_DURATION) + unsigned int mOldSleepDuration = 0; +#endif // defined(HAS_GDB_SLEEP_DURATION) +}; + +class Blocker {}; + +TEST_F(TestAsyncBlockers, Register) { + AsyncBlockers blockers; + Blocker* blocker = new Blocker(); + blockers.Register(blocker); + EXPECT_TRUE(true); +} + +TEST_F(TestAsyncBlockers, Register_Deregister) { + AsyncBlockers blockers; + Blocker* blocker = new Blocker(); + blockers.Register(blocker); + blockers.Deregister(blocker); + EXPECT_TRUE(true); +} + +TEST_F(TestAsyncBlockers, Register_WaitUntilClear) { + AsyncBlockers blockers; + bool done = false; + + Blocker* blocker = new Blocker(); + blockers.Register(blocker); + + blockers.WaitUntilClear(5 * 1000)->Then(GetCurrentSerialEventTarget(), + __func__, [&]() { + EXPECT_TRUE(true); + done = true; + }); + + NS_ProcessPendingEvents(nullptr); + + blockers.Deregister(blocker); + + PROCESS_EVENTS_UNTIL(done); +} + +class AsyncBlockerTimerCallback : public nsITimerCallback, public nsINamed { + protected: + virtual ~AsyncBlockerTimerCallback(); + + public: + explicit AsyncBlockerTimerCallback() {} + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSITIMERCALLBACK + NS_DECL_NSINAMED +}; + +NS_IMPL_ISUPPORTS(AsyncBlockerTimerCallback, nsITimerCallback, nsINamed) + +AsyncBlockerTimerCallback::~AsyncBlockerTimerCallback() = default; + +NS_IMETHODIMP +AsyncBlockerTimerCallback::Notify(nsITimer* timer) { + // If we resolve through this, it means + // blockers.WaitUntilClear() started to wait for + // the completion of the timeout which is not + // good. + EXPECT_TRUE(false); + return NS_OK; +} + +NS_IMETHODIMP +AsyncBlockerTimerCallback::GetName(nsACString& aName) { + aName.AssignLiteral("AsyncBlockerTimerCallback"); + return NS_OK; +} + +TEST_F(TestAsyncBlockers, NoRegister_WaitUntilClear) { + AsyncBlockers blockers; + bool done = false; + + nsCOMPtr<nsITimer> timer = NS_NewTimer(); + ASSERT_TRUE(timer); + + RefPtr<AsyncBlockerTimerCallback> timerCb = new AsyncBlockerTimerCallback(); + timer->InitWithCallback(timerCb, 1 * 1000, nsITimer::TYPE_ONE_SHOT); + + blockers.WaitUntilClear(10 * 1000)->Then(GetCurrentSerialEventTarget(), + __func__, [&]() { + // If we resolve through this + // before the nsITimer it means we + // have been resolved before the 5s + // timeout + EXPECT_TRUE(true); + timer->Cancel(); + done = true; + }); + + PROCESS_EVENTS_UNTIL(done); +} + +TEST_F(TestAsyncBlockers, Register_WaitUntilClear_0s) { + AsyncBlockers blockers; + bool done = false; + + Blocker* blocker = new Blocker(); + blockers.Register(blocker); + + blockers.WaitUntilClear(0)->Then(GetCurrentSerialEventTarget(), __func__, + [&]() { + EXPECT_TRUE(true); + done = true; + }); + + NS_ProcessPendingEvents(nullptr); + + blockers.Deregister(blocker); + + PROCESS_EVENTS_UNTIL(done); +} + +#if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) && !defined(ANDROID) && \ + !(defined(XP_DARWIN) && !defined(MOZ_DEBUG)) +static void DeregisterEmpty_Test() { + mozilla::gtest::DisableCrashReporter(); + + AsyncBlockers blockers; + Blocker* blocker = new Blocker(); + blockers.Deregister(blocker); +} + +TEST_F(TestAsyncBlockers, DeregisterEmpty) { + ASSERT_DEATH_IF_SUPPORTED(DeregisterEmpty_Test(), ""); +} +#endif // defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED) && !defined(ANDROID) && + // !(defined(XP_DARWIN) && !defined(MOZ_DEBUG)) + +#undef PROCESS_EVENTS_UNTIL |