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/basictypes.h" 6 #include "base/logging.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "net/quic/congestion_control/cubic.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 class CubicPeer : public Cubic { 16 public: 17 explicit CubicPeer(QuicClock* clock) 18 : Cubic(clock) { 19 } 20 using Cubic::CubeRoot; 21 }; 22 23 class CubicTest : public ::testing::Test { 24 protected: 25 CubicTest() 26 : one_ms_(QuicTime::Delta::FromMilliseconds(1)), 27 hundred_ms_(QuicTime::Delta::FromMilliseconds(100)) { 28 } 29 virtual void SetUp() { 30 cubic_.reset(new CubicPeer(&clock_)); 31 } 32 const QuicTime::Delta one_ms_; 33 const QuicTime::Delta hundred_ms_; 34 MockClock clock_; 35 scoped_ptr<CubicPeer> cubic_; 36 }; 37 38 TEST_F(CubicTest, CubeRootLow) { 39 for (uint32 i = 1; i < 256; ++i) { 40 uint64 cube = i * i * i; 41 uint8 cube_root = cubic_->CubeRoot(cube); 42 EXPECT_EQ(i, cube_root); 43 } 44 } 45 46 TEST_F(CubicTest, CubeRootHigh) { 47 // Test the range we will opperate in, 1300 to 130 000. 48 // We expect some loss in accuracy, accepting +-0.2%. 49 for (uint64 i = 1300; i < 20000; i += 100) { 50 uint64 cube = i * i * i; 51 uint32 cube_root = cubic_->CubeRoot(cube); 52 uint32 margin = cube_root >> 9; // Calculate 0.2% roughly by 53 // dividing by 512. 54 EXPECT_LE(i - margin, cube_root); 55 EXPECT_GE(i + margin, cube_root); 56 } 57 for (uint64 i = 20000; i < 130000; i *= 2) { 58 uint64 cube = i * i * i; 59 uint32 cube_root = cubic_->CubeRoot(cube); 60 uint32 margin = cube_root >> 9; 61 EXPECT_LE(i - margin, cube_root); 62 EXPECT_GE(i + margin, cube_root); 63 } 64 } 65 66 TEST_F(CubicTest, AboveOrgin) { 67 // Convex growth. 68 const QuicTime::Delta rtt_min = hundred_ms_; 69 uint32 current_cwnd = 10; 70 uint32 expected_cwnd = current_cwnd + 1; 71 // Initialize the state. 72 clock_.AdvanceTime(one_ms_); 73 EXPECT_EQ(expected_cwnd, 74 cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min)); 75 current_cwnd = expected_cwnd; 76 // Normal TCP phase. 77 for (int i = 0; i < 48; ++i) { 78 for (uint32 n = 1; n < current_cwnd; ++n) { 79 // Call once per ACK. 80 EXPECT_EQ(current_cwnd, 81 cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min)); 82 } 83 clock_.AdvanceTime(hundred_ms_); 84 current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min); 85 EXPECT_EQ(expected_cwnd, current_cwnd); 86 expected_cwnd++; 87 } 88 // Cubic phase. 89 for (int j = 48; j < 100; ++j) { 90 for (uint32 n = 1; n < current_cwnd; ++n) { 91 // Call once per ACK. 92 EXPECT_EQ(current_cwnd, 93 cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min)); 94 } 95 clock_.AdvanceTime(hundred_ms_); 96 current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min); 97 } 98 float elapsed_time_s = 10.0f + 0.1f; // We need to add the RTT here. 99 expected_cwnd = 11 + (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410) 100 / 1024; 101 EXPECT_EQ(expected_cwnd, current_cwnd); 102 } 103 104 TEST_F(CubicTest, LossEvents) { 105 const QuicTime::Delta rtt_min = hundred_ms_; 106 uint32 current_cwnd = 422; 107 uint32 expected_cwnd = current_cwnd + 1; 108 // Initialize the state. 109 clock_.AdvanceTime(one_ms_); 110 EXPECT_EQ(expected_cwnd, 111 cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min)); 112 expected_cwnd = current_cwnd * 939 / 1024; 113 EXPECT_EQ(expected_cwnd, 114 cubic_->CongestionWindowAfterPacketLoss(current_cwnd)); 115 expected_cwnd = current_cwnd * 939 / 1024; 116 EXPECT_EQ(expected_cwnd, 117 cubic_->CongestionWindowAfterPacketLoss(current_cwnd)); 118 } 119 120 TEST_F(CubicTest, BelowOrgin) { 121 // Concave growth. 122 const QuicTime::Delta rtt_min = hundred_ms_; 123 uint32 current_cwnd = 422; 124 uint32 expected_cwnd = current_cwnd + 1; 125 // Initialize the state. 126 clock_.AdvanceTime(one_ms_); 127 EXPECT_EQ(expected_cwnd, 128 cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min)); 129 expected_cwnd = current_cwnd * 939 / 1024; 130 EXPECT_EQ(expected_cwnd, 131 cubic_->CongestionWindowAfterPacketLoss(current_cwnd)); 132 current_cwnd = expected_cwnd; 133 // First update after epoch. 134 current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min); 135 // Cubic phase. 136 for (int i = 0; i < 54; ++i) { 137 for (uint32 n = 1; n < current_cwnd; ++n) { 138 // Call once per ACK. 139 EXPECT_EQ(current_cwnd, 140 cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min)); 141 } 142 clock_.AdvanceTime(hundred_ms_); 143 current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min); 144 } 145 expected_cwnd = 440; 146 EXPECT_EQ(expected_cwnd, current_cwnd); 147 } 148 149 } // namespace testing 150 } // namespace net 151