Test that SCTP succeeds with one MTU and fails with a lower MTU

This pair of tests will ensure that the SCTP layer's response to
MTU size changes has not been modified.

Bug: webrtc:12495
Change-Id: If9776ad399871e9f01b38715594b732e156118ff
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211246
Reviewed-by: Tommi <tommi@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33459}
diff --git a/pc/data_channel_integrationtest.cc b/pc/data_channel_integrationtest.cc
index 91c8870..d4a259b 100644
--- a/pc/data_channel_integrationtest.cc
+++ b/pc/data_channel_integrationtest.cc
@@ -397,6 +397,122 @@
                  kDefaultTimeout);
 }
 
+// This test sets up a call between two parties with an SCTP
+// data channel only, and sends messages of various sizes.
+TEST_P(DataChannelIntegrationTest,
+       EndToEndCallWithSctpDataChannelVariousSizes) {
+  ASSERT_TRUE(CreatePeerConnectionWrappers());
+  ConnectFakeSignaling();
+  // Expect that data channel created on caller side will show up for callee as
+  // well.
+  caller()->CreateDataChannel();
+  caller()->CreateAndSetAndSignalOffer();
+  ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+  // Caller data channel should already exist (it created one). Callee data
+  // channel may not exist yet, since negotiation happens in-band, not in SDP.
+  ASSERT_NE(nullptr, caller()->data_channel());
+  ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
+  EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
+  EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
+
+  for (int message_size = 1; message_size < 100000; message_size *= 2) {
+    std::string data(message_size, 'a');
+    caller()->data_channel()->Send(DataBuffer(data));
+    EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(),
+                   kDefaultTimeout);
+    callee()->data_channel()->Send(DataBuffer(data));
+    EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(),
+                   kDefaultTimeout);
+  }
+  // Specifically probe the area around the MTU size.
+  for (int message_size = 1100; message_size < 1300; message_size += 1) {
+    std::string data(message_size, 'a');
+    caller()->data_channel()->Send(DataBuffer(data));
+    EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(),
+                   kDefaultTimeout);
+    callee()->data_channel()->Send(DataBuffer(data));
+    EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(),
+                   kDefaultTimeout);
+  }
+}
+
+TEST_P(DataChannelIntegrationTest,
+       EndToEndCallWithSctpDataChannelLowestSafeMtu) {
+  // The lowest payload size limit that's tested and found safe for this
+  // application. Note that this is not the safe limit under all conditions;
+  // in particular, the default is not the largest DTLS signature, and
+  // this test does not use TURN.
+  const size_t kLowestSafePayloadSizeLimit = 1225;
+
+  ASSERT_TRUE(CreatePeerConnectionWrappers());
+  ConnectFakeSignaling();
+  // Expect that data channel created on caller side will show up for callee as
+  // well.
+  caller()->CreateDataChannel();
+  caller()->CreateAndSetAndSignalOffer();
+  ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+  // Caller data channel should already exist (it created one). Callee data
+  // channel may not exist yet, since negotiation happens in-band, not in SDP.
+  ASSERT_NE(nullptr, caller()->data_channel());
+  ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
+  EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
+  EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
+
+  virtual_socket_server()->set_max_udp_payload(kLowestSafePayloadSizeLimit);
+  for (int message_size = 1140; message_size < 1240; message_size += 1) {
+    std::string data(message_size, 'a');
+    caller()->data_channel()->Send(DataBuffer(data));
+    ASSERT_EQ_WAIT(data, callee()->data_observer()->last_message(),
+                   kDefaultTimeout);
+    callee()->data_channel()->Send(DataBuffer(data));
+    ASSERT_EQ_WAIT(data, caller()->data_observer()->last_message(),
+                   kDefaultTimeout);
+  }
+}
+
+// This test verifies that lowering the MTU of the connection will cause
+// the datachannel to not transmit reliably.
+// The purpose of this test is to ensure that we know how a too-small MTU
+// error manifests itself.
+TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannelHarmfulMtu) {
+  // The lowest payload size limit that's tested and found safe for this
+  // application in this configuration (see test above).
+  const size_t kLowestSafePayloadSizeLimit = 1225;
+  // The size of the smallest message that fails to be delivered.
+  const size_t kMessageSizeThatIsNotDelivered = 1157;
+
+  ASSERT_TRUE(CreatePeerConnectionWrappers());
+  ConnectFakeSignaling();
+  caller()->CreateDataChannel();
+  caller()->CreateAndSetAndSignalOffer();
+  ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+  ASSERT_NE(nullptr, caller()->data_channel());
+  ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
+  EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
+  EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
+
+  virtual_socket_server()->set_max_udp_payload(kLowestSafePayloadSizeLimit - 1);
+  // Probe for an undelivered or slowly delivered message. The exact
+  // size limit seems to be dependent on the message history, so make the
+  // code easily able to find the current value.
+  bool failure_seen = false;
+  for (size_t message_size = 1110; message_size < 1400; message_size++) {
+    const size_t message_count =
+        callee()->data_observer()->received_message_count();
+    const std::string data(message_size, 'a');
+    caller()->data_channel()->Send(DataBuffer(data));
+    // Wait a very short time for the message to be delivered.
+    WAIT(callee()->data_observer()->received_message_count() > message_count,
+         10);
+    if (callee()->data_observer()->received_message_count() == message_count) {
+      ASSERT_EQ(kMessageSizeThatIsNotDelivered, message_size);
+      failure_seen = true;
+      break;
+    }
+  }
+  ASSERT_TRUE(failure_seen);
+}
+
 // Ensure that when the callee closes an SCTP data channel, the closing
 // procedure results in the data channel being closed for the caller as well.
 TEST_P(DataChannelIntegrationTest, CalleeClosesSctpDataChannel) {