diff --git a/dom/media/gtest/TestMediaUtils.cpp b/dom/media/gtest/TestMediaUtils.cpp new file mode 100644 index 0000000000000..69ae314d3e252 --- /dev/null +++ b/dom/media/gtest/TestMediaUtils.cpp @@ -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 ticket; + MOZ_ALWAYS_SUCCEEDS(NS_DispatchBackgroundTask( + MakeAndAddRef(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 diff --git a/dom/media/gtest/moz.build b/dom/media/gtest/moz.build index d3917ccd270f6..4eb1e61806d72 100644 --- a/dom/media/gtest/moz.build +++ b/dom/media/gtest/moz.build @@ -53,6 +53,7 @@ UNIFIED_SOURCES += [ "TestMediaMIMETypes.cpp", "TestMediaQueue.cpp", "TestMediaSpan.cpp", + "TestMediaUtils.cpp", "TestMP3Demuxer.cpp", "TestMP4Demuxer.cpp", "TestMuxer.cpp",