Bug 786234 - Part 5: More detailed test-cases. r=ethanhugg
☠☠ backed out by 2945a260ef00 ☠ ☠
authorByron Campen [:bwc] <docfaraday@gmail.com>
Fri, 17 Jan 2014 17:11:00 -0800
changeset 170544 2d1f70b91712b19c9207fd9c35c6a1d0a3fd4bf0
parent 170543 c8083d830fa6b2fa4fa4e549d4942b64b289a7bd
child 170545 e8c8457299a2d3286606807eaff3ce2d1561ea58
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersethanhugg
bugs786234
milestone30.0a1
Bug 786234 - Part 5: More detailed test-cases. r=ethanhugg
media/webrtc/signaling/test/mediapipeline_unittest.cpp
--- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp
+++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp
@@ -109,17 +109,17 @@ class TransportInfo {
   // if failure occurs before layers setup.
   void FreeLayers() {
     delete loopback_;
     loopback_ = nullptr;
     delete dtls_;
     dtls_ = nullptr;
   }
 
-  void Stop() {
+  void Shutdown() {
     if (loopback_) {
       loopback_->Disconnect();
     }
     loopback_ = nullptr;
     dtls_ = nullptr;
     flow_ = nullptr;
   }
 
@@ -163,40 +163,81 @@ class TestAgent {
       test_utils->sts_target(),
       WrapRunnableRet(audio_->GetStream(), &Fake_MediaStream::Start, &ret));
 
     ASSERT_TRUE(NS_SUCCEEDED(ret));
   }
 
   void StopInt() {
     audio_->GetStream()->Stop();
-    audio_rtp_transport_.Stop();
-    audio_rtcp_transport_.Stop();
-    bundle_transport_.Stop();
-    if (audio_pipeline_)
-      audio_pipeline_->ShutdownTransport_s();
   }
 
   void Stop() {
     MOZ_MTLOG(ML_DEBUG, "Stopping");
 
     if (audio_pipeline_)
       audio_pipeline_->ShutdownMedia_m();
 
     mozilla::SyncRunnable::DispatchToThread(
       test_utils->sts_target(),
       WrapRunnable(this, &TestAgent::StopInt));
+  }
 
-    audio_pipeline_ = nullptr;
+  void Shutdown_s() {
+    audio_rtp_transport_.Shutdown();
+    audio_rtcp_transport_.Shutdown();
+    bundle_transport_.Shutdown();
+    if (audio_pipeline_)
+      audio_pipeline_->ShutdownTransport_s();
+  }
+
+  void Shutdown() {
+    if (audio_pipeline_)
+      audio_pipeline_->ShutdownMedia_m();
+
+    mozilla::SyncRunnable::DispatchToThread(
+      test_utils->sts_target(),
+      WrapRunnable(this, &TestAgent::Shutdown_s));
+  }
+
+  uint32_t GetRemoteSSRC() {
+    uint32_t res = 0;
+    audio_conduit_->GetRemoteSSRC(&res);
+    return res;
+  }
+
+  uint32_t GetLocalSSRC() {
+    uint32_t res = 0;
+    audio_conduit_->GetLocalSSRC(&res);
+    return res;
+  }
+
+  int GetAudioRtpCountSent() {
+    return audio_pipeline_->rtp_packets_sent();
+  }
+
+  int GetAudioRtpCountReceived() {
+    return audio_pipeline_->rtp_packets_received();
+  }
+
+  int GetAudioRtcpCountSent() {
+    return audio_pipeline_->rtcp_packets_sent();
+  }
+
+  int GetAudioRtcpCountReceived() {
+    return audio_pipeline_->rtcp_packets_received();
   }
 
  protected:
   mozilla::AudioCodecConfig audio_config_;
   mozilla::RefPtr<mozilla::MediaSessionConduit> audio_conduit_;
   nsRefPtr<DOMMediaStream> audio_;
+  // TODO(bcampen@mozilla.com): Right now this does not let us test RTCP in
+  // both directions; only the sender's RTCP is sent, but the receiver should
+  // be sending it too.
   mozilla::RefPtr<mozilla::MediaPipeline> audio_pipeline_;
   TransportInfo audio_rtp_transport_;
   TransportInfo audio_rtcp_transport_;
   TransportInfo bundle_transport_;
 };
 
 class TestAgentSend : public TestAgent {
  public:
@@ -233,24 +274,16 @@ class TestAgentSend : public TestAgent {
         1,
         audio_conduit_,
         rtp,
         rtcp);
 
     audio_pipeline_->Init();
   }
 
