summaryrefslogtreecommitdiff
path: root/chromium/net/quic/congestion_control/cubic_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/quic/congestion_control/cubic_test.cc')
-rw-r--r--chromium/net/quic/congestion_control/cubic_test.cc150
1 files changed, 150 insertions, 0 deletions
diff --git a/chromium/net/quic/congestion_control/cubic_test.cc b/chromium/net/quic/congestion_control/cubic_test.cc
new file mode 100644
index 00000000000..84f2a7bb53d
--- /dev/null
+++ b/chromium/net/quic/congestion_control/cubic_test.cc
@@ -0,0 +1,150 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/congestion_control/cubic.h"
+#include "net/quic/test_tools/mock_clock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class CubicPeer : public Cubic {
+ public:
+ explicit CubicPeer(QuicClock* clock)
+ : Cubic(clock) {
+ }
+ using Cubic::CubeRoot;
+};
+
+class CubicTest : public ::testing::Test {
+ protected:
+ CubicTest()
+ : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
+ hundred_ms_(QuicTime::Delta::FromMilliseconds(100)) {
+ }
+ virtual void SetUp() {
+ cubic_.reset(new CubicPeer(&clock_));
+ }
+ const QuicTime::Delta one_ms_;
+ const QuicTime::Delta hundred_ms_;
+ MockClock clock_;
+ scoped_ptr<CubicPeer> cubic_;
+};
+
+TEST_F(CubicTest, CubeRootLow) {
+ for (uint32 i = 1; i < 256; ++i) {
+ uint64 cube = i * i * i;
+ uint8 cube_root = cubic_->CubeRoot(cube);
+ EXPECT_EQ(i, cube_root);
+ }
+}
+
+TEST_F(CubicTest, CubeRootHigh) {
+ // Test the range we will opperate in, 1300 to 130 000.
+ // We expect some loss in accuracy, accepting +-0.2%.
+ for (uint64 i = 1300; i < 20000; i += 100) {
+ uint64 cube = i * i * i;
+ uint32 cube_root = cubic_->CubeRoot(cube);
+ uint32 margin = cube_root >> 9; // Calculate 0.2% roughly by
+ // dividing by 512.
+ EXPECT_LE(i - margin, cube_root);
+ EXPECT_GE(i + margin, cube_root);
+ }
+ for (uint64 i = 20000; i < 130000; i *= 2) {
+ uint64 cube = i * i * i;
+ uint32 cube_root = cubic_->CubeRoot(cube);
+ uint32 margin = cube_root >> 9;
+ EXPECT_LE(i - margin, cube_root);
+ EXPECT_GE(i + margin, cube_root);
+ }
+}
+
+TEST_F(CubicTest, AboveOrgin) {
+ // Convex growth.
+ const QuicTime::Delta rtt_min = hundred_ms_;
+ uint32 current_cwnd = 10;
+ uint32 expected_cwnd = current_cwnd + 1;
+ // Initialize the state.
+ clock_.AdvanceTime(one_ms_);
+ EXPECT_EQ(expected_cwnd,
+ cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min));
+ current_cwnd = expected_cwnd;
+ // Normal TCP phase.
+ for (int i = 0; i < 48; ++i) {
+ for (uint32 n = 1; n < current_cwnd; ++n) {
+ // Call once per ACK.
+ EXPECT_EQ(current_cwnd,
+ cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min));
+ }
+ clock_.AdvanceTime(hundred_ms_);
+ current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min);
+ EXPECT_EQ(expected_cwnd, current_cwnd);
+ expected_cwnd++;
+ }
+ // Cubic phase.
+ for (int j = 48; j < 100; ++j) {
+ for (uint32 n = 1; n < current_cwnd; ++n) {
+ // Call once per ACK.
+ EXPECT_EQ(current_cwnd,
+ cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min));
+ }
+ clock_.AdvanceTime(hundred_ms_);
+ current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min);
+ }
+ float elapsed_time_s = 10.0f + 0.1f; // We need to add the RTT here.
+ expected_cwnd = 11 + (elapsed_time_s * elapsed_time_s * elapsed_time_s * 410)
+ / 1024;
+ EXPECT_EQ(expected_cwnd, current_cwnd);
+}
+
+TEST_F(CubicTest, LossEvents) {
+ const QuicTime::Delta rtt_min = hundred_ms_;
+ uint32 current_cwnd = 422;
+ uint32 expected_cwnd = current_cwnd + 1;
+ // Initialize the state.
+ clock_.AdvanceTime(one_ms_);
+ EXPECT_EQ(expected_cwnd,
+ cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min));
+ expected_cwnd = current_cwnd * 717 / 1024;
+ EXPECT_EQ(expected_cwnd,
+ cubic_->CongestionWindowAfterPacketLoss(current_cwnd));
+ expected_cwnd = current_cwnd * 717 / 1024;
+ EXPECT_EQ(expected_cwnd,
+ cubic_->CongestionWindowAfterPacketLoss(current_cwnd));
+}
+
+TEST_F(CubicTest, BelowOrgin) {
+ // Concave growth.
+ const QuicTime::Delta rtt_min = hundred_ms_;
+ uint32 current_cwnd = 422;
+ uint32 expected_cwnd = current_cwnd + 1;
+ // Initialize the state.
+ clock_.AdvanceTime(one_ms_);
+ EXPECT_EQ(expected_cwnd,
+ cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min));
+ expected_cwnd = current_cwnd * 717 / 1024;
+ EXPECT_EQ(expected_cwnd,
+ cubic_->CongestionWindowAfterPacketLoss(current_cwnd));
+ current_cwnd = expected_cwnd;
+ // First update after epoch.
+ current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min);
+ // Cubic phase.
+ for (int i = 0; i < 54; ++i) {
+ for (uint32 n = 1; n < current_cwnd; ++n) {
+ // Call once per ACK.
+ EXPECT_EQ(current_cwnd,
+ cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min));
+ }
+ clock_.AdvanceTime(hundred_ms_);
+ current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min);
+ }
+ expected_cwnd = 422;
+ EXPECT_EQ(expected_cwnd, current_cwnd);
+}
+
+} // namespace testing
+} // namespace net