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
22using cricket::PseudoTcp;
23
24static const int kConnectTimeoutMs = 10000;  // ~3 * default RTO of 3000ms
25static const int kTransferTimeoutMs = 15000;
26static const int kBlockSize = 4096;
27
28class 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
42class 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
208class 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
316class 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.
439class 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.
591TEST_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.
599TEST_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.
608TEST_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.
617TEST_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.
627TEST_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.
637TEST_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.
646TEST_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.
655TEST_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.
664TEST_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.
674TEST_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.
683TEST_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.
692TEST_F(PseudoTcpTest, TestSendLargeInFlight) {
693  SetLocalMtu(1500);
694  SetRemoteMtu(1500);
695  SetRemoteOptRcvBuf(100000);
696  SetLocalOptRcvBuf(100000);
697  SetOptSndBuf(150000);
698  TestTransfer(1000000);
699}
700
701TEST_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.
710TEST_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.
719TEST_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.
730TEST_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.
737TEST_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.
745TEST_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.
753TEST_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.
762TEST_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.
771TEST_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.
781TEST_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.
791TEST_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.
800TEST_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.
809TEST_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.
820TEST_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.
835TEST_F(PseudoTcpTest, TestSendWithMismatchedMtus) {
836  SetLocalMtu(1500);
837  SetRemoteMtu(1280);
838  TestTransfer(1000000);
839}
840*/
841