-  int GetAudioRtpCount() {
-    return audio_pipeline_->rtp_packets_sent();
-  }
-
-  int GetAudioRtcpCount() {
-    return audio_pipeline_->rtcp_packets_received();
-  }
-
   void SetUsingBundle(bool use_bundle) {
     use_bundle_ = use_bundle;
   }
 
  private:
   bool use_bundle_;
 };
 
@@ -281,16 +314,17 @@ class TestAgentReceive : public TestAgen
       ASSERT_FALSE(audio_rtcp_transport_.flow_);
     }
 
     // For now, assume bundle always uses rtcp mux
     RefPtr<TransportFlow> dummy;
     RefPtr<TransportFlow> bundle_transport;
     if (bundle_filter_) {
       bundle_transport = bundle_transport_.flow_;
+      bundle_filter_->AddLocalSSRC(GetLocalSSRC());
     }
 
     audio_pipeline_ = new mozilla::MediaPipelineReceiveAudio(
         test_pc,
         nullptr,
         test_utils->sts_target(),
         audio_->GetStream(), 1, 1,
         static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get()),
@@ -298,46 +332,41 @@ class TestAgentReceive : public TestAgen
         audio_rtcp_transport_.flow_,
         bundle_transport,
         dummy,
         bundle_filter_);
 
     audio_pipeline_->Init();
   }
 
-  int GetAudioRtpCount() {
-    return audio_pipeline_->rtp_packets_received();
-  }
-
-  int GetAudioRtcpCount() {
-    return audio_pipeline_->rtcp_packets_sent();
-  }
-
   void SetBundleFilter(nsAutoPtr<MediaPipelineFilter> filter) {
     bundle_filter_ = filter;
   }
 
   void SetUsingBundle_s(bool decision) {
     audio_pipeline_->SetUsingBundle_s(decision);
   }
 
   void UpdateFilterFromRemoteDescription_s(
       nsAutoPtr<MediaPipelineFilter> filter) {
     audio_pipeline_->UpdateFilterFromRemoteDescription_s(filter);
   }
