- add sources.
[platform/framework/web/crosswalk.git] / src / net / quic / congestion_control / tcp_cubic_sender_test.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/logging.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "net/quic/congestion_control/tcp_cubic_sender.h"
8 #include "net/quic/congestion_control/tcp_receiver.h"
9 #include "net/quic/test_tools/mock_clock.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace net {
13 namespace test {
14
15 const uint32 kDefaultWindowTCP = 10 * kDefaultTCPMSS;
16
17 // TODO(ianswett): Remove 10000 once b/10075719 is fixed.
18 const QuicTcpCongestionWindow kDefaultMaxCongestionWindowTCP = 10000;
19
20 class TcpCubicSenderPeer : public TcpCubicSender {
21  public:
22   TcpCubicSenderPeer(const QuicClock* clock,
23                      bool reno,
24                      QuicTcpCongestionWindow max_tcp_congestion_window)
25       : TcpCubicSender(clock, reno, max_tcp_congestion_window) {
26   }
27
28   QuicTcpCongestionWindow congestion_window() {
29     return congestion_window_;
30   }
31
32   using TcpCubicSender::AvailableSendWindow;
33   using TcpCubicSender::SendWindow;
34   using TcpCubicSender::AckAccounting;
35 };
36
37 class TcpCubicSenderTest : public ::testing::Test {
38  protected:
39   TcpCubicSenderTest()
40       : rtt_(QuicTime::Delta::FromMilliseconds(60)),
41         one_ms_(QuicTime::Delta::FromMilliseconds(1)),
42         sender_(new TcpCubicSenderPeer(&clock_, true,
43                                        kDefaultMaxCongestionWindowTCP)),
44         receiver_(new TcpReceiver()),
45         sequence_number_(1),
46         acked_sequence_number_(0) {
47   }
48
49   void SendAvailableSendWindow() {
50     QuicByteCount bytes_to_send = sender_->AvailableSendWindow();
51     while (bytes_to_send > 0) {
52       QuicByteCount bytes_in_packet = std::min(kDefaultTCPMSS, bytes_to_send);
53       sender_->OnPacketSent(clock_.Now(), sequence_number_++, bytes_in_packet,
54                             NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
55       bytes_to_send -= bytes_in_packet;
56       if (bytes_to_send > 0) {
57         EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
58                         HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
59       }
60     }
61   }
62   // Normal is that TCP acks every other segment.
63   void AckNPackets(int n) {
64     for (int i = 0; i < n; ++i) {
65       acked_sequence_number_++;
66       sender_->OnIncomingAck(acked_sequence_number_, kDefaultTCPMSS, rtt_);
67     }
68     clock_.AdvanceTime(one_ms_);  // 1 millisecond.
69   }
70
71   const QuicTime::Delta rtt_;
72   const QuicTime::Delta one_ms_;
73   MockClock clock_;
74   SendAlgorithmInterface::SentPacketsMap not_used_;
75   scoped_ptr<TcpCubicSenderPeer> sender_;
76   scoped_ptr<TcpReceiver> receiver_;
77   QuicPacketSequenceNumber sequence_number_;
78   QuicPacketSequenceNumber acked_sequence_number_;
79 };
80
81 TEST_F(TcpCubicSenderTest, SimpleSender) {
82   QuicCongestionFeedbackFrame feedback;
83   // At startup make sure we are at the default.
84   EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableSendWindow());
85   EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
86   // At startup make sure we can send.
87   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
88       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
89   // Get default QuicCongestionFeedbackFrame from receiver.
90   ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
91   sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
92                                                  not_used_);
93   // Make sure we can send.
94   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
95       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
96   // And that window is un-affected.
97   EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableSendWindow());
98   EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
99
100   // A retransmit should always return 0.
101   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
102       NACK_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
103 }
104
105 TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
106   const int kNumberOfAck = 20;
107   QuicCongestionFeedbackFrame feedback;
108   // At startup make sure we can send.
109   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
110       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
111   // Get default QuicCongestionFeedbackFrame from receiver.
112   ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
113   sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
114                                                  not_used_);
115   // Make sure we can send.
116   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
117       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
118
119   for (int n = 0; n < kNumberOfAck; ++n) {
120     // Send our full send window.
121     SendAvailableSendWindow();
122     AckNPackets(2);
123   }
124   QuicByteCount bytes_to_send = sender_->SendWindow();
125   EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAck,
126             bytes_to_send);
127 }
128
129 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) {
130   // Make sure that we fall out of slow start when we send ACK train longer
131   // than half the RTT, in this test case 30ms, which is more than 30 calls to
132   // Ack2Packets in one round.
133   // Since we start at 10 packet first round will be 5 second round 10 etc
134   // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30
135   const int kNumberOfAck = 65;
136   QuicCongestionFeedbackFrame feedback;
137   // At startup make sure we can send.
138   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
139       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
140   // Get default QuicCongestionFeedbackFrame from receiver.
141   ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
142   sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
143                                                  not_used_);
144   // Make sure we can send.
145   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
146       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
147
148   for (int n = 0; n < kNumberOfAck; ++n) {
149     // Send our full send window.
150     SendAvailableSendWindow();
151     AckNPackets(2);
152   }
153   QuicByteCount expected_send_window =
154       kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAck);
155   EXPECT_EQ(expected_send_window, sender_->SendWindow());
156   EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
157   // We should now have fallen out of slow start.
158   SendAvailableSendWindow();
159   AckNPackets(2);
160   expected_send_window += kDefaultTCPMSS;
161   EXPECT_EQ(expected_send_window, sender_->SendWindow());
162
163   // Testing Reno phase.
164   // We should need 141(65*2+1+10) ACK:ed packets before increasing window by
165   // one.
166   for (int m = 0; m < 70; ++m) {
167     SendAvailableSendWindow();
168     AckNPackets(2);
169     EXPECT_EQ(expected_send_window, sender_->SendWindow());
170   }
171   SendAvailableSendWindow();
172   AckNPackets(2);
173   expected_send_window += kDefaultTCPMSS;
174   EXPECT_EQ(expected_send_window, sender_->SendWindow());
175 }
176
177 TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
178   // Make sure that we fall out of slow start when we encounter a packet loss.
179   const int kNumberOfAck = 10;
180   QuicCongestionFeedbackFrame feedback;
181   // At startup make sure we can send.
182   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
183       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
184   // Get default QuicCongestionFeedbackFrame from receiver.
185   ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
186   sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
187                                                  not_used_);
188   // Make sure we can send.
189   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
190       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
191
192   for (int i = 0; i < kNumberOfAck; ++i) {
193     // Send our full send window.
194     SendAvailableSendWindow();
195     AckNPackets(2);
196   }
197   SendAvailableSendWindow();
198   QuicByteCount expected_send_window = kDefaultWindowTCP +
199       (kDefaultTCPMSS * 2 * kNumberOfAck);
200   EXPECT_EQ(expected_send_window, sender_->SendWindow());
201
202   sender_->OnIncomingLoss(clock_.Now());
203
204   // Make sure that we should not send right now.
205   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
206       HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsInfinite());
207
208   // We should now have fallen out of slow start.
209   // We expect window to be cut in half.
210   expected_send_window /= 2;
211   EXPECT_EQ(expected_send_window, sender_->SendWindow());
212
213   // Testing Reno phase.
214   // We need to ack half of the pending packet before we can send again.
215   int number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
216   AckNPackets(number_of_packets_in_window);
217   EXPECT_EQ(expected_send_window, sender_->SendWindow());
218   EXPECT_EQ(0u, sender_->AvailableSendWindow());
219
220   AckNPackets(1);
221   expected_send_window += kDefaultTCPMSS;
222   number_of_packets_in_window++;
223   EXPECT_EQ(expected_send_window, sender_->SendWindow());
224
225   // We should need number_of_packets_in_window ACK:ed packets before
226   // increasing window by one.
227   for (int k = 0; k < number_of_packets_in_window; ++k) {
228     SendAvailableSendWindow();
229     AckNPackets(1);
230     EXPECT_EQ(expected_send_window, sender_->SendWindow());
231   }
232   SendAvailableSendWindow();
233   AckNPackets(1);
234   expected_send_window += kDefaultTCPMSS;
235   EXPECT_EQ(expected_send_window, sender_->SendWindow());
236 }
237
238 TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
239   const int64 kRttMs = 10;
240   const int64 kDeviationMs = 3;
241   EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
242
243   sender_->AckAccounting(QuicTime::Delta::FromMilliseconds(kRttMs));
244
245   // Initial value is to set the median deviation to half of the initial
246   // rtt, the median in then multiplied by a factor of 4 and finally the
247   // smoothed rtt is added which is the initial rtt.
248   QuicTime::Delta expected_delay =
249       QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4);
250   EXPECT_EQ(expected_delay, sender_->RetransmissionDelay());
251
252   for (int i = 0; i < 100; ++i) {
253     // Run to make sure that we converge.
254     sender_->AckAccounting(
255         QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs));
256     sender_->AckAccounting(
257         QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs));
258   }
259   expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4);
260
261   EXPECT_NEAR(kRttMs, sender_->SmoothedRtt().ToMilliseconds(), 1);
262   EXPECT_NEAR(expected_delay.ToMilliseconds(),
263               sender_->RetransmissionDelay().ToMilliseconds(),
264               1);
265 }
266
267 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) {
268   const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50;
269   const int kNumberOfAck = 100;
270   sender_.reset(
271       new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
272
273   QuicCongestionFeedbackFrame feedback;
274   // At startup make sure we can send.
275   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
276       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
277   // Get default QuicCongestionFeedbackFrame from receiver.
278   ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
279   sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
280                                                  not_used_);
281   // Make sure we can send.
282   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
283       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
284
285   for (int i = 0; i < kNumberOfAck; ++i) {
286     // Send our full send window.
287     SendAvailableSendWindow();
288     AckNPackets(2);
289   }
290   QuicByteCount expected_send_window =
291       kMaxCongestionWindowTCP * kDefaultTCPMSS;
292   EXPECT_EQ(expected_send_window, sender_->SendWindow());
293 }
294
295 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
296   const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50;
297   const int kNumberOfAck = 1000;
298   sender_.reset(
299       new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP));
300
301   QuicCongestionFeedbackFrame feedback;
302   // At startup make sure we can send.
303   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
304       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
305   // Get default QuicCongestionFeedbackFrame from receiver.
306   ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
307   sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
308                                                  not_used_);
309   // Make sure we can send.
310   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
311       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
312
313   SendAvailableSendWindow();
314   AckNPackets(2);
315   // Make sure we fall out of slow start.
316   sender_->OnIncomingLoss(clock_.Now());
317
318   for (int i = 0; i < kNumberOfAck; ++i) {
319     // Send our full send window.
320     SendAvailableSendWindow();
321     AckNPackets(2);
322   }
323
324   QuicByteCount expected_send_window =
325       kMaxCongestionWindowTCP * kDefaultTCPMSS;
326   EXPECT_EQ(expected_send_window, sender_->SendWindow());
327 }
328
329 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
330   const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50;
331   const int kNumberOfAck = 1000;
332   sender_.reset(
333       new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
334
335   QuicCongestionFeedbackFrame feedback;
336   // At startup make sure we can send.
337   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
338       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
339   // Get default QuicCongestionFeedbackFrame from receiver.
340   ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
341   sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
342                                                  not_used_);
343   // Make sure we can send.
344   EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
345       NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
346
347   SendAvailableSendWindow();
348   AckNPackets(2);
349   // Make sure we fall out of slow start.
350   sender_->OnIncomingLoss(clock_.Now());
351
352   for (int i = 0; i < kNumberOfAck; ++i) {
353     // Send our full send window.
354     SendAvailableSendWindow();
355     AckNPackets(2);
356   }
357
358   QuicByteCount expected_send_window =
359       kMaxCongestionWindowTCP * kDefaultTCPMSS;
360   EXPECT_EQ(expected_send_window, sender_->SendWindow());
361 }
362
363 TEST_F(TcpCubicSenderTest, SendWindowNotAffectedByAcks) {
364   QuicByteCount send_window = sender_->AvailableSendWindow();
365
366   // Send a packet with no retransmittable data, and ensure that the congestion
367   // window doesn't change.
368   QuicByteCount bytes_in_packet = std::min(kDefaultTCPMSS, send_window);
369   sender_->OnPacketSent(clock_.Now(), sequence_number_++, bytes_in_packet,
370                         NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
371   EXPECT_EQ(send_window, sender_->AvailableSendWindow());
372
373   // Send a data packet with retransmittable data, and ensure that the
374   // congestion window has shrunk.
375   sender_->OnPacketSent(clock_.Now(), sequence_number_++, bytes_in_packet,
376                         NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
377   EXPECT_GT(send_window, sender_->AvailableSendWindow());
378 }
379
380 TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) {
381   QuicTcpCongestionWindow congestion_window = sender_->congestion_window();
382   QuicConfig config;
383   config.set_server_initial_congestion_window(2 * congestion_window,
384                                        2 * congestion_window);
385   EXPECT_EQ(2 * congestion_window, config.server_initial_congestion_window());
386
387   sender_->SetFromConfig(config, true);
388   EXPECT_EQ(2 * congestion_window, sender_->congestion_window());
389 }
390
391 }  // namespace test
392 }  // namespace net