Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <algorithm>
     12 #include <vector>
     13 
     14 #include "webrtc/p2p/base/pseudotcp.h"
     15 #include "webrtc/base/gunit.h"
     16 #include "webrtc/base/helpers.h"
     17 #include "webrtc/base/messagehandler.h"
     18 #include "webrtc/base/stream.h"
     19 #include "webrtc/base/thread.h"
     20 #include "webrtc/base/timeutils.h"
     21 
     22 using cricket::PseudoTcp;
     23 
     24 static const int kConnectTimeoutMs = 10000;  // ~3 * default RTO of 3000ms
     25 static const int kTransferTimeoutMs = 15000;
     26 static const int kBlockSize = 4096;
     27 
     28 class PseudoTcpForTest : public cricket::PseudoTcp {
     29  public:
     30   PseudoTcpForTest(cricket::IPseudoTcpNotify* notify, uint32_t conv)
     31       : PseudoTcp(notify, conv) {}
     32 
     33   bool isReceiveBufferFull() const {
     34     return PseudoTcp::isReceiveBufferFull();
     35   }
     36 
     37   void disableWindowScale() {
     38     PseudoTcp::disableWindowScale();
     39   }
     40 };
     41 
     42 class PseudoTcpTestBase : public testing::Test,
     43                       public rtc::MessageHandler,
     44                       public cricket::IPseudoTcpNotify {
     45  public:
     46   PseudoTcpTestBase()
     47       : local_(this, 1),
     48         remote_(this, 1),
     49         have_connected_(false),
     50         have_disconnected_(false),
     51         local_mtu_(65535),
     52         remote_mtu_(65535),
     53         delay_(0),
     54         loss_(0) {
     55     // Set use of the test RNG to get predictable loss patterns.
     56     rtc::SetRandomTestMode(true);
     57   }
     58   ~PseudoTcpTestBase() {
     59     // Put it back for the next test.
     60     rtc::SetRandomTestMode(false);
     61   }
     62   void SetLocalMtu(int mtu) {
     63     local_.NotifyMTU(mtu);
     64     local_mtu_ = mtu;
     65   }
     66   void SetRemoteMtu(int mtu) {
     67     remote_.NotifyMTU(mtu);
     68     remote_mtu_ = mtu;
     69   }
     70   void SetDelay(int delay) {
     71     delay_ = delay;
     72   }
     73   void SetLoss(int percent) {
     74     loss_ = percent;
     75   }
     76   void SetOptNagling(bool enable_nagles) {
     77     local_.SetOption(PseudoTcp::OPT_NODELAY, !enable_nagles);
     78     remote_.SetOption(PseudoTcp::OPT_NODELAY, !enable_nagles);
     79   }
     80   void SetOptAckDelay(int ack_delay) {
     81     local_.SetOption(PseudoTcp::OPT_ACKDELAY, ack_delay);
     82     remote_.SetOption(PseudoTcp::OPT_ACKDELAY, ack_delay);
     83   }
     84   void SetOptSndBuf(int size) {
     85     local_.SetOption(PseudoTcp::OPT_SNDBUF, size);
     86     remote_.SetOption(PseudoTcp::OPT_SNDBUF, size);
     87   }
     88   void SetRemoteOptRcvBuf(int size) {
     89     remote_.SetOption(PseudoTcp::OPT_RCVBUF, size);
     90   }
     91   void SetLocalOptRcvBuf(int size) {
     92     local_.SetOption(PseudoTcp::OPT_RCVBUF, size);
     93   }
     94   void DisableRemoteWindowScale() {
     95     remote_.disableWindowScale();
     96   }
     97   void DisableLocalWindowScale() {
     98     local_.disableWindowScale();
     99   }
    100 
    101  protected:
    102   int Connect() {
    103     int ret = local_.Connect();
    104     if (ret == 0) {
    105       UpdateLocalClock();
    106     }
    107     return ret;
    108   }
    109   void Close() {
    110     local_.Close(false);
    111     UpdateLocalClock();
    112   }
    113 
    114   enum { MSG_LPACKET, MSG_RPACKET, MSG_LCLOCK, MSG_RCLOCK, MSG_IOCOMPLETE,
    115          MSG_WRITE};
    116   virtual void OnTcpOpen(PseudoTcp* tcp) {
    117     // Consider ourselves connected when the local side gets OnTcpOpen.
    118     // OnTcpWriteable isn't fired at open, so we trigger it now.
    119     LOG(LS_VERBOSE) << "Opened";
    120     if (tcp == &local_) {
    121       have_connected_ = true;
    122       OnTcpWriteable(tcp);
    123     }
    124   }
    125   // Test derived from the base should override
    126   //   virtual void OnTcpReadable(PseudoTcp* tcp)
    127   // and
    128   //   virtual void OnTcpWritable(PseudoTcp* tcp)
    129   virtual void OnTcpClosed(PseudoTcp* tcp, uint32_t error) {
    130     // Consider ourselves closed when the remote side gets OnTcpClosed.
    131     // TODO: OnTcpClosed is only ever notified in case of error in
    132     // the current implementation.  Solicited close is not (yet) supported.
    133     LOG(LS_VERBOSE) << "Closed";
    134     EXPECT_EQ(0U, error);
    135     if (tcp == &remote_) {
    136       have_disconnected_ = true;
    137     }
    138   }
    139   virtual WriteResult TcpWritePacket(PseudoTcp* tcp,
    140                                      const char* buffer, size_t len) {
    141     // Randomly drop the desired percentage of packets.
    142     // Also drop packets that are larger than the configured MTU.
    143     if (rtc::CreateRandomId() % 100 < static_cast<uint32_t>(loss_)) {
    144       LOG(LS_VERBOSE) << "Randomly dropping packet, size=" << len;
    145     } else if (len > static_cast<size_t>(std::min(local_mtu_, remote_mtu_))) {
    146       LOG(LS_VERBOSE) << "Dropping packet that exceeds path MTU, size=" << len;
    147     } else {
    148       int id = (tcp == &local_) ? MSG_RPACKET : MSG_LPACKET;
    149       std::string packet(buffer, len);
    150       rtc::Thread::Current()->PostDelayed(delay_, this, id,
    151           rtc::WrapMessageData(packet));
    152     }
    153     return WR_SUCCESS;
    154   }
    155 
    156   void UpdateLocalClock() { UpdateClock(&local_, MSG_LCLOCK); }
    157   void UpdateRemoteClock() { UpdateClock(&remote_, MSG_RCLOCK); }
    158   void UpdateClock(PseudoTcp* tcp, uint32_t message) {
    159     long interval = 0;  // NOLINT
    160     tcp->GetNextClock(PseudoTcp::Now(), interval);
    161     interval = std::max<int>(interval, 0L);  // sometimes interval is < 0
    162     rtc::Thread::Current()->Clear(this, message);
    163     rtc::Thread::Current()->PostDelayed(interval, this, message);
    164   }
    165 
    166   virtual void OnMessage(rtc::Message* message) {
    167     switch (message->message_id) {
    168       case MSG_LPACKET: {
    169         const std::string& s(
    170             rtc::UseMessageData<std::string>(message->pdata));
    171         local_.NotifyPacket(s.c_str(), s.size());
    172         UpdateLocalClock();
    173         break;
    174       }
    175       case MSG_RPACKET: {
    176         const std::string& s(
    177             rtc::UseMessageData<std::string>(message->pdata));
    178         remote_.NotifyPacket(s.c_str(), s.size());
    179         UpdateRemoteClock();
    180         break;
    181       }
    182       case MSG_LCLOCK:
    183         local_.NotifyClock(PseudoTcp::Now());
    184         UpdateLocalClock();
    185         break;
    186       case MSG_RCLOCK:
    187         remote_.NotifyClock(PseudoTcp::Now());
    188         UpdateRemoteClock();
    189         break;
    190       default:
    191         break;
    192     }
    193     delete message->pdata;
    194   }
    195 
    196   PseudoTcpForTest local_;
    197   PseudoTcpForTest remote_;
    198   rtc::MemoryStream send_stream_;
    199   rtc::MemoryStream recv_stream_;
    200   bool have_connected_;
    201   bool have_disconnected_;
    202   int local_mtu_;
    203   int remote_mtu_;
    204   int delay_;
    205   int loss_;
    206 };
    207 
    208 class PseudoTcpTest : public PseudoTcpTestBase {
    209  public:
    210   void TestTransfer(int size) {
    211     uint32_t start, elapsed;
    212     size_t received;
    213     // Create some dummy data to send.
    214     send_stream_.ReserveSize(size);
    215     for (int i = 0; i < size; ++i) {
    216       char ch = static_cast<char>(i);
    217       send_stream_.Write(&ch, 1, NULL, NULL);
    218     }
    219     send_stream_.Rewind();
    220     // Prepare the receive stream.
    221     recv_stream_.ReserveSize(size);
    222     // Connect and wait until connected.
    223     start = rtc::Time();
    224     EXPECT_EQ(0, Connect());
    225     EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs);
    226     // Sending will start from OnTcpWriteable and complete when all data has
    227     // been received.
    228     EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs);
    229     elapsed = rtc::TimeSince(start);
    230     recv_stream_.GetSize(&received);
    231     // Ensure we closed down OK and we got the right data.
    232     // TODO: Ensure the errors are cleared properly.
    233     //EXPECT_EQ(0, local_.GetError());
    234     //EXPECT_EQ(0, remote_.GetError());
    235     EXPECT_EQ(static_cast<size_t>(size), received);
    236     EXPECT_EQ(0, memcmp(send_stream_.GetBuffer(),
    237                         recv_stream_.GetBuffer(), size));
    238     LOG(LS_INFO) << "Transferred " << received << " bytes in " << elapsed
    239                  << " ms (" << size * 8 / elapsed << " Kbps)";
    240   }
    241 
    242  private:
    243   // IPseudoTcpNotify interface
    244 
    245   virtual void OnTcpReadable(PseudoTcp* tcp) {
    246     // Stream bytes to the recv stream as they arrive.
    247     if (tcp == &remote_) {
    248       ReadData();
    249 
    250       // TODO: OnTcpClosed() is currently only notified on error -
    251       // there is no on-the-wire equivalent of TCP FIN.
    252       // So we fake the notification when all the data has been read.
    253       size_t received, required;
    254       recv_stream_.GetPosition(&received);
    255       send_stream_.GetSize(&required);
    256       if (received == required)
    257         OnTcpClosed(&remote_, 0);
    258     }
    259   }
    260   virtual void OnTcpWriteable(PseudoTcp* tcp) {
    261     // Write bytes from the send stream when we can.
    262     // Shut down when we've sent everything.
    263     if (tcp == &local_) {
    264       LOG(LS_VERBOSE) << "Flow Control Lifted";
    265       bool done;
    266       WriteData(&done);
    267       if (done) {
    268         Close();
    269       }
    270     }
    271   }
    272 
    273   void ReadData() {
    274     char block[kBlockSize];
    275     size_t position;
    276     int rcvd;
    277     do {
    278       rcvd = remote_.Recv(block, sizeof(block));
    279       if (rcvd != -1) {
    280         recv_stream_.Write(block, rcvd, NULL, NULL);
    281         recv_stream_.GetPosition(&position);
    282         LOG(LS_VERBOSE) << "Received: " << position;
    283       }
    284     } while (rcvd > 0);
    285   }
    286   void WriteData(bool* done) {
    287     size_t position, tosend;
    288     int sent;
    289     char block[kBlockSize];
    290     do {
    291       send_stream_.GetPosition(&position);
    292       if (send_stream_.Read(block, sizeof(block), &tosend, NULL) !=
    293           rtc::SR_EOS) {
    294         sent = local_.Send(block, tosend);
    295         UpdateLocalClock();
    296         if (sent != -1) {
    297           send_stream_.SetPosition(position + sent);
    298           LOG(LS_VERBOSE) << "Sent: " << position + sent;
    299         } else {
    300           send_stream_.SetPosition(position);
    301           LOG(LS_VERBOSE) << "Flow Controlled";
    302         }
    303       } else {
    304         sent = static_cast<int>(tosend = 0);
    305       }
    306     } while (sent > 0);
    307     *done = (tosend == 0);
    308   }
    309 
    310  private:
    311   rtc::MemoryStream send_stream_;
    312   rtc::MemoryStream recv_stream_;
    313 };
    314 
    315 
    316 class PseudoTcpTestPingPong : public PseudoTcpTestBase {
    317  public:
    318   PseudoTcpTestPingPong()
    319       : iterations_remaining_(0),
    320 	sender_(NULL),
    321 	receiver_(NULL),
    322 	bytes_per_send_(0) {
    323   }
    324   void SetBytesPerSend(int bytes) {
    325     bytes_per_send_ = bytes;
    326   }
    327   void TestPingPong(int size, int iterations) {
    328     uint32_t start, elapsed;
    329     iterations_remaining_ = iterations;
    330     receiver_ = &remote_;
    331     sender_ = &local_;
    332     // Create some dummy data to send.
    333     send_stream_.ReserveSize(size);
    334     for (int i = 0; i < size; ++i) {
    335       char ch = static_cast<char>(i);
    336       send_stream_.Write(&ch, 1, NULL, NULL);
    337     }
    338     send_stream_.Rewind();
    339     // Prepare the receive stream.
    340     recv_stream_.ReserveSize(size);
    341     // Connect and wait until connected.
    342     start = rtc::Time();
    343     EXPECT_EQ(0, Connect());
    344     EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs);
    345     // Sending will start from OnTcpWriteable and stop when the required
    346     // number of iterations have completed.
    347     EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs);
    348     elapsed = rtc::TimeSince(start);
    349     LOG(LS_INFO) << "Performed " << iterations << " pings in "
    350                  << elapsed << " ms";
    351   }
    352 
    353  private:
    354   // IPseudoTcpNotify interface
    355 
    356   virtual void OnTcpReadable(PseudoTcp* tcp) {
    357     if (tcp != receiver_) {
    358       LOG_F(LS_ERROR) << "unexpected OnTcpReadable";
    359       return;
    360     }
    361     // Stream bytes to the recv stream as they arrive.
    362     ReadData();
    363     // If we've received the desired amount of data, rewind things
    364     // and send it back the other way!
    365     size_t position, desired;
    366     recv_stream_.GetPosition(&position);
    367     send_stream_.GetSize(&desired);
    368     if (position == desired) {
    369       if (receiver_ == &local_ && --iterations_remaining_ == 0) {
    370         Close();
    371         // TODO: Fake OnTcpClosed() on the receiver for now.
    372         OnTcpClosed(&remote_, 0);
    373         return;
    374       }
    375       PseudoTcp* tmp = receiver_;
    376       receiver_ = sender_;
    377       sender_ = tmp;
    378       recv_stream_.Rewind();
    379       send_stream_.Rewind();
    380       OnTcpWriteable(sender_);
    381     }
    382   }
    383   virtual void OnTcpWriteable(PseudoTcp* tcp) {
    384     if (tcp != sender_)
    385       return;
    386     // Write bytes from the send stream when we can.
    387     // Shut down when we've sent everything.
    388     LOG(LS_VERBOSE) << "Flow Control Lifted";
    389     WriteData();
    390   }
    391 
    392   void ReadData() {
    393     char block[kBlockSize];
    394     size_t position;
    395     int rcvd;
    396     do {
    397       rcvd = receiver_->Recv(block, sizeof(block));
    398       if (rcvd != -1) {
    399         recv_stream_.Write(block, rcvd, NULL, NULL);
    400         recv_stream_.GetPosition(&position);
    401         LOG(LS_VERBOSE) << "Received: " << position;
    402       }
    403     } while (rcvd > 0);
    404   }
    405   void WriteData() {
    406     size_t position, tosend;
    407     int sent;
    408     char block[kBlockSize];
    409     do {
    410       send_stream_.GetPosition(&position);
    411       tosend = bytes_per_send_ ? bytes_per_send_ : sizeof(block);
    412       if (send_stream_.Read(block, tosend, &tosend, NULL) !=
    413           rtc::SR_EOS) {
    414         sent = sender_->Send(block, tosend);
    415         UpdateLocalClock();
    416         if (sent != -1) {
    417           send_stream_.SetPosition(position + sent);
    418           LOG(LS_VERBOSE) << "Sent: " << position + sent;
    419         } else {
    420           send_stream_.SetPosition(position);
    421           LOG(LS_VERBOSE) << "Flow Controlled";
    422         }
    423       } else {
    424         sent = static_cast<int>(tosend = 0);
    425       }
    426     } while (sent > 0);
    427   }
    428 
    429  private:
    430   int iterations_remaining_;
    431   PseudoTcp* sender_;
    432   PseudoTcp* receiver_;
    433   int bytes_per_send_;
    434 };
    435 
    436 // Fill the receiver window until it is full, drain it and then
    437 // fill it with the same amount. This is to test that receiver window
    438 // contracts and enlarges correctly.
    439 class PseudoTcpTestReceiveWindow : public PseudoTcpTestBase {
    440  public:
    441   // Not all the data are transfered, |size| just need to be big enough
    442   // to fill up the receiver window twice.
    443   void TestTransfer(int size) {
    444     // Create some dummy data to send.
    445     send_stream_.ReserveSize(size);
    446     for (int i = 0; i < size; ++i) {
    447       char ch = static_cast<char>(i);
    448       send_stream_.Write(&ch, 1, NULL, NULL);
    449     }
    450     send_stream_.Rewind();
    451 
    452     // Prepare the receive stream.
    453     recv_stream_.ReserveSize(size);
    454 
    455     // Connect and wait until connected.
    456     EXPECT_EQ(0, Connect());
    457     EXPECT_TRUE_WAIT(have_connected_, kConnectTimeoutMs);
    458 
    459     rtc::Thread::Current()->Post(this, MSG_WRITE);
    460     EXPECT_TRUE_WAIT(have_disconnected_, kTransferTimeoutMs);
    461 
    462     ASSERT_EQ(2u, send_position_.size());
    463     ASSERT_EQ(2u, recv_position_.size());
    464 
    465     const size_t estimated_recv_window = EstimateReceiveWindowSize();
    466 
    467     // The difference in consecutive send positions should equal the
    468     // receive window size or match very closely. This verifies that receive
    469     // window is open after receiver drained all the data.
    470     const size_t send_position_diff = send_position_[1] - send_position_[0];
    471     EXPECT_GE(1024u, estimated_recv_window - send_position_diff);
    472 
    473     // Receiver drained the receive window twice.
    474     EXPECT_EQ(2 * estimated_recv_window, recv_position_[1]);
    475   }
    476 
    477   virtual void OnMessage(rtc::Message* message) {
    478     int message_id = message->message_id;
    479     PseudoTcpTestBase::OnMessage(message);
    480 
    481     switch (message_id) {
    482       case MSG_WRITE: {
    483         WriteData();
    484         break;
    485       }
    486       default:
    487         break;
    488     }
    489   }
    490 
    491   uint32_t EstimateReceiveWindowSize() const {
    492     return static_cast<uint32_t>(recv_position_[0]);
    493   }
    494 
    495   uint32_t EstimateSendWindowSize() const {
    496     return static_cast<uint32_t>(send_position_[0] - recv_position_[0]);
    497   }
    498 
    499  private:
    500   // IPseudoTcpNotify interface
    501   virtual void OnTcpReadable(PseudoTcp* tcp) {
    502   }
    503 
    504   virtual void OnTcpWriteable(PseudoTcp* tcp) {
    505   }
    506 
    507   void ReadUntilIOPending() {
    508     char block[kBlockSize];
    509     size_t position;
    510     int rcvd;
    511 
    512     do {
    513       rcvd = remote_.Recv(block, sizeof(block));
    514       if (rcvd != -1) {
    515         recv_stream_.Write(block, rcvd, NULL, NULL);
    516         recv_stream_.GetPosition(&position);
    517         LOG(LS_VERBOSE) << "Received: " << position;
    518       }
    519     } while (rcvd > 0);
    520 
    521     recv_stream_.GetPosition(&position);
    522     recv_position_.push_back(position);
    523 
    524     // Disconnect if we have done two transfers.
    525     if (recv_position_.size() == 2u) {
    526       Close();
    527       OnTcpClosed(&remote_, 0);
    528     } else {
    529       WriteData();
    530     }
    531   }
    532 
    533   void WriteData() {
    534     size_t position, tosend;
    535     int sent;
    536     char block[kBlockSize];
    537     do {
    538       send_stream_.GetPosition(&position);
    539       if (send_stream_.Read(block, sizeof(block), &tosend, NULL) !=
    540           rtc::SR_EOS) {
    541         sent = local_.Send(block, tosend);
    542         UpdateLocalClock();
    543         if (sent != -1) {
    544           send_stream_.SetPosition(position + sent);
    545           LOG(LS_VERBOSE) << "Sent: " << position + sent;
    546         } else {
    547           send_stream_.SetPosition(position);
    548           LOG(LS_VERBOSE) << "Flow Controlled";
    549         }
    550       } else {
    551         sent = static_cast<int>(tosend = 0);
    552       }
    553     } while (sent > 0);
    554     // At this point, we've filled up the available space in the send queue.
    555 
    556     int message_queue_size =
    557         static_cast<int>(rtc::Thread::Current()->size());
    558     // The message queue will always have at least 2 messages, an RCLOCK and
    559     // an LCLOCK, since they are added back on the delay queue at the same time
    560     // they are pulled off and therefore are never really removed.
    561     if (message_queue_size > 2) {
    562       // If there are non-clock messages remaining, attempt to continue sending
    563       // after giving those messages time to process, which should free up the
    564       // send buffer.
    565       rtc::Thread::Current()->PostDelayed(10, this, MSG_WRITE);
    566     } else {
    567       if (!remote_.isReceiveBufferFull()) {
    568         LOG(LS_ERROR) << "This shouldn't happen - the send buffer is full, "
    569                       << "the receive buffer is not, and there are no "
    570                       << "remaining messages to process.";
    571       }
    572       send_stream_.GetPosition(&position);
    573       send_position_.push_back(position);
    574 
    575       // Drain the receiver buffer.
    576       ReadUntilIOPending();
    577     }
    578   }
    579 
    580  private:
    581   rtc::MemoryStream send_stream_;
    582   rtc::MemoryStream recv_stream_;
    583 
    584   std::vector<size_t> send_position_;
    585   std::vector<size_t> recv_position_;
    586 };
    587 
    588 // Basic end-to-end data transfer tests
    589 
    590 // Test the normal case of sending data from one side to the other.
    591 TEST_F(PseudoTcpTest, TestSend) {
    592   SetLocalMtu(1500);
    593   SetRemoteMtu(1500);
    594   TestTransfer(1000000);
    595 }
    596 
    597 // Test sending data with a 50 ms RTT. Transmission should take longer due
    598 // to a slower ramp-up in send rate.
    599 TEST_F(PseudoTcpTest, TestSendWithDelay) {
    600   SetLocalMtu(1500);
    601   SetRemoteMtu(1500);
    602   SetDelay(50);
    603   TestTransfer(1000000);
    604 }
    605 
    606 // Test sending data with packet loss. Transmission should take much longer due
    607 // to send back-off when loss occurs.
    608 TEST_F(PseudoTcpTest, TestSendWithLoss) {
    609   SetLocalMtu(1500);
    610   SetRemoteMtu(1500);
    611   SetLoss(10);
    612   TestTransfer(100000);  // less data so test runs faster
    613 }
    614 
    615 // Test sending data with a 50 ms RTT and 10% packet loss. Transmission should
    616 // take much longer due to send back-off and slower detection of loss.
    617 TEST_F(PseudoTcpTest, TestSendWithDelayAndLoss) {
    618   SetLocalMtu(1500);
    619   SetRemoteMtu(1500);
    620   SetDelay(50);
    621   SetLoss(10);
    622   TestTransfer(100000);  // less data so test runs faster
    623 }
    624 
    625 // Test sending data with 10% packet loss and Nagling disabled.  Transmission
    626 // should take about the same time as with Nagling enabled.
    627 TEST_F(PseudoTcpTest, TestSendWithLossAndOptNaglingOff) {
    628   SetLocalMtu(1500);
    629   SetRemoteMtu(1500);
    630   SetLoss(10);
    631   SetOptNagling(false);
    632   TestTransfer(100000);  // less data so test runs faster
    633 }
    634 
    635 // Test sending data with 10% packet loss and Delayed ACK disabled.
    636 // Transmission should be slightly faster than with it enabled.
    637 TEST_F(PseudoTcpTest, TestSendWithLossAndOptAckDelayOff) {
    638   SetLocalMtu(1500);
    639   SetRemoteMtu(1500);
    640   SetLoss(10);
    641   SetOptAckDelay(0);
    642   TestTransfer(100000);
    643 }
    644 
    645 // Test sending data with 50ms delay and Nagling disabled.
    646 TEST_F(PseudoTcpTest, TestSendWithDelayAndOptNaglingOff) {
    647   SetLocalMtu(1500);
    648   SetRemoteMtu(1500);
    649   SetDelay(50);
    650   SetOptNagling(false);
    651   TestTransfer(100000);  // less data so test runs faster
    652 }
    653 
    654 // Test sending data with 50ms delay and Delayed ACK disabled.
    655 TEST_F(PseudoTcpTest, TestSendWithDelayAndOptAckDelayOff) {
    656   SetLocalMtu(1500);
    657   SetRemoteMtu(1500);
    658   SetDelay(50);
    659   SetOptAckDelay(0);
    660   TestTransfer(100000);  // less data so test runs faster
    661 }
    662 
    663 // Test a large receive buffer with a sender that doesn't support scaling.
    664 TEST_F(PseudoTcpTest, TestSendRemoteNoWindowScale) {
    665   SetLocalMtu(1500);
    666   SetRemoteMtu(1500);
    667   SetLocalOptRcvBuf(100000);
    668   DisableRemoteWindowScale();
    669   TestTransfer(1000000);
    670 }
    671 
    672 // Test a large sender-side receive buffer with a receiver that doesn't support
    673 // scaling.
    674 TEST_F(PseudoTcpTest, TestSendLocalNoWindowScale) {
    675   SetLocalMtu(1500);
    676   SetRemoteMtu(1500);
    677   SetRemoteOptRcvBuf(100000);
    678   DisableLocalWindowScale();
    679   TestTransfer(1000000);
    680 }
    681 
    682 // Test when both sides use window scaling.
    683 TEST_F(PseudoTcpTest, TestSendBothUseWindowScale) {
    684   SetLocalMtu(1500);
    685   SetRemoteMtu(1500);
    686   SetRemoteOptRcvBuf(100000);
    687   SetLocalOptRcvBuf(100000);
    688   TestTransfer(1000000);
    689 }
    690 
    691 // Test using a large window scale value.
    692 TEST_F(PseudoTcpTest, TestSendLargeInFlight) {
    693   SetLocalMtu(1500);
    694   SetRemoteMtu(1500);
    695   SetRemoteOptRcvBuf(100000);
    696   SetLocalOptRcvBuf(100000);
    697   SetOptSndBuf(150000);
    698   TestTransfer(1000000);
    699 }
    700 
    701 TEST_F(PseudoTcpTest, TestSendBothUseLargeWindowScale) {
    702   SetLocalMtu(1500);
    703   SetRemoteMtu(1500);
    704   SetRemoteOptRcvBuf(1000000);
    705   SetLocalOptRcvBuf(1000000);
    706   TestTransfer(10000000);
    707 }
    708 
    709 // Test using a small receive buffer.
    710 TEST_F(PseudoTcpTest, TestSendSmallReceiveBuffer) {
    711   SetLocalMtu(1500);
    712   SetRemoteMtu(1500);
    713   SetRemoteOptRcvBuf(10000);
    714   SetLocalOptRcvBuf(10000);
    715   TestTransfer(1000000);
    716 }
    717 
    718 // Test using a very small receive buffer.
    719 TEST_F(PseudoTcpTest, TestSendVerySmallReceiveBuffer) {
    720   SetLocalMtu(1500);
    721   SetRemoteMtu(1500);
    722   SetRemoteOptRcvBuf(100);
    723   SetLocalOptRcvBuf(100);
    724   TestTransfer(100000);
    725 }
    726 
    727 // Ping-pong (request/response) tests
    728 
    729 // Test sending <= 1x MTU of data in each ping/pong.  Should take <10ms.
    730 TEST_F(PseudoTcpTestPingPong, TestPingPong1xMtu) {
    731   SetLocalMtu(1500);
    732   SetRemoteMtu(1500);
    733   TestPingPong(100, 100);
    734 }
    735 
    736 // Test sending 2x-3x MTU of data in each ping/pong.  Should take <10ms.
    737 TEST_F(PseudoTcpTestPingPong, TestPingPong3xMtu) {
    738   SetLocalMtu(1500);
    739   SetRemoteMtu(1500);
    740   TestPingPong(400, 100);
    741 }
    742 
    743 // Test sending 1x-2x MTU of data in each ping/pong.
    744 // Should take ~1s, due to interaction between Nagling and Delayed ACK.
    745 TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtu) {
    746   SetLocalMtu(1500);
    747   SetRemoteMtu(1500);
    748   TestPingPong(2000, 5);
    749 }
    750 
    751 // Test sending 1x-2x MTU of data in each ping/pong with Delayed ACK off.
    752 // Should take <10ms.
    753 TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtuWithAckDelayOff) {
    754   SetLocalMtu(1500);
    755   SetRemoteMtu(1500);
    756   SetOptAckDelay(0);
    757   TestPingPong(2000, 100);
    758 }
    759 
    760 // Test sending 1x-2x MTU of data in each ping/pong with Nagling off.
    761 // Should take <10ms.
    762 TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtuWithNaglingOff) {
    763   SetLocalMtu(1500);
    764   SetRemoteMtu(1500);
    765   SetOptNagling(false);
    766   TestPingPong(2000, 5);
    767 }
    768 
    769 // Test sending a ping as pair of short (non-full) segments.
    770 // Should take ~1s, due to Delayed ACK interaction with Nagling.
    771 TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegments) {
    772   SetLocalMtu(1500);
    773   SetRemoteMtu(1500);
    774   SetOptAckDelay(5000);
    775   SetBytesPerSend(50); // i.e. two Send calls per payload
    776   TestPingPong(100, 5);
    777 }
    778 
    779 // Test sending ping as a pair of short (non-full) segments, with Nagling off.
    780 // Should take <10ms.
    781 TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegmentsWithNaglingOff) {
    782   SetLocalMtu(1500);
    783   SetRemoteMtu(1500);
    784   SetOptNagling(false);
    785   SetBytesPerSend(50); // i.e. two Send calls per payload
    786   TestPingPong(100, 5);
    787 }
    788 
    789 // Test sending <= 1x MTU of data ping/pong, in two segments, no Delayed ACK.
    790 // Should take ~1s.
    791 TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegmentsWithAckDelayOff) {
    792   SetLocalMtu(1500);
    793   SetRemoteMtu(1500);
    794   SetBytesPerSend(50); // i.e. two Send calls per payload
    795   SetOptAckDelay(0);
    796   TestPingPong(100, 5);
    797 }
    798 
    799 // Test that receive window expands and contract correctly.
    800 TEST_F(PseudoTcpTestReceiveWindow, TestReceiveWindow) {
    801   SetLocalMtu(1500);
    802   SetRemoteMtu(1500);
    803   SetOptNagling(false);
    804   SetOptAckDelay(0);
    805   TestTransfer(1024 * 1000);
    806 }
    807 
    808 // Test setting send window size to a very small value.
    809 TEST_F(PseudoTcpTestReceiveWindow, TestSetVerySmallSendWindowSize) {
    810   SetLocalMtu(1500);
    811   SetRemoteMtu(1500);
    812   SetOptNagling(false);
    813   SetOptAckDelay(0);
    814   SetOptSndBuf(900);
    815   TestTransfer(1024 * 1000);
    816   EXPECT_EQ(900u, EstimateSendWindowSize());
    817 }
    818 
    819 // Test setting receive window size to a value other than default.
    820 TEST_F(PseudoTcpTestReceiveWindow, TestSetReceiveWindowSize) {
    821   SetLocalMtu(1500);
    822   SetRemoteMtu(1500);
    823   SetOptNagling(false);
    824   SetOptAckDelay(0);
    825   SetRemoteOptRcvBuf(100000);
    826   SetLocalOptRcvBuf(100000);
    827   TestTransfer(1024 * 1000);
    828   EXPECT_EQ(100000u, EstimateReceiveWindowSize());
    829 }
    830 
    831 /* Test sending data with mismatched MTUs. We should detect this and reduce
    832 // our packet size accordingly.
    833 // TODO: This doesn't actually work right now. The current code
    834 // doesn't detect if the MTU is set too high on either side.
    835 TEST_F(PseudoTcpTest, TestSendWithMismatchedMtus) {
    836   SetLocalMtu(1500);
    837   SetRemoteMtu(1280);
    838   TestTransfer(1000000);
    839 }
    840 */
    841