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.
5 #include "net/quic/congestion_control/cubic.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "net/quic/quic_connection_stats.h"
10 #include "net/quic/test_tools/mock_clock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
16 const float kBeta
= 0.7f
; // Default Cubic backoff factor.
17 const uint32 kNumConnections
= 2;
18 const float kNConnectionBeta
= (kNumConnections
- 1 + kBeta
) / kNumConnections
;
19 const float kNConnectionAlpha
= 3 * kNumConnections
* kNumConnections
*
20 (1 - kNConnectionBeta
) / (1 + kNConnectionBeta
);
22 class CubicTest
: public ::testing::Test
{
25 : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
26 hundred_ms_(QuicTime::Delta::FromMilliseconds(100)),
28 const QuicTime::Delta one_ms_
;
29 const QuicTime::Delta hundred_ms_
;
34 TEST_F(CubicTest
, AboveOrigin
) {
36 const QuicTime::Delta rtt_min
= hundred_ms_
;
37 QuicPacketCount current_cwnd
= 10;
38 QuicPacketCount expected_cwnd
= current_cwnd
+ 1;
39 // Initialize the state.
40 clock_
.AdvanceTime(one_ms_
);
41 EXPECT_EQ(expected_cwnd
,
42 cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
));
43 current_cwnd
= expected_cwnd
;
45 for (int i
= 0; i
< 48; ++i
) {
46 for (QuicPacketCount n
= 1; n
< current_cwnd
/ kNConnectionAlpha
; ++n
) {
48 EXPECT_NEAR(current_cwnd
,
49 cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
), 1);
51 clock_
.AdvanceTime(hundred_ms_
);
52 current_cwnd
= cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
53 EXPECT_NEAR(expected_cwnd
, current_cwnd
, 1);
57 for (int i
= 0; i
< 52; ++i
) {
58 for (QuicPacketCount n
= 1; n
< current_cwnd
; ++n
) {
60 EXPECT_EQ(current_cwnd
,
61 cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
));
63 clock_
.AdvanceTime(hundred_ms_
);
64 current_cwnd
= cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
66 // Total time elapsed so far; add min_rtt (0.1s) here as well.
67 float elapsed_time_s
= 10.0f
+ 0.1f
;
68 // |expected_cwnd| is initial value of cwnd + K * t^3, where K = 0.4.
69 expected_cwnd
= 11 + (elapsed_time_s
* elapsed_time_s
* elapsed_time_s
* 410)
71 EXPECT_EQ(expected_cwnd
, current_cwnd
);
74 TEST_F(CubicTest
, CwndIncreaseStatsDuringConvexRegion
) {
75 const QuicTime::Delta rtt_min
= hundred_ms_
;
76 QuicPacketCount current_cwnd
= 10;
77 QuicPacketCount expected_cwnd
= current_cwnd
+ 1;
78 // Initialize controller state.
79 clock_
.AdvanceTime(one_ms_
);
80 expected_cwnd
= cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
81 current_cwnd
= expected_cwnd
;
82 // Testing Reno mode increase.
83 for (int i
= 0; i
< 48; ++i
) {
84 for (QuicPacketCount n
= 1; n
< current_cwnd
/ kNConnectionAlpha
; ++n
) {
85 // Call once per ACK, causing cwnd growth in Reno mode.
86 cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
88 // Advance current time so that cwnd update is allowed to happen by Cubic.
89 clock_
.AdvanceTime(hundred_ms_
);
90 current_cwnd
= cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
94 // Testing Cubic mode increase.
95 for (int i
= 0; i
< 52; ++i
) {
96 for (QuicPacketCount n
= 1; n
< current_cwnd
; ++n
) {
98 cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
100 clock_
.AdvanceTime(hundred_ms_
);
101 current_cwnd
= cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
106 TEST_F(CubicTest
, LossEvents
) {
107 const QuicTime::Delta rtt_min
= hundred_ms_
;
108 QuicPacketCount current_cwnd
= 422;
109 QuicPacketCount expected_cwnd
= current_cwnd
+ 1;
110 // Initialize the state.
111 clock_
.AdvanceTime(one_ms_
);
112 EXPECT_EQ(expected_cwnd
,
113 cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
));
114 expected_cwnd
= static_cast<QuicPacketCount
>(current_cwnd
* kNConnectionBeta
);
115 EXPECT_EQ(expected_cwnd
,
116 cubic_
.CongestionWindowAfterPacketLoss(current_cwnd
));
117 expected_cwnd
= static_cast<QuicPacketCount
>(current_cwnd
* kNConnectionBeta
);
118 EXPECT_EQ(expected_cwnd
,
119 cubic_
.CongestionWindowAfterPacketLoss(current_cwnd
));
122 TEST_F(CubicTest
, BelowOrigin
) {
124 const QuicTime::Delta rtt_min
= hundred_ms_
;
125 QuicPacketCount current_cwnd
= 422;
126 QuicPacketCount expected_cwnd
= current_cwnd
+ 1;
127 // Initialize the state.
128 clock_
.AdvanceTime(one_ms_
);
129 EXPECT_EQ(expected_cwnd
,
130 cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
));
131 expected_cwnd
= static_cast<QuicPacketCount
>(current_cwnd
* kNConnectionBeta
);
132 EXPECT_EQ(expected_cwnd
,
133 cubic_
.CongestionWindowAfterPacketLoss(current_cwnd
));
134 current_cwnd
= expected_cwnd
;
135 // First update after loss to initialize the epoch.
136 current_cwnd
= cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
138 for (int i
= 0; i
< 40 ; ++i
) {
139 clock_
.AdvanceTime(hundred_ms_
);
140 current_cwnd
= cubic_
.CongestionWindowAfterAck(current_cwnd
, rtt_min
);
143 EXPECT_EQ(expected_cwnd
, current_cwnd
);