+
  private:
   nsAutoPtr<MediaPipelineFilter> bundle_filter_;
 };
 
 
 class MediaPipelineTest : public ::testing::Test {
  public:
   ~MediaPipelineTest() {
     p1_.Stop();
     p2_.Stop();
+    p1_.Shutdown();
+    p2_.Shutdown();
   }
 
   // Setup transport.
   void InitTransports(bool aIsRtcpMux) {
     // RTP, p1_ is server, p2_ is client
     mozilla::SyncRunnable::DispatchToThread(
       test_utils->sts_target(),
       WrapRunnableNM(&TestAgent::ConnectRtp, &p2_, &p1_));
@@ -357,17 +386,19 @@ class MediaPipelineTest : public ::testi
   }
 
   // Verify RTP and RTCP
   void TestAudioSend(bool aIsRtcpMux,
                      bool bundle = false,
                      nsAutoPtr<MediaPipelineFilter> localFilter =
                         nsAutoPtr<MediaPipelineFilter>(nullptr),
                      nsAutoPtr<MediaPipelineFilter> remoteFilter =
-                        nsAutoPtr<MediaPipelineFilter>(nullptr)) {
+                        nsAutoPtr<MediaPipelineFilter>(nullptr),
+                     unsigned int ms_until_answer = 500,
+                     unsigned int ms_of_traffic_after_answer = 10000) {
 
     // We do not support testing bundle without rtcp mux, since that doesn't
     // make any sense.
     ASSERT_FALSE(!aIsRtcpMux && bundle);
 
     p1_.SetUsingBundle(bundle);
     p2_.SetBundleFilter(localFilter);
 
@@ -381,55 +412,76 @@ class MediaPipelineTest : public ::testi
     mozilla::SyncRunnable::DispatchToThread(
       test_utils->sts_target(),
       WrapRunnable(&p2_, &TestAgent::CreatePipelines_s, aIsRtcpMux));
 
     p2_.Start();
     p1_.Start();
 
     // Simulate pre-answer traffic
-    PR_Sleep(500);
+    PR_Sleep(ms_until_answer);
 
     mozilla::SyncRunnable::DispatchToThread(
       test_utils->sts_target(),
       WrapRunnable(&p2_, &TestAgentReceive::SetUsingBundle_s, bundle));
 
     if (bundle) {
+      // Leaving remoteFilter not set implies we want to test sunny-day
       if (!remoteFilter) {
         remoteFilter = new MediaPipelineFilter;
+        // Might not be safe, strictly speaking.
+        remoteFilter->AddRemoteSSRC(p1_.GetLocalSSRC());
       }
+
       mozilla::SyncRunnable::DispatchToThread(
           test_utils->sts_target(),
           WrapRunnable(&p2_,
                        &TestAgentReceive::UpdateFilterFromRemoteDescription_s,
                        remoteFilter));
     }
 
 
     // wait for some RTP/RTCP tx and rx to happen
-    PR_Sleep(10000);
-
-    if (bundle) {
-      // Filter should have eaten everything
-      ASSERT_EQ(0, p2_.GetAudioRtpCount());
-    } else {
-      ASSERT_GE(p1_.GetAudioRtpCount(), 40);
-      ASSERT_GE(p2_.GetAudioRtpCount(), 40);
-      ASSERT_GE(p2_.GetAudioRtcpCount(), 1);
-    }
+    PR_Sleep(ms_of_traffic_after_answer);
 
     p1_.Stop();
     p2_.Stop();
+
+    // wait for any packets in flight to arrive
+    PR_Sleep(100);
+
+    p1_.Shutdown();
+    p2_.Shutdown();
+
+    if (!bundle) {
+      // If we are doing bundle, allow the test-case to do this checking.
+      ASSERT_GE(p1_.GetAudioRtpCountSent(), 40);
+      ASSERT_EQ(p1_.GetAudioRtpCountReceived(), p2_.GetAudioRtpCountSent());
+      ASSERT_EQ(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived());
+
+      // Calling ShutdownMedia_m on both pipelines does not stop the flow of
+      // RTCP. So, we might be off by one here.
+      ASSERT_LE(p2_.GetAudioRtcpCountReceived(), p1_.GetAudioRtcpCountSent());
+      ASSERT_GE(p2_.GetAudioRtcpCountReceived() + 1, p1_.GetAudioRtcpCountSent());
+    }
+
   }
 
   void TestAudioReceiverOffersBundle(bool bundle_accepted,
       nsAutoPtr<MediaPipelineFilter> localFilter,
       nsAutoPtr<MediaPipelineFilter> remoteFilter =
-          nsAutoPtr<MediaPipelineFilter>(nullptr)) {
-    TestAudioSend(true, bundle_accepted, localFilter, remoteFilter);
+          nsAutoPtr<MediaPipelineFilter>(nullptr),
+      unsigned int ms_until_answer = 500,
+      unsigned int ms_of_traffic_after_answer = 10000) {
+    TestAudioSend(true,
+                  bundle_accepted,
+                  localFilter,
+                  remoteFilter,
+                  ms_until_answer,
+                  ms_of_traffic_after_answer);
   }
 protected:
   TestAgentSend p1_;
   TestAgentReceive p2_;
 };
 
 class MediaPipelineFilterTest : public ::testing::Test {
   public:
@@ -824,17 +876,43 @@ TEST_F(MediaPipelineTest, TestAudioSendM
 
 TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndDeclined) {
   nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
   TestAudioReceiverOffersBundle(false, filter);
 }
 
 TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAccepted) {
   nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
-  TestAudioReceiverOffersBundle(true, filter);
+  // These durations have to be _extremely_ long to have any assurance that
+  // some RTCP will be sent at all. This is because the first RTCP packet
+  // is sometimes sent before the transports are ready, which causes it to
+  // be dropped.
+  TestAudioReceiverOffersBundle(true,
+                                filter,
+  // We do not specify the filter for the remote description, so it will be
+  // set to something sane after a short time.
+                                nsAutoPtr<MediaPipelineFilter>(),
+                                10000,
+                                10000);
+
+  // Some packets should have been dropped, but not all
+  ASSERT_GT(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived());
+  ASSERT_GT(p2_.GetAudioRtpCountReceived(), 40);
+  ASSERT_GT(p1_.GetAudioRtcpCountSent(), 1);
+  ASSERT_GT(p1_.GetAudioRtcpCountSent(), p2_.GetAudioRtcpCountReceived());
+  ASSERT_GT(p2_.GetAudioRtcpCountReceived(), 0);
+}
+
+TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAcceptedEmptyFilter) {
+  nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
+  nsAutoPtr<MediaPipelineFilter> bad_answer_filter(new MediaPipelineFilter);
+  TestAudioReceiverOffersBundle(true, filter, bad_answer_filter);
+  // Filter is empty, so should drop everything.
+  ASSERT_EQ(0, p2_.GetAudioRtpCountReceived());
+  ASSERT_EQ(0, p2_.GetAudioRtcpCountReceived());
 }
 
 }  // end namespace
 
 
 int main(int argc, char **argv) {
   test_utils = new MtransportTestUtils();
   // Start the tests