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