blob: 558971aab6983ba688d0cc2d786038113c73ba4c [file] [log] [blame]
// Copyright 2016 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 "net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
namespace quic {
namespace test {
class BandwidthSamplerPeer {
public:
static size_t GetNumberOfTrackedPackets(const BandwidthSampler& sampler) {
return sampler.connection_state_map_.number_of_present_entries();
}
static QuicByteCount GetPacketSize(const BandwidthSampler& sampler,
QuicPacketNumber packet_number) {
return sampler.connection_state_map_.GetEntry(packet_number)->size;
}
};
const QuicByteCount kRegularPacketSize = 1280;
// Enforce divisibility for some of the tests.
static_assert((kRegularPacketSize & 31) == 0,
"kRegularPacketSize has to be five times divisible by 2");
// A test fixture with utility methods for BandwidthSampler tests.
class BandwidthSamplerTest : public QuicTest {
protected:
BandwidthSamplerTest()
: sampler_(nullptr, /*max_height_tracker_window_length=*/0),
bytes_in_flight_(0) {
// Ensure that the clock does not start at zero.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
MockClock clock_;
BandwidthSampler sampler_;
QuicByteCount bytes_in_flight_;
QuicByteCount PacketsToBytes(QuicPacketCount packet_count) {
return packet_count * kRegularPacketSize;
}
void SendPacketInner(uint64_t packet_number,
QuicByteCount bytes,
HasRetransmittableData has_retransmittable_data) {
sampler_.OnPacketSent(clock_.Now(), QuicPacketNumber(packet_number), bytes,
bytes_in_flight_, has_retransmittable_data);
if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA) {
bytes_in_flight_ += bytes;
}
}
void SendPacket(uint64_t packet_number) {
SendPacketInner(packet_number, kRegularPacketSize,
HAS_RETRANSMITTABLE_DATA);
}
BandwidthSample AckPacketInner(uint64_t packet_number) {
QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
sampler_, QuicPacketNumber(packet_number));
bytes_in_flight_ -= size;
return sampler_.OnPacketAcknowledged(clock_.Now(),
QuicPacketNumber(packet_number));
}
// Acknowledge receipt of a packet and expect it to be not app-limited.
QuicBandwidth AckPacket(uint64_t packet_number) {
BandwidthSample sample = AckPacketInner(packet_number);
EXPECT_TRUE(sample.state_at_send.is_valid);
EXPECT_FALSE(sample.state_at_send.is_app_limited);
return sample.bandwidth;
}
SendTimeState LosePacket(uint64_t packet_number) {
QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
sampler_, QuicPacketNumber(packet_number));
bytes_in_flight_ -= size;
SendTimeState send_time_state =
sampler_.OnPacketLost(QuicPacketNumber(packet_number));
EXPECT_TRUE(send_time_state.is_valid);
return send_time_state;
}
// Sends one packet and acks it. Then, send 20 packets. Finally, send
// another 20 packets while acknowledging previous 20.
void Send40PacketsAndAckFirst20(QuicTime::Delta time_between_packets) {
// Send 20 packets at a constant inter-packet time.
for (int i = 1; i <= 20; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
}
// Ack packets 1 to 20, while sending new packets at the same rate as
// before.
for (int i = 1; i <= 20; i++) {
AckPacket(i);
SendPacket(i + 20);
clock_.AdvanceTime(time_between_packets);
}
}
};
// Test the sampler in a simple stop-and-wait sender setting.
TEST_F(BandwidthSamplerTest, SendAndWait) {
QuicTime::Delta time_between_packets = QuicTime::Delta::FromMilliseconds(10);
QuicBandwidth expected_bandwidth =
QuicBandwidth::FromBytesPerSecond(kRegularPacketSize * 100);
// Send packets at the constant bandwidth.
for (int i = 1; i < 20; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
QuicBandwidth current_sample = AckPacket(i);
EXPECT_EQ(expected_bandwidth, current_sample);
}
// Send packets at the exponentially decreasing bandwidth.
for (int i = 20; i < 25; i++) {
time_between_packets = time_between_packets * 2;
expected_bandwidth = expected_bandwidth * 0.5;
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
QuicBandwidth current_sample = AckPacket(i);
EXPECT_EQ(expected_bandwidth, current_sample);
}
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
TEST_F(BandwidthSamplerTest, SendTimeState) {
QuicTime::Delta time_between_packets = QuicTime::Delta::FromMilliseconds(10);
// Send packets 1-5.
for (int i = 1; i <= 5; i++) {
SendPacket(i);
EXPECT_EQ(PacketsToBytes(i), sampler_.total_bytes_sent());
clock_.AdvanceTime(time_between_packets);
}
// Ack packet 1.
SendTimeState send_time_state = AckPacketInner(1).state_at_send;
EXPECT_EQ(PacketsToBytes(1), send_time_state.total_bytes_sent);
EXPECT_EQ(0u, send_time_state.total_bytes_acked);
EXPECT_EQ(0u, send_time_state.total_bytes_lost);
EXPECT_EQ(PacketsToBytes(1), sampler_.total_bytes_acked());
// Lose packet 2.
send_time_state = LosePacket(2);
EXPECT_EQ(PacketsToBytes(2), send_time_state.total_bytes_sent);
EXPECT_EQ(0u, send_time_state.total_bytes_acked);
EXPECT_EQ(0u, send_time_state.total_bytes_lost);
EXPECT_EQ(PacketsToBytes(1), sampler_.total_bytes_lost());
// Lose packet 3.
send_time_state = LosePacket(3);
EXPECT_EQ(PacketsToBytes(3), send_time_state.total_bytes_sent);
EXPECT_EQ(0u, send_time_state.total_bytes_acked);
EXPECT_EQ(0u, send_time_state.total_bytes_lost);
EXPECT_EQ(PacketsToBytes(2), sampler_.total_bytes_lost());
// Send packets 6-10.
for (int i = 6; i <= 10; i++) {
SendPacket(i);
EXPECT_EQ(PacketsToBytes(i), sampler_.total_bytes_sent());
clock_.AdvanceTime(time_between_packets);
}
// Ack all inflight packets.
QuicPacketCount acked_packet_count = 1;
EXPECT_EQ(PacketsToBytes(acked_packet_count), sampler_.total_bytes_acked());
for (int i = 4; i <= 10; i++) {
send_time_state = AckPacketInner(i).state_at_send;
++acked_packet_count;
EXPECT_EQ(PacketsToBytes(acked_packet_count), sampler_.total_bytes_acked());
EXPECT_EQ(PacketsToBytes(i), send_time_state.total_bytes_sent);
if (i <= 5) {
EXPECT_EQ(0u, send_time_state.total_bytes_acked);
EXPECT_EQ(0u, send_time_state.total_bytes_lost);
} else {
EXPECT_EQ(PacketsToBytes(1), send_time_state.total_bytes_acked);
EXPECT_EQ(PacketsToBytes(2), send_time_state.total_bytes_lost);
}
clock_.AdvanceTime(time_between_packets);
}
}
// Test the sampler during regular windowed sender scenario with fixed
// CWND of 20.
TEST_F(BandwidthSamplerTest, SendPaced) {
const QuicTime::Delta time_between_packets =
QuicTime::Delta::FromMilliseconds(1);
QuicBandwidth expected_bandwidth =
QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
Send40PacketsAndAckFirst20(time_between_packets);
// Ack the packets 21 to 40, arriving at the correct bandwidth.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
for (int i = 21; i <= 40; i++) {
last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
clock_.AdvanceTime(time_between_packets);
}
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
// Test the sampler in a scenario where 50% of packets is consistently lost.
TEST_F(BandwidthSamplerTest, SendWithLosses) {
const QuicTime::Delta time_between_packets =
QuicTime::Delta::FromMilliseconds(1);
QuicBandwidth expected_bandwidth =
QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize) * 0.5;
// Send 20 packets, each 1 ms apart.
for (int i = 1; i <= 20; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
}
// Ack packets 1 to 20, losing every even-numbered packet, while sending new
// packets at the same rate as before.
for (int i = 1; i <= 20; i++) {
if (i % 2 == 0) {
AckPacket(i);
} else {
LosePacket(i);
}
SendPacket(i + 20);
clock_.AdvanceTime(time_between_packets);
}
// Ack the packets 21 to 40 with the same loss pattern.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
for (int i = 21; i <= 40; i++) {
if (i % 2 == 0) {
last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
} else {
LosePacket(i);
}
clock_.AdvanceTime(time_between_packets);
}
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
// Test the sampler in a scenario where the 50% of packets are not
// congestion controlled (specifically, non-retransmittable data is not
// congestion controlled). Should be functionally consistent in behavior with
// the SendWithLosses test.
TEST_F(BandwidthSamplerTest, NotCongestionControlled) {
const QuicTime::Delta time_between_packets =
QuicTime::Delta::FromMilliseconds(1);
QuicBandwidth expected_bandwidth =
QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize) * 0.5;
// Send 20 packets, each 1 ms apart. Every even packet is not congestion
// controlled.
for (int i = 1; i <= 20; i++) {
SendPacketInner(
i, kRegularPacketSize,
i % 2 == 0 ? HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA);
clock_.AdvanceTime(time_between_packets);
}
// Ensure only congestion controlled packets are tracked.
EXPECT_EQ(10u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
// Ack packets 2 to 21, ignoring every even-numbered packet, while sending new
// packets at the same rate as before.
for (int i = 1; i <= 20; i++) {
if (i % 2 == 0) {
AckPacket(i);
}
SendPacketInner(
i + 20, kRegularPacketSize,
i % 2 == 0 ? HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA);
clock_.AdvanceTime(time_between_packets);
}
// Ack the packets 22 to 41 with the same congestion controlled pattern.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
for (int i = 21; i <= 40; i++) {
if (i % 2 == 0) {
last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
}
clock_.AdvanceTime(time_between_packets);
}
// Since only congestion controlled packets are entered into the map, it has
// to be empty at this point.
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
// Simulate a situation where ACKs arrive in burst and earlier than usual, thus
// producing an ACK rate which is higher than the original send rate.
TEST_F(BandwidthSamplerTest, CompressedAck) {
const QuicTime::Delta time_between_packets =
QuicTime::Delta::FromMilliseconds(1);
QuicBandwidth expected_bandwidth =
QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
Send40PacketsAndAckFirst20(time_between_packets);
// Simulate an RTT somewhat lower than the one for 1-to-21 transmission.
clock_.AdvanceTime(time_between_packets * 15);
// Ack the packets 21 to 40 almost immediately at once.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
QuicTime::Delta ridiculously_small_time_delta =
QuicTime::Delta::FromMicroseconds(20);
for (int i = 21; i <= 40; i++) {
last_bandwidth = AckPacket(i);
clock_.AdvanceTime(ridiculously_small_time_delta);
}
EXPECT_EQ(expected_bandwidth, last_bandwidth);
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
// Tests receiving ACK packets in the reverse order.
TEST_F(BandwidthSamplerTest, ReorderedAck) {
const QuicTime::Delta time_between_packets =
QuicTime::Delta::FromMilliseconds(1);
QuicBandwidth expected_bandwidth =
QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
Send40PacketsAndAckFirst20(time_between_packets);
// Ack the packets 21 to 40 in the reverse order, while sending packets 41 to
// 60.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
for (int i = 0; i < 20; i++) {
last_bandwidth = AckPacket(40 - i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
SendPacket(41 + i);
clock_.AdvanceTime(time_between_packets);
}
// Ack the packets 41 to 60, now in the regular order.
for (int i = 41; i <= 60; i++) {
last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
clock_.AdvanceTime(time_between_packets);
}
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
// Test the app-limited logic.
TEST_F(BandwidthSamplerTest, AppLimited) {
const QuicTime::Delta time_between_packets =
QuicTime::Delta::FromMilliseconds(1);
QuicBandwidth expected_bandwidth =
QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
Send40PacketsAndAckFirst20(time_between_packets);
// We are now app-limited. Ack 21 to 40 as usual, but do not send anything for
// now.
sampler_.OnAppLimited();
for (int i = 21; i <= 40; i++) {
QuicBandwidth current_sample = AckPacket(i);
EXPECT_EQ(expected_bandwidth, current_sample);
clock_.AdvanceTime(time_between_packets);
}
// Enter quiescence.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
// Send packets 41 to 60, all of which would be marked as app-limited.
for (int i = 41; i <= 60; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
}
// Ack packets 41 to 60, while sending packets 61 to 80. 41 to 60 should be
// app-limited and underestimate the bandwidth due to that.
for (int i = 41; i <= 60; i++) {
BandwidthSample sample = AckPacketInner(i);
EXPECT_TRUE(sample.state_at_send.is_app_limited);
EXPECT_LT(sample.bandwidth, 0.7f * expected_bandwidth);
SendPacket(i + 20);
clock_.AdvanceTime(time_between_packets);
}
// Run out of packets, and then ack packet 61 to 80, all of which should have
// correct non-app-limited samples.
for (int i = 61; i <= 80; i++) {
QuicBandwidth last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
clock_.AdvanceTime(time_between_packets);
}
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
EXPECT_EQ(0u, bytes_in_flight_);
}
// Test the samples taken at the first flight of packets sent.
TEST_F(BandwidthSamplerTest, FirstRoundTrip) {
const QuicTime::Delta time_between_packets =
QuicTime::Delta::FromMilliseconds(1);
const QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(800);
const int num_packets = 10;
const QuicByteCount num_bytes = kRegularPacketSize * num_packets;
const QuicBandwidth real_bandwidth =
QuicBandwidth::FromBytesAndTimeDelta(num_bytes, rtt);
for (int i = 1; i <= 10; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
}
clock_.AdvanceTime(rtt - num_packets * time_between_packets);
QuicBandwidth last_sample = QuicBandwidth::Zero();
for (int i = 1; i <= 10; i++) {
QuicBandwidth sample = AckPacket(i);
EXPECT_GT(sample, last_sample);
last_sample = sample;
clock_.AdvanceTime(time_between_packets);
}
// The final measured sample for the first flight of sample is expected to be
// smaller than the real bandwidth, yet it should not lose more than 10%. The
// specific value of the error depends on the difference between the RTT and
// the time it takes to exhaust the congestion window (i.e. in the limit when
// all packets are sent simultaneously, last sample would indicate the real
// bandwidth).
EXPECT_LT(last_sample, real_bandwidth);
EXPECT_GT(last_sample, 0.9f * real_bandwidth);
}
// Test sampler's ability to remove obsolete packets.
TEST_F(BandwidthSamplerTest, RemoveObsoletePackets) {
SendPacket(1);
SendPacket(2);
SendPacket(3);
SendPacket(4);
SendPacket(5);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
EXPECT_EQ(5u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
sampler_.RemoveObsoletePackets(QuicPacketNumber(4));
EXPECT_EQ(2u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
sampler_.OnPacketLost(QuicPacketNumber(4));
EXPECT_EQ(1u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
AckPacket(5);
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
}
class MaxAckHeightTrackerTest : public QuicTest {
protected:
MaxAckHeightTrackerTest() : tracker_(/*initial_filter_window=*/10) {}
// Run a full aggregation episode, which is one or more aggregated acks,
// followed by a quiet period in which no ack happens.
// After this function returns, the time is set to the earliest point at which
// any ack event will cause tracker_.Update() to start a new aggregation.
void AggregationEpisode(QuicBandwidth aggregation_bandwidth,
QuicTime::Delta aggregation_duration,
QuicByteCount bytes_per_ack,
bool expect_new_aggregation_epoch) {
ASSERT_GE(aggregation_bandwidth, bandwidth_);
const QuicTime start_time = now_;
const QuicByteCount aggregation_bytes =
aggregation_bandwidth * aggregation_duration;
const int num_acks = aggregation_bytes / bytes_per_ack;
ASSERT_EQ(aggregation_bytes, num_acks * bytes_per_ack)
<< "aggregation_bytes: " << aggregation_bytes << " ["
<< aggregation_bandwidth << " in " << aggregation_duration
<< "], bytes_per_ack: " << bytes_per_ack;
const QuicTime::Delta time_between_acks = QuicTime::Delta::FromMicroseconds(
aggregation_duration.ToMicroseconds() / num_acks);
ASSERT_EQ(aggregation_duration, num_acks * time_between_acks)
<< "aggregation_bytes: " << aggregation_bytes
<< ", num_acks: " << num_acks
<< ", time_between_acks: " << time_between_acks;
// The total duration of aggregation time and quiet period.
const QuicTime::Delta total_duration = QuicTime::Delta::FromMicroseconds(
aggregation_bytes * 8 * 1000000 / bandwidth_.ToBitsPerSecond());
ASSERT_EQ(aggregation_bytes, total_duration * bandwidth_)
<< "total_duration: " << total_duration
<< ", bandwidth_: " << bandwidth_;
QuicByteCount last_extra_acked = 0;
for (QuicByteCount bytes = 0; bytes < aggregation_bytes;
bytes += bytes_per_ack) {
QuicByteCount extra_acked =
tracker_.Update(bandwidth_, RoundTripCount(), now_, bytes_per_ack);
QUIC_VLOG(1) << "T" << now_ << ": Update after " << bytes_per_ack
<< " bytes acked, " << extra_acked << " extra bytes acked";
// |extra_acked| should be 0 if either
// [1] We are at the beginning of a aggregation epoch(bytes==0) and the
// the current tracker implementation can identify it, or
// [2] We are not really aggregating acks.
if ((bytes == 0 && expect_new_aggregation_epoch) || // [1]
(aggregation_bandwidth == bandwidth_)) { // [2]
EXPECT_EQ(0u, extra_acked);
} else {
EXPECT_LT(last_extra_acked, extra_acked);
}
now_ = now_ + time_between_acks;
last_extra_acked = extra_acked;
}
// Advance past the quiet period.
const QuicTime time_after_aggregation = now_;
now_ = start_time + total_duration;
QUIC_VLOG(1) << "Advanced time from " << time_after_aggregation << " to "
<< now_ << ". Aggregation time["
<< (time_after_aggregation - start_time) << "], Quiet time["
<< (now_ - time_after_aggregation) << "].";
}
QuicRoundTripCount RoundTripCount() const {
return (now_ - QuicTime::Zero()).ToMicroseconds() / rtt_.ToMicroseconds();
}
MaxAckHeightTracker tracker_;
QuicBandwidth bandwidth_ = QuicBandwidth::FromBytesPerSecond(10 * 1000);
QuicTime now_ = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1);
QuicTime::Delta rtt_ = QuicTime::Delta::FromMilliseconds(60);
};
TEST_F(MaxAckHeightTrackerTest, VeryAggregatedLargeAck) {
AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
1200, true);
AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
1200, true);
now_ = now_ - QuicTime::Delta::FromMilliseconds(1);
AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6),
1200, false);
}
TEST_F(MaxAckHeightTrackerTest, VeryAggregatedSmallAcks) {
AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6), 300,
true);
AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6), 300,
true);
now_ = now_ - QuicTime::Delta::FromMilliseconds(1);
AggregationEpisode(bandwidth_ * 20, QuicTime::Delta::FromMilliseconds(6), 300,
false);
}
TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedLargeAck) {
AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
1000, true);
AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
1000, true);
now_ = now_ - QuicTime::Delta::FromMilliseconds(1);
AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50),
1000, false);
}
TEST_F(MaxAckHeightTrackerTest, SomewhatAggregatedSmallAcks) {
AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50), 100,
true);
AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50), 100,
true);
now_ = now_ - QuicTime::Delta::FromMilliseconds(1);
AggregationEpisode(bandwidth_ * 2, QuicTime::Delta::FromMilliseconds(50), 100,
false);
}
TEST_F(MaxAckHeightTrackerTest, NotAggregated) {
AggregationEpisode(bandwidth_, QuicTime::Delta::FromMilliseconds(100), 100,
true);
}
} // namespace test
} // namespace quic