Add test for many non-dropped packets in unreliable mode.

These tests document existing behavior; there are notes about where
this behavior is either surprising or wrong.

Bug: chromium:1148951
Change-Id: If9875fb744c44c129ff9949d1bab3d3d99f17b81
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/217520
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34058}
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 3039ec6..82f90df 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -1056,6 +1056,7 @@
       "../rtc_base/synchronization:mutex",
       "../rtc_base/third_party/base64",
       "../rtc_base/third_party/sigslot",
+      "../system_wrappers:field_trial",
       "../system_wrappers:metrics",
       "../test:field_trial",
       "../test:fileutils",
diff --git a/pc/data_channel_integrationtest.cc b/pc/data_channel_integrationtest.cc
index 4b6ae1f..1deeb55 100644
--- a/pc/data_channel_integrationtest.cc
+++ b/pc/data_channel_integrationtest.cc
@@ -27,6 +27,7 @@
 #include "rtc_base/gunit.h"
 #include "rtc_base/ref_counted_object.h"
 #include "rtc_base/virtual_socket_server.h"
+#include "system_wrappers/include/field_trial.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -622,7 +623,7 @@
                  kDefaultTimeout);
 }
 
-TEST_P(DataChannelIntegrationTest, QueuedPacketsGetDeliveredInUnReliableMode) {
+TEST_P(DataChannelIntegrationTest, QueuedPacketsGetDroppedInUnreliableMode) {
   CreatePeerConnectionWrappers();
   ConnectFakeSignaling();
   DataChannelInit init;
@@ -637,6 +638,9 @@
                  kDefaultTimeout);
   // Cause a temporary network outage
   virtual_socket_server()->set_drop_probability(1.0);
+  // Send a few packets. Note that all get dropped only when all packets
+  // fit into the receiver receive window/congestion window, so that they
+  // actually get sent.
   for (int i = 1; i <= 10; i++) {
     caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
   }
@@ -659,6 +663,116 @@
   EXPECT_EQ(2u, callee()->data_observer()->received_message_count());
 }
 
