TestMediaUtils.cpp (8185B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "MediaUtils.h" 8 #include "gtest/gtest.h" 9 #include "mozilla/AppShutdown.h" 10 #include "mozilla/SyncRunnable.h" 11 #include "mozilla/gtest/MozHelpers.h" 12 13 using namespace mozilla; 14 using namespace mozilla::gtest; 15 using namespace mozilla::media; 16 17 // Spawning the death test child process aborts on Android. 18 #if !defined(ANDROID) && defined(GTEST_HAS_DEATH_TEST) 19 20 // Kept here for reference as it can be handy during development. 21 # define DISABLE_CRASH_REPORTING \ 22 gtest::DisableCrashReporter(); \ 23 ZERO_GDB_SLEEP(); 24 25 void DoCreateTicketBeforeAppShutdownOnMain() { 26 auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor); 27 28 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown); 29 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown); 30 31 Monitor mon("TestMonitor"); 32 bool pastAppShutdown = false; 33 bool backgroundTaskFinished = false; 34 35 auto ticket = ShutdownBlockingTicket::Create( 36 u"Test"_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__); 37 38 MOZ_ALWAYS_SUCCEEDS( 39 NS_DispatchBackgroundTask(NS_NewRunnableFunction(__func__, [&] { 40 TimeStamp now = TimeStamp::Now(); 41 TimeStamp end = now + TimeDuration::FromSeconds(0.2); 42 MonitorAutoLock lock(mon); 43 while (!pastAppShutdown && (end - now) > TimeDuration()) { 44 lock.Wait(end - now); 45 now = TimeStamp::Now(); 46 } 47 EXPECT_FALSE(pastAppShutdown); 48 ticket = nullptr; 49 while (!pastAppShutdown) { 50 lock.Wait(); 51 } 52 EXPECT_TRUE(pastAppShutdown); 53 backgroundTaskFinished = true; 54 lock.Notify(); 55 }))); 56 57 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown); 58 59 { 60 MonitorAutoLock lock(mon); 61 pastAppShutdown = true; 62 lock.Notify(); 63 while (!backgroundTaskFinished) { 64 lock.Wait(); 65 } 66 } 67 68 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM); 69 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry); 70 71 NS_ShutdownXPCOM(nullptr); 72 } 73 74 void DoCreateTicketAfterAppShutdownOnMain() { 75 auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor); 76 77 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown); 78 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown); 79 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown); 80 81 auto ticket = ShutdownBlockingTicket::Create( 82 u"Test"_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__); 83 EXPECT_FALSE(ticket); 84 85 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM); 86 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry); 87 88 NS_ShutdownXPCOM(nullptr); 89 } 90 91 void DoCreateTicketBeforeAppShutdownOffMain() { 92 auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor); 93 94 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown); 95 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown); 96 97 Monitor mon("TestMonitor"); 98 bool pastAppShutdown = false; 99 bool ticketCreated = false; 100 bool backgroundTaskFinished = false; 101 102 MOZ_ALWAYS_SUCCEEDS( 103 NS_DispatchBackgroundTask(NS_NewRunnableFunction(__func__, [&] { 104 MonitorAutoLock lock(mon); 105 auto ticket = ShutdownBlockingTicket::Create( 106 u"Test"_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__); 107 EXPECT_TRUE(ticket); 108 ticketCreated = true; 109 lock.Notify(); 110 111 TimeStamp now = TimeStamp::Now(); 112 TimeStamp end = now + TimeDuration::FromSeconds(0.2); 113 while (!pastAppShutdown && (end - now) > TimeDuration()) { 114 lock.Wait(end - now); 115 now = TimeStamp::Now(); 116 } 117 EXPECT_FALSE(pastAppShutdown); 118 ticket = nullptr; 119 while (!pastAppShutdown) { 120 lock.Wait(); 121 } 122 EXPECT_TRUE(pastAppShutdown); 123 backgroundTaskFinished = true; 124 lock.Notify(); 125 }))); 126 127 { 128 MonitorAutoLock lock(mon); 129 while (!ticketCreated) { 130 lock.Wait(); 131 } 132 } 133 134 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown); 135 136 MonitorAutoLock lock(mon); 137 pastAppShutdown = true; 138 lock.Notify(); 139 while (!backgroundTaskFinished) { 140 lock.Wait(); 141 } 142 143 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM); 144 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry); 145 146 NS_ShutdownXPCOM(nullptr); 147 } 148 149 void DoCreateTicketAfterAppShutdownOffMain() { 150 auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor); 151 152 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown); 153 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown); 154 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown); 155 156 nsCOMPtr<nsISerialEventTarget> bg; 157 MOZ_ALWAYS_SUCCEEDS( 158 NS_CreateBackgroundTaskQueue(__func__, getter_AddRefs(bg))); 159 UniquePtr<ShutdownBlockingTicket> ticket; 160 MOZ_ALWAYS_SUCCEEDS( 161 MakeRefPtr<SyncRunnable>(NS_NewRunnableFunction(__func__, [&] { 162 ticket = ShutdownBlockingTicket::Create( 163 u"Test"_ns, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__); 164 }))->DispatchToThread(bg)); 165 166 EXPECT_FALSE(ticket); 167 168 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM); 169 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry); 170 171 NS_ShutdownXPCOM(nullptr); 172 } 173 174 void DoTwoTicketsWithSameNameBothBlockShutdown() { 175 auto reporter = ScopedTestResultReporter::Create(ExitMode::ExitOnDtor); 176 177 const auto name = u"Test"_ns; 178 auto ticket1 = ShutdownBlockingTicket::Create( 179 name, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__); 180 EXPECT_TRUE(ticket1); 181 auto ticket2 = ShutdownBlockingTicket::Create( 182 name, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__); 183 EXPECT_TRUE(ticket2); 184 185 ticket1 = nullptr; 186 187 // A copyable holder for the std::function in NS_NewTimerWithCallback. 188 auto ticket2Holder = 189 MakeRefPtr<Refcountable<UniquePtr<ShutdownBlockingTicket>>>( 190 ticket2.release()); 191 192 const auto waitBeforeDestroyingTicket = TimeDuration::FromMilliseconds(100); 193 TimeStamp before = TimeStamp::Now(); 194 auto timerResult = NS_NewTimerWithCallback( 195 [t = std::move(ticket2Holder)](nsITimer* aTimer) {}, 196 waitBeforeDestroyingTicket, nsITimer::TYPE_ONE_SHOT, 197 "DoTwoTicketsWithSameNameBothBlockShutdown"_ns); 198 ASSERT_TRUE(timerResult.isOk()); 199 200 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownNetTeardown); 201 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTeardown); 202 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdown); 203 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownQM); 204 AppShutdown::AdvanceShutdownPhase(ShutdownPhase::AppShutdownTelemetry); 205 206 NS_ShutdownXPCOM(nullptr); 207 TimeStamp after = TimeStamp::Now(); 208 EXPECT_GT((after - before).ToMilliseconds(), 209 waitBeforeDestroyingTicket.ToMilliseconds()); 210 } 211 212 TEST(ShutdownBlockingTicketDeathTest, CreateTicketBeforeAppShutdownOnMain) 213 { 214 EXPECT_EXIT(DoCreateTicketBeforeAppShutdownOnMain(), 215 testing::ExitedWithCode(0), ""); 216 } 217 218 TEST(ShutdownBlockingTicketDeathTest, CreateTicketAfterAppShutdownOnMain) 219 { 220 EXPECT_EXIT(DoCreateTicketAfterAppShutdownOnMain(), 221 testing::ExitedWithCode(0), ""); 222 } 223 224 TEST(ShutdownBlockingTicketDeathTest, CreateTicketBeforeAppShutdownOffMain) 225 { 226 EXPECT_EXIT(DoCreateTicketBeforeAppShutdownOffMain(), 227 testing::ExitedWithCode(0), ""); 228 } 229 230 TEST(ShutdownBlockingTicketDeathTest, CreateTicketAfterAppShutdownOffMain) 231 { 232 EXPECT_EXIT(DoCreateTicketAfterAppShutdownOffMain(), 233 testing::ExitedWithCode(0), ""); 234 } 235 236 TEST(ShutdownBlockingTicketDeathTest, TwoTicketsWithSameNameBothBlockShutdown) 237 { 238 EXPECT_EXIT(DoTwoTicketsWithSameNameBothBlockShutdown(), 239 testing::ExitedWithCode(0), ""); 240 } 241 242 # undef DISABLE_CRASH_REPORTING 243 244 #endif