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