+TEST_P(DataChannelIntegrationTest,
+       QueuedPacketsGetDroppedInLifetimeLimitedMode) {
+  CreatePeerConnectionWrappers();
+  ConnectFakeSignaling();
+  DataChannelInit init;
+  init.maxRetransmitTime = 1;
+  init.ordered = false;
+  caller()->CreateDataChannel(&init);
+  caller()->CreateAndSetAndSignalOffer();
+  ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+  ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
+  caller()->data_channel()->Send(DataBuffer("hello first"));
+  ASSERT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
+                 kDefaultTimeout);
+  // Cause a temporary network outage
+  virtual_socket_server()->set_drop_probability(1.0);
+  for (int i = 1; i <= 200; i++) {
+    caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
+  }
+  // Nothing should be delivered during outage.
+  // We do a short wait to verify that delivery count is still 1,
+  // and to make sure max packet lifetime (which is in ms) is exceeded.
+  WAIT(false, 10);
+  EXPECT_EQ(1u, callee()->data_observer()->received_message_count());
+  // Reverse the network outage.
+  virtual_socket_server()->set_drop_probability(0.0);
+  // Send a new packet, and wait for it to be delivered.
+  caller()->data_channel()->Send(DataBuffer("After block"));
+  EXPECT_EQ_WAIT("After block", callee()->data_observer()->last_message(),
+                 kDefaultTimeout);
+  // Some messages should be lost, but first and last message should have
+  // been delivered.
+  // First, check that the protocol guarantee is preserved.
+  EXPECT_GT(202u, callee()->data_observer()->received_message_count());
+  EXPECT_LE(2u, callee()->data_observer()->received_message_count());
+  // Then, check that observed behavior (lose some messages) has not changed
+  if (webrtc::field_trial::IsEnabled("WebRTC-DataChannel-Dcsctp")) {
+    // DcSctp loses all messages. This is correct.
+    EXPECT_EQ(2u, callee()->data_observer()->received_message_count());
+  } else {
+    // Usrsctp loses some messages, but keeps messages not attempted.
+    // THIS IS THE WRONG BEHAVIOR. According to discussion in
+    // https://github.com/sctplab/usrsctp/issues/584, all these packets
+    // should be discarded.
+    // TODO(bugs.webrtc.org/12731): Fix this.
+    EXPECT_EQ(90u, callee()->data_observer()->received_message_count());
+  }
+}
+
+TEST_P(DataChannelIntegrationTest,
+       SomeQueuedPacketsGetDroppedInMaxRetransmitsMode) {
+  CreatePeerConnectionWrappers();
+  ConnectFakeSignaling();
+  DataChannelInit init;
+  init.maxRetransmits = 0;
+  init.ordered = false;
+  caller()->CreateDataChannel(&init);
+  caller()->CreateAndSetAndSignalOffer();
+  ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+  ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
+  caller()->data_channel()->Send(DataBuffer("hello first"));
+  ASSERT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
+                 kDefaultTimeout);
+  // Cause a temporary network outage
+  virtual_socket_server()->set_drop_probability(1.0);
+  // Fill the buffer until queued data starts to build
+  size_t packet_counter = 0;
+  while (caller()->data_channel()->buffered_amount() < 1 &&
+         packet_counter < 10000) {
+    packet_counter++;
+    caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
+  }
+  if (caller()->data_channel()->buffered_amount()) {
+    RTC_LOG(LS_INFO) << "Buffered data after " << packet_counter << " packets";
+  } else {
+    RTC_LOG(LS_INFO) << "No buffered data after " << packet_counter
+                     << " packets";
+  }
+  // Nothing should be delivered during outage.
+  // We do a short wait to verify that delivery count is still 1.
+  WAIT(false, 10);
+  EXPECT_EQ(1u, callee()->data_observer()->received_message_count());
+  // Reverse the network outage.
+  virtual_socket_server()->set_drop_probability(0.0);
+  // Send a new packet, and wait for it to be delivered.
+  caller()->data_channel()->Send(DataBuffer("After block"));
+  EXPECT_EQ_WAIT("After block", callee()->data_observer()->last_message(),
+                 kDefaultTimeout);
+  // Some messages should be lost, but first and last message should have
+  // been delivered.
+  // Due to the fact that retransmissions are only counted when the packet
+  // goes on the wire, NOT when they are stalled in queue due to
+  // congestion, we expect some of the packets to be delivered, because
+  // congestion prevented them from being sent.
+  // Citation: https://tools.ietf.org/html/rfc7496#section-3.1
+
+  // First, check that the protocol guarantee is preserved.
+  EXPECT_GT(packet_counter,
+            callee()->data_observer()->received_message_count());
+  EXPECT_LE(2u, callee()->data_observer()->received_message_count());
+  // Then, check that observed behavior (lose between 100 and 200 messages)
+  // has not changed.
+  // Usrsctp behavior is different on Android (177) and other platforms (122).
+  // Dcsctp loses 432 packets.
+  EXPECT_GT(2 + packet_counter - 100,
+            callee()->data_observer()->received_message_count());
+  EXPECT_LT(2 + packet_counter - 500,
+            callee()->data_observer()->received_message_count());
+}
+
 INSTANTIATE_TEST_SUITE_P(
     DataChannelIntegrationTest,
     DataChannelIntegrationTest,
diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc
index 89b39e5..81a4cd8 100644
--- a/pc/peer_connection_factory.cc
+++ b/pc/peer_connection_factory.cc
@@ -139,6 +139,7 @@
     case cricket::MEDIA_TYPE_UNSUPPORTED:
       return RtpCapabilities();
   }
+  RTC_DLOG(LS_ERROR) << "Got unexpected MediaType " << kind;
   RTC_CHECK_NOTREACHED();
 }
 
@@ -165,6 +166,7 @@
     case cricket::MEDIA_TYPE_UNSUPPORTED:
       return RtpCapabilities();
   }
+  RTC_DLOG(LS_ERROR) << "Got unexpected MediaType " << kind;
   RTC_CHECK_NOTREACHED();
 }