Home | History | Annotate | Download | only in congestion_control
      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 * 717 / 1024;
    113   EXPECT_EQ(expected_cwnd,
    114             cubic_->CongestionWindowAfterPacketLoss(current_cwnd));
    115   expected_cwnd = current_cwnd * 717 / 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 * 717 / 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 = 422;
    146   EXPECT_EQ(expected_cwnd, current_cwnd);
    147 }
    148 
    149 }  // namespace testing
    150 }  // namespace net
    151