mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 20:30:41 +00:00
244 lines
7.9 KiB
C++
244 lines
7.9 KiB
C++
/* -*- 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 "MediaUtils.h"
|
|
#include "mozilla/AppShutdown.h"
|
|
#include "mozilla/SyncRunnable.h"
|
|
#include "mozilla/gtest/MozHelpers.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::gtest;
|
|
using namespace mozilla::media;
|
|
|
|
// Spawning the death test child process aborts on Android.
|
|
#if !defined(ANDROID) && defined(GTEST_HAS_DEATH_TEST)
|
|
|
|
// Kept here for reference as it can be handy during development.
|
|
# define DISABLE_CRASH_REPORTING \
|
|
gtest::DisableCrashReporter(); \
|
|
ZERO_GDB_SLEEP();
|
|
|
|
void DoCreateTicketBeforeAppShutdownOnMain() {
|
|
auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor);
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown);
|
|
|
|
Monitor mon("TestMonitor");
|
|
bool pastAppShutdown = false;
|
|
bool backgroundTaskFinished = false;
|
|
|
|
UniquePtr ticket = ShutdownBlockingTicket::Create(
|
|
u"Test"_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__);
|
|
|
|
MOZ_ALWAYS_SUCCEEDS(
|
|
NS_DispatchBackgroundTask(NS_NewRunnableFunction(__func__, [&] {
|
|
TimeStamp now = TimeStamp::Now();
|
|
TimeStamp end = now + TimeDuration::FromSeconds(0.2);
|
|
MonitorAutoLock lock(mon);
|
|
while (!pastAppShutdown && (end - now) > TimeDuration()) {
|
|
lock.Wait(end - now);
|
|
now = TimeStamp::Now();
|
|
}
|
|
EXPECT_FALSE(pastAppShutdown);
|
|
ticket = nullptr;
|
|
while (!pastAppShutdown) {
|
|
lock.Wait();
|
|
}
|
|
EXPECT_TRUE(pastAppShutdown);
|
|
backgroundTaskFinished = true;
|
|
lock.Notify();
|
|
})));
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown);
|
|
|
|
{
|
|
MonitorAutoLock lock(mon);
|
|
pastAppShutdown = true;
|
|
lock.Notify();
|
|
while (!backgroundTaskFinished) {
|
|
lock.Wait();
|
|
}
|
|
}
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry);
|
|
|
|
NS_ShutdownXPCOM(nullptr);
|
|
}
|
|
|
|
void DoCreateTicketAfterAppShutdownOnMain() {
|
|
auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor);
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown);
|
|
|
|
auto ticket = ShutdownBlockingTicket::Create(
|
|
u"Test"_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__);
|
|
EXPECT_FALSE(ticket);
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry);
|
|
|
|
NS_ShutdownXPCOM(nullptr);
|
|
}
|
|
|
|
void DoCreateTicketBeforeAppShutdownOffMain() {
|
|
auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor);
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown);
|
|
|
|
Monitor mon("TestMonitor");
|
|
bool pastAppShutdown = false;
|
|
bool ticketCreated = false;
|
|
bool backgroundTaskFinished = false;
|
|
|
|
MOZ_ALWAYS_SUCCEEDS(
|
|
NS_DispatchBackgroundTask(NS_NewRunnableFunction(__func__, [&] {
|
|
MonitorAutoLock lock(mon);
|
|
auto ticket = ShutdownBlockingTicket::Create(
|
|
u"Test"_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__);
|
|
EXPECT_TRUE(ticket);
|
|
ticketCreated = true;
|
|
lock.Notify();
|
|
|
|
TimeStamp now = TimeStamp::Now();
|
|
TimeStamp end = now + TimeDuration::FromSeconds(0.2);
|
|
while (!pastAppShutdown && (end - now) > TimeDuration()) {
|
|
lock.Wait(end - now);
|
|
now = TimeStamp::Now();
|
|
}
|
|
EXPECT_FALSE(pastAppShutdown);
|
|
ticket = nullptr;
|
|
while (!pastAppShutdown) {
|
|
lock.Wait();
|
|
}
|
|
EXPECT_TRUE(pastAppShutdown);
|
|
backgroundTaskFinished = true;
|
|
lock.Notify();
|
|
})));
|
|
|
|
{
|
|
MonitorAutoLock lock(mon);
|
|
while (!ticketCreated) {
|
|
lock.Wait();
|
|
}
|
|
}
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown);
|
|
|
|
MonitorAutoLock lock(mon);
|
|
pastAppShutdown = true;
|
|
lock.Notify();
|
|
while (!backgroundTaskFinished) {
|
|
lock.Wait();
|
|
}
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry);
|
|
|
|
NS_ShutdownXPCOM(nullptr);
|
|
}
|
|
|
|
void DoCreateTicketAfterAppShutdownOffMain() {
|
|
auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor);
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown);
|
|
|
|
nsCOMPtr<nsISerialEventTarget> bg;
|
|
MOZ_ALWAYS_SUCCEEDS(
|
|
NS_CreateBackgroundTaskQueue(__func__, getter_AddRefs(bg)));
|
|
UniquePtr<ShutdownBlockingTicket> ticket;
|
|
MOZ_ALWAYS_SUCCEEDS(
|
|
MakeRefPtr<SyncRunnable>(NS_NewRunnableFunction(__func__, [&] {
|
|
ticket = ShutdownBlockingTicket::Create(
|
|
u"Test"_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__);
|
|
}))->DispatchToThread(bg));
|
|
|
|
EXPECT_FALSE(ticket);
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry);
|
|
|
|
NS_ShutdownXPCOM(nullptr);
|
|
}
|
|
|
|
void DoTwoTicketsWithSameNameBothBlockShutdown() {
|
|
auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor);
|
|
|
|
const auto name = u"Test"_ns;
|
|
auto ticket1 = ShutdownBlockingTicket::Create(
|
|
name, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__);
|
|
EXPECT_TRUE(ticket1);
|
|
auto ticket2 = ShutdownBlockingTicket::Create(
|
|
name, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__);
|
|
EXPECT_TRUE(ticket2);
|
|
|
|
ticket1 = nullptr;
|
|
|
|
// A copyable holder for the std::function in NS_NewTimerWithCallback.
|
|
auto ticket2Holder =
|
|
MakeRefPtr<Refcountable<UniquePtr<ShutdownBlockingTicket>>>(
|
|
ticket2.release());
|
|
|
|
const auto waitBeforeDestroyingTicket = TimeDuration::FromMilliseconds(100);
|
|
TimeStamp before = TimeStamp::Now();
|
|
auto timerResult = NS_NewTimerWithCallback(
|
|
[t = std::move(ticket2Holder)](nsITimer* aTimer) {},
|
|
waitBeforeDestroyingTicket, nsITimer::TYPE_ONE_SHOT, __func__);
|
|
ASSERT_TRUE(timerResult.isOk());
|
|
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM);
|
|
AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry);
|
|
|
|
NS_ShutdownXPCOM(nullptr);
|
|
TimeStamp after = TimeStamp::Now();
|
|
EXPECT_GT((after - before).ToMilliseconds(),
|
|
waitBeforeDestroyingTicket.ToMilliseconds());
|
|
}
|
|
|
|
TEST(ShutdownBlockingTicketDeathTest, CreateTicketBeforeAppShutdownOnMain)
|
|
{
|
|
EXPECT_EXIT(DoCreateTicketBeforeAppShutdownOnMain(),
|
|
testing::ExitedWithCode(0), "");
|
|
}
|
|
|
|
TEST(ShutdownBlockingTicketDeathTest, CreateTicketAfterAppShutdownOnMain)
|
|
{
|
|
EXPECT_EXIT(DoCreateTicketAfterAppShutdownOnMain(),
|
|
testing::ExitedWithCode(0), "");
|
|
}
|
|
|
|
TEST(ShutdownBlockingTicketDeathTest, CreateTicketBeforeAppShutdownOffMain)
|
|
{
|
|
EXPECT_EXIT(DoCreateTicketBeforeAppShutdownOffMain(),
|
|
testing::ExitedWithCode(0), "");
|
|
}
|
|
|
|
TEST(ShutdownBlockingTicketDeathTest, CreateTicketAfterAppShutdownOffMain)
|
|
{
|
|
EXPECT_EXIT(DoCreateTicketAfterAppShutdownOffMain(),
|
|
testing::ExitedWithCode(0), "");
|
|
}
|
|
|
|
TEST(ShutdownBlockingTicketDeathTest, TwoTicketsWithSameNameBothBlockShutdown)
|
|
{
|
|
EXPECT_EXIT(DoTwoTicketsWithSameNameBothBlockShutdown(),
|
|
testing::ExitedWithCode(0), "");
|
|
}
|
|
|
|
# undef DISABLE_CRASH_REPORTING
|
|
|
|
#endif
|