Skip to content

Commit

Permalink
Bug 1825259 - Unittest ShutdownBlockingTicket with gtest death tests.…
Browse files Browse the repository at this point in the history
… r=karlt

This uses death tests to be able to run through the shutdown sequence without
affecting the main process.

Differential Revision: https://phabricator.services.mozilla.com/D174094
  • Loading branch information
Pehrsons committed Apr 19, 2023
1 parent 8738689 commit ce9346d
Show file tree
Hide file tree
Showing 2 changed files with 198 additions and 0 deletions.
197 changes: 197 additions & 0 deletions dom/media/gtest/TestMediaUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/* -*- 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)

// 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);

UniquePtr<ShutdownBlockingTicket> ticket;
MOZ_ALWAYS_SUCCEEDS(NS_DispatchBackgroundTask(
MakeAndAddRef<SyncRunnable>(NS_NewRunnableFunction(__func__, [&] {
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);
}

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), "");
}

# undef DISABLE_CRASH_REPORTING

#endif
1 change: 1 addition & 0 deletions dom/media/gtest/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ UNIFIED_SOURCES += [
"TestMediaMIMETypes.cpp",
"TestMediaQueue.cpp",
"TestMediaSpan.cpp",
"TestMediaUtils.cpp",
"TestMP3Demuxer.cpp",
"TestMP4Demuxer.cpp",
"TestMuxer.cpp",
Expand Down

0 comments on commit ce9346d

Please sign in to comment.