diff options
Diffstat (limited to 'ipc/glue/test/gtest')
-rw-r--r-- | ipc/glue/test/gtest/TestAsyncBlockers.cpp | 166 | ||||
-rw-r--r-- | ipc/glue/test/gtest/TestUtilityProcess.cpp | 155 | ||||
-rw-r--r-- | ipc/glue/test/gtest/TestUtilityProcessSandboxing.cpp | 66 | ||||
-rw-r--r-- | ipc/glue/test/gtest/moz.build | 22 |
4 files changed, 409 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 diff --git a/ipc/glue/test/gtest/TestUtilityProcess.cpp b/ipc/glue/test/gtest/TestUtilityProcess.cpp new file mode 100644 index 0000000000..c5d19c992f --- /dev/null +++ b/ipc/glue/test/gtest/TestUtilityProcess.cpp @@ -0,0 +1,155 @@ +/* -*- 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/UtilityProcessManager.h" + +#if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX) +# include "nsIAppShellService.h" +# include "nsServiceManagerUtils.h" +#endif // defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX) + +#if defined(XP_WIN) +# include "mozilla/gtest/MozHelpers.h" +# include "mozilla/ipc/UtilityProcessImpl.h" +#endif // defined(XP_WIN) + +#ifdef MOZ_WIDGET_ANDROID +# define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/widget/appshell/android;1" +#endif // MOZ_WIDGET_ANDROID + +#ifdef XP_MACOSX +# define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/widget/appshell/mac;1" +#endif // XP_MACOSX + +using namespace mozilla; +using namespace mozilla::ipc; + +#define WAIT_FOR_EVENTS \ + SpinEventLoopUntil("UtilityProcess::emptyUtil"_ns, [&]() { return done; }); + +bool setupDone = false; + +class UtilityProcess : public ::testing::Test { + protected: + void SetUp() override { + if (setupDone) { + return; + } + +#if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX) + appShell = do_GetService(NS_APPSHELLSERVICE_CONTRACTID); +#endif // defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX) + +#if defined(XP_WIN) && defined(MOZ_SANDBOX) + mozilla::SandboxBroker::GeckoDependentInitialize(); +#endif // defined(XP_WIN) && defined(MOZ_SANDBOX) + + setupDone = true; + } + +#if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX) + nsCOMPtr<nsIAppShellService> appShell; +#endif // defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX) +}; + +TEST_F(UtilityProcess, ProcessManager) { + RefPtr<UtilityProcessManager> utilityProc = + UtilityProcessManager::GetSingleton(); + ASSERT_NE(utilityProc, nullptr); +} + +TEST_F(UtilityProcess, NoProcess) { + RefPtr<UtilityProcessManager> utilityProc = + UtilityProcessManager::GetSingleton(); + EXPECT_NE(utilityProc, nullptr); + + Maybe<int32_t> noPid = + utilityProc->ProcessPid(SandboxingKind::GENERIC_UTILITY); + ASSERT_TRUE(noPid.isNothing()); +} + +TEST_F(UtilityProcess, LaunchProcess) { + bool done = false; + + RefPtr<UtilityProcessManager> utilityProc = + UtilityProcessManager::GetSingleton(); + EXPECT_NE(utilityProc, nullptr); + + int32_t thisPid = base::GetCurrentProcId(); + EXPECT_GE(thisPid, 1); + + utilityProc->LaunchProcess(SandboxingKind::GENERIC_UTILITY) + ->Then( + GetCurrentSerialEventTarget(), __func__, + [&]() mutable { + EXPECT_TRUE(true); + + Maybe<int32_t> utilityPid = + utilityProc->ProcessPid(SandboxingKind::GENERIC_UTILITY); + EXPECT_TRUE(utilityPid.isSome()); + EXPECT_GE(*utilityPid, 1); + EXPECT_NE(*utilityPid, thisPid); + + printf_stderr("UtilityProcess running as %d\n", *utilityPid); + + done = true; + }, + [&](nsresult aError) mutable { + EXPECT_TRUE(false); + done = true; + }); + + WAIT_FOR_EVENTS; +} + +TEST_F(UtilityProcess, DestroyProcess) { + bool done = false; + + RefPtr<UtilityProcessManager> utilityProc = + UtilityProcessManager::GetSingleton(); + + utilityProc->LaunchProcess(SandboxingKind::GENERIC_UTILITY) + ->Then( + GetCurrentSerialEventTarget(), __func__, + [&]() { + Maybe<int32_t> utilityPid = + utilityProc->ProcessPid(SandboxingKind::GENERIC_UTILITY); + EXPECT_TRUE(utilityPid.isSome()); + EXPECT_GE(*utilityPid, 1); + + utilityProc->CleanShutdown(SandboxingKind::GENERIC_UTILITY); + + utilityPid = + utilityProc->ProcessPid(SandboxingKind::GENERIC_UTILITY); + EXPECT_TRUE(utilityPid.isNothing()); + + EXPECT_TRUE(true); + done = true; + }, + [&](nsresult aError) { + EXPECT_TRUE(false); + done = true; + }); + + WAIT_FOR_EVENTS; +} + +#if defined(XP_WIN) +static void LoadLibraryCrash_Test() { + mozilla::gtest::DisableCrashReporter(); + // Just a uuidgen name to have something random + UtilityProcessImpl::LoadLibraryOrCrash( + L"2b49036e-6ba3-400c-a297-38fa1f6c5255.dll"); +} + +TEST_F(UtilityProcess, LoadLibraryCrash) { + ASSERT_DEATH_IF_SUPPORTED(LoadLibraryCrash_Test(), ""); +} +#endif // defined(XP_WIN) + +#undef WAIT_FOR_EVENTS diff --git a/ipc/glue/test/gtest/TestUtilityProcessSandboxing.cpp b/ipc/glue/test/gtest/TestUtilityProcessSandboxing.cpp new file mode 100644 index 0000000000..fff17d63ef --- /dev/null +++ b/ipc/glue/test/gtest/TestUtilityProcessSandboxing.cpp @@ -0,0 +1,66 @@ +/* -*- 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/gtest/MozHelpers.h" +#include "mozilla/ipc/UtilityProcessSandboxing.h" + +using namespace mozilla; +using namespace mozilla::ipc; + +TEST(UtilityProcessSandboxing, ParseNoEnvVar) +{ EXPECT_TRUE(IsUtilitySandboxEnabled("", SandboxingKind::COUNT)); } + +TEST(UtilityProcessSandboxing, ParseEnvVar_DisableAll) +{ EXPECT_FALSE(IsUtilitySandboxEnabled("1", SandboxingKind::COUNT)); } + +TEST(UtilityProcessSandboxing, ParseEnvVar_DontDisableAll) +{ EXPECT_TRUE(IsUtilitySandboxEnabled("0", SandboxingKind::COUNT)); } + +TEST(UtilityProcessSandboxing, ParseEnvVar_DisableGenericOnly) +{ + EXPECT_FALSE( + IsUtilitySandboxEnabled("utility:0", SandboxingKind::GENERIC_UTILITY)); + EXPECT_TRUE(IsUtilitySandboxEnabled("utility:0", SandboxingKind::COUNT)); +} + +#if defined(XP_DARWIN) +TEST(UtilityProcessSandboxing, ParseEnvVar_DisableAppleAudioOnly) +{ + EXPECT_FALSE(IsUtilitySandboxEnabled( + "utility:1", SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA)); + EXPECT_TRUE( + IsUtilitySandboxEnabled("utility:1", SandboxingKind::GENERIC_UTILITY)); +} +#endif // defined(XP_DARWIN) + +#if defined(XP_WIN) +TEST(UtilityProcessSandboxing, ParseEnvVar_DisableWMFOnly) +{ + EXPECT_FALSE(IsUtilitySandboxEnabled( + "utility:1", SandboxingKind::UTILITY_AUDIO_DECODING_WMF)); + EXPECT_TRUE( + IsUtilitySandboxEnabled("utility:1", SandboxingKind::GENERIC_UTILITY)); +} +#endif // defined(XP_WIN) + +TEST(UtilityProcessSandboxing, ParseEnvVar_DisableGenericOnly_Multiples) +{ + EXPECT_FALSE(IsUtilitySandboxEnabled("utility:1,utility:0,utility:2", + SandboxingKind::GENERIC_UTILITY)); +#if defined(XP_DARWIN) + EXPECT_FALSE(IsUtilitySandboxEnabled( + "utility:1,utility:0,utility:2", + SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA)); +#endif // XP_DARWIN +#if defined(XP_WIN) + EXPECT_FALSE( + IsUtilitySandboxEnabled("utility:1,utility:0,utility:2", + SandboxingKind::UTILITY_AUDIO_DECODING_WMF)); +#endif // XP_WIN + EXPECT_TRUE(IsUtilitySandboxEnabled("utility:8,utility:0,utility:6", + SandboxingKind::COUNT)); +} diff --git a/ipc/glue/test/gtest/moz.build b/ipc/glue/test/gtest/moz.build new file mode 100644 index 0000000000..b0af6d80cd --- /dev/null +++ b/ipc/glue/test/gtest/moz.build @@ -0,0 +1,22 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +Library("ipcgluetest") + +UNIFIED_SOURCES = [ + "TestAsyncBlockers.cpp", + "TestUtilityProcess.cpp", + "TestUtilityProcessSandboxing.cpp", +] + +LOCAL_INCLUDES += [ + "/widget", + "/widget/android", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul-gtest" |