| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 "net/quic/congestion_control/rtt_stats.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "net/test/scoped_mock_log.h" | |
| 11 #include "testing/gtest/include/gtest/gtest.h" | |
| 12 | |
| 13 using logging::LOG_WARNING; | |
| 14 using std::vector; | |
| 15 using testing::HasSubstr; | |
| 16 using testing::Message; | |
| 17 using testing::_; | |
| 18 | |
| 19 namespace net { | |
| 20 namespace test { | |
| 21 | |
| 22 class RttStatsPeer { | |
| 23 public: | |
| 24 static QuicTime::Delta GetHalfWindowRtt(const RttStats* rtt_stats) { | |
| 25 return rtt_stats->half_window_rtt_.rtt; | |
| 26 } | |
| 27 | |
| 28 static QuicTime::Delta GetQuarterWindowRtt(const RttStats* rtt_stats) { | |
| 29 return rtt_stats->quarter_window_rtt_.rtt; | |
| 30 } | |
| 31 }; | |
| 32 | |
| 33 class RttStatsTest : public ::testing::Test { | |
| 34 protected: | |
| 35 RttStats rtt_stats_; | |
| 36 }; | |
| 37 | |
| 38 TEST_F(RttStatsTest, DefaultsBeforeUpdate) { | |
| 39 EXPECT_LT(0u, rtt_stats_.initial_rtt_us()); | |
| 40 EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.min_rtt()); | |
| 41 EXPECT_EQ(QuicTime::Delta::Zero(), rtt_stats_.smoothed_rtt()); | |
| 42 } | |
| 43 | |
| 44 TEST_F(RttStatsTest, SmoothedRtt) { | |
| 45 // Verify that ack_delay is corrected for in Smoothed RTT. | |
| 46 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300), | |
| 47 QuicTime::Delta::FromMilliseconds(100), | |
| 48 QuicTime::Zero()); | |
| 49 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt()); | |
| 50 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt()); | |
| 51 // Verify that effective RTT of zero does not change Smoothed RTT. | |
| 52 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200), | |
| 53 QuicTime::Delta::FromMilliseconds(200), | |
| 54 QuicTime::Zero()); | |
| 55 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt()); | |
| 56 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt()); | |
| 57 // Verify that large erroneous ack_delay does not change Smoothed RTT. | |
| 58 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200), | |
| 59 QuicTime::Delta::FromMilliseconds(300), | |
| 60 QuicTime::Zero()); | |
| 61 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt()); | |
| 62 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.smoothed_rtt()); | |
| 63 } | |
| 64 | |
| 65 TEST_F(RttStatsTest, MinRtt) { | |
| 66 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200), | |
| 67 QuicTime::Delta::Zero(), | |
| 68 QuicTime::Zero()); | |
| 69 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.min_rtt()); | |
| 70 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), | |
| 71 rtt_stats_.recent_min_rtt()); | |
| 72 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(10), | |
| 73 QuicTime::Delta::Zero(), | |
| 74 QuicTime::Zero().Add( | |
| 75 QuicTime::Delta::FromMilliseconds(10))); | |
| 76 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 77 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.recent_min_rtt()); | |
| 78 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(50), | |
| 79 QuicTime::Delta::Zero(), | |
| 80 QuicTime::Zero().Add( | |
| 81 QuicTime::Delta::FromMilliseconds(20))); | |
| 82 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 83 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.recent_min_rtt()); | |
| 84 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(50), | |
| 85 QuicTime::Delta::Zero(), | |
| 86 QuicTime::Zero().Add( | |
| 87 QuicTime::Delta::FromMilliseconds(30))); | |
| 88 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 89 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.recent_min_rtt()); | |
| 90 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(50), | |
| 91 QuicTime::Delta::Zero(), | |
| 92 QuicTime::Zero().Add( | |
| 93 QuicTime::Delta::FromMilliseconds(40))); | |
| 94 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 95 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.recent_min_rtt()); | |
| 96 // Verify that ack_delay does not go into recording of min_rtt_. | |
| 97 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(7), | |
| 98 QuicTime::Delta::FromMilliseconds(2), | |
| 99 QuicTime::Zero().Add( | |
| 100 QuicTime::Delta::FromMilliseconds(50))); | |
| 101 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(7), rtt_stats_.min_rtt()); | |
| 102 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(7), rtt_stats_.recent_min_rtt()); | |
| 103 } | |
| 104 | |
| 105 TEST_F(RttStatsTest, RecentMinRtt) { | |
| 106 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(10), | |
| 107 QuicTime::Delta::Zero(), | |
| 108 QuicTime::Zero()); | |
| 109 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 110 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.recent_min_rtt()); | |
| 111 | |
| 112 rtt_stats_.SampleNewRecentMinRtt(4); | |
| 113 for (int i = 0; i < 3; ++i) { | |
| 114 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(50), | |
| 115 QuicTime::Delta::Zero(), | |
| 116 QuicTime::Zero()); | |
| 117 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 118 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), | |
| 119 rtt_stats_.recent_min_rtt()); | |
| 120 } | |
| 121 rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(50), | |
| 122 QuicTime::Delta::Zero(), | |
| 123 QuicTime::Zero()); | |
| 124 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 125 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(50), rtt_stats_.recent_min_rtt()); | |
| 126 } | |
| 127 | |
| 128 TEST_F(RttStatsTest, WindowedRecentMinRtt) { | |
| 129 // Set the window to 99ms, so 25ms is more than a quarter rtt. | |
| 130 rtt_stats_.set_recent_min_rtt_window(QuicTime::Delta::FromMilliseconds(99)); | |
| 131 | |
| 132 QuicTime now = QuicTime::Zero(); | |
| 133 QuicTime::Delta rtt_sample = QuicTime::Delta::FromMilliseconds(10); | |
| 134 rtt_stats_.UpdateRtt(rtt_sample, QuicTime::Delta::Zero(), now); | |
| 135 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 136 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.recent_min_rtt()); | |
| 137 | |
| 138 // Gradually increase the rtt samples and ensure the recent_min_rtt starts | |
| 139 // rising. | |
| 140 for (int i = 0; i < 8; ++i) { | |
| 141 now = now.Add(QuicTime::Delta::FromMilliseconds(25)); | |
| 142 rtt_sample = rtt_sample.Add(QuicTime::Delta::FromMilliseconds(10)); | |
| 143 rtt_stats_.UpdateRtt(rtt_sample, QuicTime::Delta::Zero(), now); | |
| 144 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 145 EXPECT_EQ(rtt_sample, RttStatsPeer::GetQuarterWindowRtt(&rtt_stats_)); | |
| 146 EXPECT_EQ(rtt_sample.Subtract(QuicTime::Delta::FromMilliseconds(10)), | |
| 147 RttStatsPeer::GetHalfWindowRtt(&rtt_stats_)); | |
| 148 if (i < 3) { | |
| 149 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), | |
| 150 rtt_stats_.recent_min_rtt()); | |
| 151 } else if (i < 5) { | |
| 152 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(30), | |
| 153 rtt_stats_.recent_min_rtt()); | |
| 154 } else if (i < 7) { | |
| 155 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(50), | |
| 156 rtt_stats_.recent_min_rtt()); | |
| 157 } else { | |
| 158 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(70), | |
| 159 rtt_stats_.recent_min_rtt()); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 // A new quarter rtt low sets that, but nothing else. | |
| 164 rtt_sample = rtt_sample.Subtract(QuicTime::Delta::FromMilliseconds(5)); | |
| 165 rtt_stats_.UpdateRtt(rtt_sample, QuicTime::Delta::Zero(), now); | |
| 166 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 167 EXPECT_EQ(rtt_sample, RttStatsPeer::GetQuarterWindowRtt(&rtt_stats_)); | |
| 168 EXPECT_EQ(rtt_sample.Subtract(QuicTime::Delta::FromMilliseconds(5)), | |
| 169 RttStatsPeer::GetHalfWindowRtt(&rtt_stats_)); | |
| 170 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(70), | |
| 171 rtt_stats_.recent_min_rtt()); | |
| 172 | |
| 173 // A new half rtt low sets that and the quarter rtt low. | |
| 174 rtt_sample = rtt_sample.Subtract(QuicTime::Delta::FromMilliseconds(15)); | |
| 175 rtt_stats_.UpdateRtt(rtt_sample, QuicTime::Delta::Zero(), now); | |
| 176 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 177 EXPECT_EQ(rtt_sample, RttStatsPeer::GetQuarterWindowRtt(&rtt_stats_)); | |
| 178 EXPECT_EQ(rtt_sample, RttStatsPeer::GetHalfWindowRtt(&rtt_stats_)); | |
| 179 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(70), | |
| 180 rtt_stats_.recent_min_rtt()); | |
| 181 | |
| 182 // A new full window loss sets the recent_min_rtt, but not min_rtt. | |
| 183 rtt_sample = QuicTime::Delta::FromMilliseconds(65); | |
| 184 rtt_stats_.UpdateRtt(rtt_sample, QuicTime::Delta::Zero(), now); | |
| 185 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), rtt_stats_.min_rtt()); | |
| 186 EXPECT_EQ(rtt_sample, RttStatsPeer::GetQuarterWindowRtt(&rtt_stats_)); | |
| 187 EXPECT_EQ(rtt_sample, RttStatsPeer::GetHalfWindowRtt(&rtt_stats_)); | |
| 188 EXPECT_EQ(rtt_sample, rtt_stats_.recent_min_rtt()); | |
| 189 | |
| 190 // A new all time low sets both the min_rtt and the recent_min_rtt. | |
| 191 rtt_sample = QuicTime::Delta::FromMilliseconds(5); | |
| 192 rtt_stats_.UpdateRtt(rtt_sample, QuicTime::Delta::Zero(), now); | |
| 193 | |
| 194 EXPECT_EQ(rtt_sample, rtt_stats_.min_rtt()); | |
| 195 EXPECT_EQ(rtt_sample, RttStatsPeer::GetQuarterWindowRtt(&rtt_stats_)); | |
| 196 EXPECT_EQ(rtt_sample, RttStatsPeer::GetHalfWindowRtt(&rtt_stats_)); | |
| 197 EXPECT_EQ(rtt_sample, rtt_stats_.recent_min_rtt()); | |
| 198 } | |
| 199 | |
| 200 TEST_F(RttStatsTest, ExpireSmoothedMetrics) { | |
| 201 QuicTime::Delta initial_rtt = QuicTime::Delta::FromMilliseconds(10); | |
| 202 rtt_stats_.UpdateRtt(initial_rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); | |
| 203 EXPECT_EQ(initial_rtt, rtt_stats_.min_rtt()); | |
| 204 EXPECT_EQ(initial_rtt, rtt_stats_.recent_min_rtt()); | |
| 205 EXPECT_EQ(initial_rtt, rtt_stats_.smoothed_rtt()); | |
| 206 | |
| 207 EXPECT_EQ(initial_rtt.Multiply(0.5), rtt_stats_.mean_deviation()); | |
| 208 | |
| 209 // Update once with a 20ms RTT. | |
| 210 QuicTime::Delta doubled_rtt = initial_rtt.Multiply(2); | |
| 211 rtt_stats_.UpdateRtt(doubled_rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); | |
| 212 EXPECT_EQ(initial_rtt.Multiply(1.125), rtt_stats_.smoothed_rtt()); | |
| 213 | |
| 214 // Expire the smoothed metrics, increasing smoothed rtt and mean deviation. | |
| 215 rtt_stats_.ExpireSmoothedMetrics(); | |
| 216 EXPECT_EQ(doubled_rtt, rtt_stats_.smoothed_rtt()); | |
| 217 EXPECT_EQ(initial_rtt.Multiply(0.875), rtt_stats_.mean_deviation()); | |
| 218 | |
| 219 // Now go back down to 5ms and expire the smoothed metrics, and ensure the | |
| 220 // mean deviation increases to 15ms. | |
| 221 QuicTime::Delta half_rtt = initial_rtt.Multiply(0.5); | |
| 222 rtt_stats_.UpdateRtt(half_rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); | |
| 223 EXPECT_GT(doubled_rtt, rtt_stats_.smoothed_rtt()); | |
| 224 EXPECT_LT(initial_rtt, rtt_stats_.mean_deviation()); | |
| 225 } | |
| 226 | |
| 227 TEST_F(RttStatsTest, UpdateRttWithBadSendDeltas) { | |
| 228 // Make sure we ignore bad RTTs. | |
| 229 ScopedMockLog log; | |
| 230 | |
| 231 QuicTime::Delta initial_rtt = QuicTime::Delta::FromMilliseconds(10); | |
| 232 rtt_stats_.UpdateRtt(initial_rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); | |
| 233 EXPECT_EQ(initial_rtt, rtt_stats_.min_rtt()); | |
| 234 EXPECT_EQ(initial_rtt, rtt_stats_.recent_min_rtt()); | |
| 235 EXPECT_EQ(initial_rtt, rtt_stats_.smoothed_rtt()); | |
| 236 | |
| 237 vector<QuicTime::Delta> bad_send_deltas; | |
| 238 bad_send_deltas.push_back(QuicTime::Delta::Zero()); | |
| 239 bad_send_deltas.push_back(QuicTime::Delta::Infinite()); | |
| 240 bad_send_deltas.push_back(QuicTime::Delta::FromMicroseconds(-1000)); | |
| 241 log.StartCapturingLogs(); | |
| 242 | |
| 243 for (QuicTime::Delta bad_send_delta : bad_send_deltas) { | |
| 244 SCOPED_TRACE(Message() << "bad_send_delta = " | |
| 245 << bad_send_delta.ToMicroseconds()); | |
| 246 EXPECT_CALL(log, Log(LOG_WARNING, _, _, _, HasSubstr("Ignoring"))); | |
| 247 rtt_stats_.UpdateRtt(bad_send_delta, | |
| 248 QuicTime::Delta::Zero(), | |
| 249 QuicTime::Zero()); | |
| 250 EXPECT_EQ(initial_rtt, rtt_stats_.min_rtt()); | |
| 251 EXPECT_EQ(initial_rtt, rtt_stats_.recent_min_rtt()); | |
| 252 EXPECT_EQ(initial_rtt, rtt_stats_.smoothed_rtt()); | |
| 253 } | |
| 254 } | |
| 255 | |
| 256 } // namespace test | |
| 257 } // namespace net | |
| OLD | NEW |