diff --git a/media/webrtc/signaling/test/signaling_unittests.cpp b/media/webrtc/signaling/test/signaling_unittests.cpp index 0a428e19f957..2576907e5a68 100644 --- a/media/webrtc/signaling/test/signaling_unittests.cpp +++ b/media/webrtc/signaling/test/signaling_unittests.cpp @@ -48,7 +48,9 @@ #include "mtransport_test_utils.h" #include "gtest_ringbuffer_dumper.h" MtransportTestUtils *test_utils; -nsCOMPtr gThread; +nsCOMPtr gMainThread; +nsCOMPtr gGtestThread; +bool gTestsComplete = false; #ifndef USE_FAKE_MEDIA_STREAMS #error USE_FAKE_MEDIA_STREAMS undefined @@ -213,19 +215,6 @@ enum mediaPipelineFlags }; -static bool SetupGlobalThread() { - if (!gThread) { - nsIThread *thread; - - nsresult rv = NS_NewNamedThread("pseudo-main",&thread); - if (NS_FAILED(rv)) - return false; - - gThread = thread; - } - return true; -} - class TestObserver : public AFakePCObserver { public: @@ -703,7 +692,7 @@ class SignalingAgent { ~SignalingAgent() { - mozilla::SyncRunnable::DispatchToThread(gThread, + mozilla::SyncRunnable::DispatchToThread(gMainThread, WrapRunnable(this, &SignalingAgent::Close)); } @@ -1282,7 +1271,6 @@ class SignalingEnvironment : public ::testing::Environment { class SignalingAgentTest : public ::testing::Test { public: static void SetUpTestCase() { - ASSERT_TRUE(SetupGlobalThread()); } void TearDown() { @@ -1301,7 +1289,7 @@ class SignalingAgentTest : public ::testing::Test { ScopedDeletePtr agent( new SignalingAgent("agent", stun_addr, stun_port)); - agent->Init(gThread); + agent->Init(gMainThread); if (wait_for_gather) { if (!agent->WaitForGatherAllowFail()) @@ -1345,7 +1333,6 @@ public: stun_port_(stun_port) {} static void SetUpTestCase() { - ASSERT_TRUE(SetupGlobalThread()); } void EnsureInit() { @@ -1356,8 +1343,8 @@ public: a1_ = new SignalingAgent(callerName, stun_addr_, stun_port_); a2_ = new SignalingAgent(calleeName, stun_addr_, stun_port_); - a1_->Init(gThread); - a2_->Init(gThread); + a1_->Init(gMainThread); + a2_->Init(gMainThread); if (wait_for_gather_) { WaitForGather(); @@ -1370,7 +1357,6 @@ public: } static void TearDownTestCase() { - gThread = nullptr; } void CreateOffer(sipcc::MediaConstraints& constraints, @@ -1636,12 +1622,51 @@ public: uint16_t stun_port_; }; +static void SetIntPrefOnMainThread(nsCOMPtr prefs, + const char *pref_name, + int new_value) { + MOZ_ASSERT(NS_IsMainThread()); + prefs->SetIntPref(pref_name, new_value); +} + +static void SetMaxFsFr(nsCOMPtr prefs, + int max_fs, + int max_fr) { + gMainThread->Dispatch( + WrapRunnableNM(SetIntPrefOnMainThread, + prefs, + "media.navigator.video.max_fs", + max_fs), + NS_DISPATCH_SYNC); + + gMainThread->Dispatch( + WrapRunnableNM(SetIntPrefOnMainThread, + prefs, + "media.navigator.video.max_fr", + max_fr), + NS_DISPATCH_SYNC); +} + class FsFrPrefClearer { public: FsFrPrefClearer(nsCOMPtr prefs): mPrefs(prefs) {} ~FsFrPrefClearer() { - mPrefs->ClearUserPref("media.navigator.video.max_fs"); - mPrefs->ClearUserPref("media.navigator.video.max_fr"); + gMainThread->Dispatch( + WrapRunnableNM(FsFrPrefClearer::ClearUserPrefOnMainThread, + mPrefs, + "media.navigator.video.max_fs"), + NS_DISPATCH_SYNC); + gMainThread->Dispatch( + WrapRunnableNM(FsFrPrefClearer::ClearUserPrefOnMainThread, + mPrefs, + "media.navigator.video.max_fr"), + NS_DISPATCH_SYNC); + } + + static void ClearUserPrefOnMainThread(nsCOMPtr prefs, + const char *pref_name) { + MOZ_ASSERT(NS_IsMainThread()); + prefs->ClearUserPref(pref_name); } private: nsCOMPtr mPrefs; @@ -3458,8 +3483,7 @@ TEST_F(SignalingTest, MaxFsFrInOffer) ASSERT_TRUE(prefs); FsFrPrefClearer prefClearer(prefs); - prefs->SetIntPref("media.navigator.video.max_fs", 300); - prefs->SetIntPref("media.navigator.video.max_fr", 30); + SetMaxFsFr(prefs, 300, 30); a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); @@ -3479,8 +3503,7 @@ TEST_F(SignalingTest, MaxFsFrInAnswer) FsFrPrefClearer prefClearer(prefs); // We don't want max_fs and max_fr prefs impact SDP at this moment - prefs->SetIntPref("media.navigator.video.max_fs", 0); - prefs->SetIntPref("media.navigator.video.max_fr", 0); + SetMaxFsFr(prefs, 0, 0); a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); @@ -3489,8 +3512,7 @@ TEST_F(SignalingTest, MaxFsFrInAnswer) a2_->SetRemote(TestObserver::OFFER, a1_->offer()); - prefs->SetIntPref("media.navigator.video.max_fs", 600); - prefs->SetIntPref("media.navigator.video.max_fr", 60); + SetMaxFsFr(prefs, 600, 60); a2_->CreateAnswer(constraints, a1_->offer(), OFFER_AV | ANSWER_AV); @@ -3510,8 +3532,7 @@ TEST_F(SignalingTest, MaxFsFrCalleeCodec) FsFrPrefClearer prefClearer(prefs); // We don't want max_fs and max_fr prefs impact SDP at this moment - prefs->SetIntPref("media.navigator.video.max_fs", 0); - prefs->SetIntPref("media.navigator.video.max_fr", 0); + SetMaxFsFr(prefs, 0, 0); a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); @@ -3567,8 +3588,7 @@ TEST_F(SignalingTest, MaxFsFrCallerCodec) FsFrPrefClearer prefClearer(prefs); // We don't want max_fs and max_fr prefs impact SDP at this moment - prefs->SetIntPref("media.navigator.video.max_fs", 0); - prefs->SetIntPref("media.navigator.video.max_fr", 0); + SetMaxFsFr(prefs, 0, 0); a1_->CreateOffer(constraints, OFFER_AV, SHOULD_CHECK_AV); a1_->SetLocal(TestObserver::OFFER, a1_->offer()); @@ -3642,6 +3662,39 @@ static std::string get_environment(const char *name) { return value; } +// This exists to send as an event to trigger shutdown. +static void tests_complete() { + gTestsComplete = true; +} + +// The GTest thread runs this instead of the main thread so it can +// do things like ASSERT_TRUE_WAIT which you could not do on the main thread. +static int gtest_main(int argc, char **argv) { + MOZ_ASSERT(!NS_IsMainThread()); + + ::testing::InitGoogleTest(&argc, argv); + + for(int i=0; ists_target()->Dispatch( + WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC); + + // Set the global shutdown flag and tickle the main thread + // The main thread did not go through Init() so calling Shutdown() + // on it will not work. + gMainThread->Dispatch(WrapRunnableNM(tests_complete), NS_DISPATCH_SYNC); + + return result; +} + + int main(int argc, char **argv) { // This test can cause intermittent oranges on the builders @@ -3667,14 +3720,6 @@ int main(int argc, char **argv) { NSS_NoDB_Init(nullptr); NSS_SetDomesticPolicy(); - ::testing::InitGoogleTest(&argc, argv); - - for(int i=0; ilisteners(); // Adds a listener to the end. Google Test takes the ownership. @@ -3682,15 +3727,28 @@ int main(int argc, char **argv) { test_utils->sts_target()->Dispatch( WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC); - ::testing::AddGlobalTestEnvironment(new test::SignalingEnvironment); - int result = RUN_ALL_TESTS(); + // Set the main thread global which is this thread. + nsIThread *thread; + NS_GetMainThread(&thread); + gMainThread = thread; + MOZ_ASSERT(NS_IsMainThread()); - test_utils->sts_target()->Dispatch( - WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC); + // Now create the GTest thread and run all of the tests on it + // When it is complete it will set gTestsComplete + NS_NewNamedThread("gtest_thread", &thread); + gGtestThread = thread; + + int result; + gGtestThread->Dispatch( + WrapRunnableNMRet(gtest_main, argc, argv, &result), NS_DISPATCH_NORMAL); + + // Here we handle the event queue for dispatches to the main thread + // When the GTest thread is complete it will send one more dispatch + // with gTestsComplete == true. + while (!gTestsComplete && NS_ProcessNextEvent()); + + gGtestThread->Shutdown(); - // Because we don't initialize on the main thread, we can't register for - // XPCOM shutdown callbacks (where the context is usually shut down) -- - // so we need to explictly destroy the context. sipcc::PeerConnectionCtx::Destroy(); delete test_utils;