From baf5c9fabd3eba46a2b7747df00b1124a8f5def8 Mon Sep 17 00:00:00 2001 From: Rasmus Brandt Date: Mon, 17 Oct 2022 12:11:47 +0000 Subject: [PATCH] Revert "Add documentation, tests and simplify webrtc::SimulatedNetwork." MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c1d5fda22c8ae456950c5549d22d099b478c67e2. Reason for revert: This CL created thousands of metric alerts in the perf tests. It's possible that these are all expected, but since mbonadei@ is OOO right now, I think it's better to revert, and have him re-land when he is back. Most alerts are here: https://bugs.chromium.org/p/webrtc/issues/detail?id=14549 Original change's description: > Add documentation, tests and simplify webrtc::SimulatedNetwork. > > This CL increases the test coverage for webrtc::SimualtedNetwork, adds > some more comments to the class and the interface it implements and > simplify the logic around capacity and delay management in the > simulated network. > > More CLs will follow to continue the refactoring but this is the > ground work to make this more modular in the future. > > Bug: webrtc:14525, b/243202138 > Change-Id: Ib0408cf6e2c1cdceb71f8bec3202d2960c5b4d3c > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/278042 > Reviewed-by: Artem Titov > Reviewed-by: Per Kjellander > Reviewed-by: Rasmus Brandt > Commit-Queue: Mirko Bonadei > Reviewed-by: Björn Terelius > Cr-Commit-Position: refs/heads/main@{#38388} Bug: webrtc:14525, b/243202138 Change-Id: I5bc56c954bb12e7c27cb859e838f0b7a89e006f8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/279522 Owners-Override: Artem Titov Reviewed-by: Björn Terelius Reviewed-by: Artem Titov Bot-Commit: rubber-stamper@appspot.gserviceaccount.com Commit-Queue: Rasmus Brandt Cr-Commit-Position: refs/heads/main@{#38415} --- api/test/simulated_network.h | 50 +- call/BUILD.gn | 7 +- call/fake_network_pipe_unittest.cc | 2 +- call/simulated_network.cc | 182 +++---- call/simulated_network.h | 61 +-- call/simulated_network_unittest.cc | 513 ------------------ .../goog_cc_network_control_unittest.cc | 4 +- .../tests/remote_estimate_test.cc | 5 +- 8 files changed, 85 insertions(+), 739 deletions(-) delete mode 100644 call/simulated_network_unittest.cc diff --git a/api/test/simulated_network.h b/api/test/simulated_network.h index 04c5517c8d..fbf5c5ca29 100644 --- a/api/test/simulated_network.h +++ b/api/test/simulated_network.h @@ -38,12 +38,6 @@ struct PacketDeliveryInfo { static constexpr int kNotReceived = -1; PacketDeliveryInfo(PacketInFlightInfo source, int64_t receive_time_us) : receive_time_us(receive_time_us), packet_id(source.packet_id) {} - - bool operator==(const PacketDeliveryInfo& other) const { - return receive_time_us == other.receive_time_us && - packet_id == other.packet_id; - } - int64_t receive_time_us; uint64_t packet_id; }; @@ -70,50 +64,14 @@ struct BuiltInNetworkBehaviorConfig { int packet_overhead = 0; }; -// Interface that represents a Network behaviour. -// -// It is clients of this interface responsibility to enqueue and dequeue -// packets (based on the estimated delivery time expressed by -// NextDeliveryTimeUs). -// -// To enqueue packets, call EnqueuePacket: -// EXPECT_TRUE(network.EnqueuePacket( -// PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/1))); -// -// To know when to call DequeueDeliverablePackets to pull packets out of the -// network, call NextDeliveryTimeUs and schedule a task to invoke -// DequeueDeliverablePackets (if not already scheduled). -// -// DequeueDeliverablePackets will return a vector of delivered packets, but this -// vector can be empty in case of extra delay. In such case, make sure to invoke -// NextDeliveryTimeUs and schedule a task to call DequeueDeliverablePackets for -// the next estimated delivery of packets. -// -// std::vector delivered_packets = -// network.DequeueDeliverablePackets(/*receive_time_us=*/1000000); class NetworkBehaviorInterface { public: - // Enqueues a packet in the network and returns true if the action was - // successful, false otherwise (for example, because the network capacity has - // been saturated). If the return value is false, the packet should be - // considered as dropped and it will not be returned by future calls - // to DequeueDeliverablePackets. - // Packets enqueued will exit the network when DequeueDeliverablePackets is - // called and enough time has passed (see NextDeliveryTimeUs). virtual bool EnqueuePacket(PacketInFlightInfo packet_info) = 0; // Retrieves all packets that should be delivered by the given receive time. - // Not all the packets in the returned std::vector are actually delivered. - // In order to know the state of each packet it is necessary to check the - // `receive_time_us` field of each packet. If that is set to - // PacketDeliveryInfo::kNotReceived then the packet is considered lost in the - // network. virtual std::vector DequeueDeliverablePackets( int64_t receive_time_us) = 0; // Returns time in microseconds when caller should call - // DequeueDeliverablePackets to get the next set of delivered packets. It is - // possible that no packet will be delivered by that time (e.g. in case of - // random extra delay), in such case this method should be called again to get - // the updated estimated delivery time. + // DequeueDeliverablePackets to get next set of packets to deliver. virtual absl::optional NextDeliveryTimeUs() const = 0; virtual ~NetworkBehaviorInterface() = default; }; @@ -123,14 +81,10 @@ class NetworkBehaviorInterface { // capacity introduced delay. class SimulatedNetworkInterface : public NetworkBehaviorInterface { public: - // Sets a new configuration. + // Sets a new configuration. This won't affect packets already in the pipe. virtual void SetConfig(const BuiltInNetworkBehaviorConfig& config) = 0; virtual void UpdateConfig( std::function config_modifier) = 0; - // Pauses the network until `until_us`. This affects both delivery (calling - // DequeueDeliverablePackets before `until_us` results in an empty std::vector - // of packets) and capacity (the network is paused, so packets are not - // flowing and they will restart flowing at `until_us`). virtual void PauseTransmissionUntil(int64_t until_us) = 0; }; diff --git a/call/BUILD.gn b/call/BUILD.gn index 27a56eda90..fda5f706bf 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn @@ -652,16 +652,11 @@ if (rtc_include_tests) { rtc_library("fake_network_pipe_unittests") { testonly = true - sources = [ - "fake_network_pipe_unittest.cc", - "simulated_network_unittest.cc", - ] + sources = [ "fake_network_pipe_unittest.cc" ] deps = [ ":fake_network", ":simulated_network", - "../api:simulated_network_api", "../api/units:data_rate", - "../api/units:time_delta", "../system_wrappers", "../test:test_support", "//testing/gtest", diff --git a/call/fake_network_pipe_unittest.cc b/call/fake_network_pipe_unittest.cc index 60c26e335b..b9c69c9b74 100644 --- a/call/fake_network_pipe_unittest.cc +++ b/call/fake_network_pipe_unittest.cc @@ -274,7 +274,7 @@ TEST_F(FakeNetworkPipeTest, ChangingCapacityWithPacketsInPipeTest) { std::unique_ptr pipe( new FakeNetworkPipe(&fake_clock_, std::move(network), &receiver)); - // Add 20 packets of 1000 bytes, = 160 kb. + // Add 20 packets of 1000 bytes, = 80 kb. const int kNumPackets = 20; const int kPacketSize = 1000; SendPackets(pipe.get(), kNumPackets, kPacketSize); diff --git a/call/simulated_network.cc b/call/simulated_network.cc index 8f9d76dfe3..f5d0501313 100644 --- a/call/simulated_network.cc +++ b/call/simulated_network.cc @@ -12,7 +12,6 @@ #include #include -#include #include #include "api/units/data_rate.h" @@ -22,33 +21,11 @@ namespace webrtc { namespace { - -// Calculate the time (in microseconds) that takes to send N `bits` on a -// network with link capacity equal to `capacity_kbps` starting at time -// `start_time_us`. -int64_t CalculateArrivalTimeUs(int64_t start_time_us, - int64_t bits, - int capacity_kbps) { - // If capacity is 0, the link capacity is assumed to be infinite. - if (capacity_kbps == 0) { - return start_time_us; - } - // Adding `capacity - 1` to the numerator rounds the extra delay caused by - // capacity constraints up to an integral microsecond. Sending 0 bits takes 0 - // extra time, while sending 1 bit gets rounded up to 1 (the multiplication by - // 1000 is because capacity is in kbps). - // The factor 1000 comes from 10^6 / 10^3, where 10^6 is due to the time unit - // being us and 10^3 is due to the rate unit being kbps. - return start_time_us + ((1000 * bits + capacity_kbps - 1) / capacity_kbps); -} - +constexpr TimeDelta kDefaultProcessDelay = TimeDelta::Millis(5); } // namespace SimulatedNetwork::SimulatedNetwork(Config config, uint64_t random_seed) - : random_(random_seed), - bursting_(false), - last_enqueue_time_us_(0), - last_capacity_link_exit_time_(0) { + : random_(random_seed), bursting_(false) { SetConfig(config); } @@ -92,52 +69,26 @@ void SimulatedNetwork::PauseTransmissionUntil(int64_t until_us) { bool SimulatedNetwork::EnqueuePacket(PacketInFlightInfo packet) { RTC_DCHECK_RUNS_SERIALIZED(&process_checker_); - - // Check that old packets don't get enqueued, the SimulatedNetwork expect that - // the packets' send time is monotonically increasing. The tolerance for - // non-monotonic enqueue events is 0.5 ms because on multi core systems - // clock_gettime(CLOCK_MONOTONIC) can show non-monotonic behaviour between - // theads running on different cores. - // TODO(bugs.webrtc.org/14525): Open a bug on this with the goal to re-enable - // the DCHECK. - // At the moment, we see more than 130ms between non-monotonic events, which - // is more than expected. - // RTC_DCHECK_GE(packet.send_time_us - last_enqueue_time_us_, -2000); - ConfigState state = GetConfigState(); - // If the network config requires packet overhead, let's apply it as early as - // possible. + UpdateCapacityQueue(state, packet.send_time_us); + packet.size += state.config.packet_overhead; - // If `queue_length_packets` is 0, the queue size is infinite. if (state.config.queue_length_packets > 0 && capacity_link_.size() >= state.config.queue_length_packets) { // Too many packet on the link, drop this one. return false; } - // If the packet has been sent before the previous packet in the network left - // the capacity queue, let's ensure the new packet will start its trip in the - // network after the last bit of the previous packet has left it. - int64_t packet_send_time_us = packet.send_time_us; - if (!capacity_link_.empty()) { - packet_send_time_us = - std::max(packet_send_time_us, capacity_link_.back().arrival_time_us); - } - capacity_link_.push({.packet = packet, - .arrival_time_us = CalculateArrivalTimeUs( - packet_send_time_us, packet.size * 8, - state.config.link_capacity_kbps)}); - - // Only update `next_process_time_us_` if not already set (if set, there is no - // way that a new packet will make the `next_process_time_us_` change). + // Set arrival time = send time for now; actual arrival time will be + // calculated in UpdateCapacityQueue. + queue_size_bytes_ += packet.size; + capacity_link_.push({packet, packet.send_time_us}); if (!next_process_time_us_) { - RTC_DCHECK_EQ(capacity_link_.size(), 1); - next_process_time_us_ = capacity_link_.front().arrival_time_us; + next_process_time_us_ = packet.send_time_us + kDefaultProcessDelay.us(); } - last_enqueue_time_us_ = packet.send_time_us; return true; } @@ -148,40 +99,52 @@ absl::optional SimulatedNetwork::NextDeliveryTimeUs() const { void SimulatedNetwork::UpdateCapacityQueue(ConfigState state, int64_t time_now_us) { - // If there is at least one packet in the `capacity_link_`, let's update its - // arrival time to take into account changes in the network configuration - // since the last call to UpdateCapacityQueue. - if (!capacity_link_.empty()) { - capacity_link_.front().arrival_time_us = CalculateArrivalTimeUs( - std::max(capacity_link_.front().packet.send_time_us, - last_capacity_link_exit_time_), - capacity_link_.front().packet.size * 8, - state.config.link_capacity_kbps); - } + bool needs_sort = false; - // The capacity link is empty or the first packet is not expected to exit yet. - if (capacity_link_.empty() || - time_now_us < capacity_link_.front().arrival_time_us) { + // Catch for thread races. + if (time_now_us < last_capacity_link_visit_us_.value_or(time_now_us)) return; - } - bool reorder_packets = false; - do { - // Time to get this packet (the original or just updated arrival_time_us is - // smaller or equal to time_now_us). + int64_t time_us = last_capacity_link_visit_us_.value_or(time_now_us); + // Check the capacity link first. + while (!capacity_link_.empty()) { + int64_t time_until_front_exits_us = 0; + if (state.config.link_capacity_kbps > 0) { + int64_t remaining_bits = + capacity_link_.front().packet.size * 8 - pending_drain_bits_; + RTC_DCHECK(remaining_bits > 0); + // Division rounded up - packet not delivered until its last bit is. + time_until_front_exits_us = + (1000 * remaining_bits + state.config.link_capacity_kbps - 1) / + state.config.link_capacity_kbps; + } + + if (time_us + time_until_front_exits_us > time_now_us) { + // Packet at front will not exit yet. Will not enter here on infinite + // capacity(=0) so no special handling needed. + pending_drain_bits_ += + ((time_now_us - time_us) * state.config.link_capacity_kbps) / 1000; + break; + } + if (state.config.link_capacity_kbps > 0) { + pending_drain_bits_ += + (time_until_front_exits_us * state.config.link_capacity_kbps) / 1000; + } else { + // Enough to drain the whole queue. + pending_drain_bits_ = queue_size_bytes_ * 8; + } + + // Time to get this packet. PacketInfo packet = capacity_link_.front(); capacity_link_.pop(); - // If the network is paused, the pause will be implemented as an extra delay - // to be spent in the `delay_link_` queue. - if (state.pause_transmission_until_us > packet.arrival_time_us) { - packet.arrival_time_us = state.pause_transmission_until_us; - } - - // Store the original arrival time, before applying packet loss or extra - // delay. This is needed to know when it is the first available time the - // next packet in the `capacity_link_` queue can start transmitting. - last_capacity_link_exit_time_ = packet.arrival_time_us; + time_us += time_until_front_exits_us; + RTC_DCHECK(time_us >= packet.packet.send_time_us); + packet.arrival_time_us = + std::max(state.pause_transmission_until_us, time_us); + queue_size_bytes_ -= packet.packet.size; + pending_drain_bits_ -= packet.packet.size * 8; + RTC_DCHECK(pending_drain_bits_ >= 0); // Drop packets at an average rate of `state.config.loss_percent` with // and average loss burst length of `state.config.avg_burst_loss_length`. @@ -190,7 +153,6 @@ void SimulatedNetwork::UpdateCapacityQueue(ConfigState state, bursting_ = true; packet.arrival_time_us = PacketDeliveryInfo::kNotReceived; } else { - // If packets are not dropped, apply extra delay as configured. bursting_ = false; int64_t arrival_time_jitter_us = std::max( random_.Gaussian(state.config.queue_delay_ms * 1000, @@ -207,38 +169,24 @@ void SimulatedNetwork::UpdateCapacityQueue(ConfigState state, arrival_time_jitter_us = last_arrival_time_us - packet.arrival_time_us; } packet.arrival_time_us += arrival_time_jitter_us; - - // Optimization: Schedule a reorder only when a packet will exit before - // the one in front. - if (last_arrival_time_us > packet.arrival_time_us) { - reorder_packets = true; + if (packet.arrival_time_us >= last_arrival_time_us) { + last_arrival_time_us = packet.arrival_time_us; + } else { + needs_sort = true; } } delay_link_.emplace_back(packet); + } + last_capacity_link_visit_us_ = time_now_us; + // Cannot save unused capacity for later. + pending_drain_bits_ = std::min(pending_drain_bits_, queue_size_bytes_ * 8); - // If there are no packets in the queue, there is nothing else to do. - if (capacity_link_.empty()) { - break; - } - // If instead there is another packet in the `capacity_link_` queue, let's - // calculate its arrival_time_us based on the latest config (which might - // have been changed since it was enqueued). - int64_t next_start = std::max(last_capacity_link_exit_time_, - capacity_link_.front().packet.send_time_us); - capacity_link_.front().arrival_time_us = CalculateArrivalTimeUs( - next_start, capacity_link_.front().packet.size * 8, - state.config.link_capacity_kbps); - // And if the next packet in the queue needs to exit, let's dequeue it. - } while (capacity_link_.front().arrival_time_us <= time_now_us); - - if (state.config.allow_reordering && reorder_packets) { - // Packets arrived out of order and since the network config allows - // reordering, let's sort them per arrival_time_us to make so they will also - // be delivered out of order. - std::stable_sort(delay_link_.begin(), delay_link_.end(), - [](const PacketInfo& p1, const PacketInfo& p2) { - return p1.arrival_time_us < p2.arrival_time_us; - }); + if (needs_sort) { + // Packet(s) arrived out of order, make sure list is sorted. + std::sort(delay_link_.begin(), delay_link_.end(), + [](const PacketInfo& p1, const PacketInfo& p2) { + return p1.arrival_time_us < p2.arrival_time_us; + }); } } @@ -250,10 +198,8 @@ SimulatedNetwork::ConfigState SimulatedNetwork::GetConfigState() const { std::vector SimulatedNetwork::DequeueDeliverablePackets( int64_t receive_time_us) { RTC_DCHECK_RUNS_SERIALIZED(&process_checker_); - UpdateCapacityQueue(GetConfigState(), receive_time_us); std::vector packets_to_deliver; - // Check the extra delay queue. while (!delay_link_.empty() && receive_time_us >= delay_link_.front().arrival_time_us) { @@ -266,7 +212,7 @@ std::vector SimulatedNetwork::DequeueDeliverablePackets( if (!delay_link_.empty()) { next_process_time_us_ = delay_link_.front().arrival_time_us; } else if (!capacity_link_.empty()) { - next_process_time_us_ = capacity_link_.front().arrival_time_us; + next_process_time_us_ = receive_time_us + kDefaultProcessDelay.us(); } else { next_process_time_us_.reset(); } diff --git a/call/simulated_network.h b/call/simulated_network.h index 8597367add..d3092aefba 100644 --- a/call/simulated_network.h +++ b/call/simulated_network.h @@ -28,27 +28,16 @@ namespace webrtc { -// Class simulating a network link. -// -// This is a basic implementation of NetworkBehaviorInterface that supports: -// - Packet loss -// - Capacity delay -// - Extra delay with or without packets reorder -// - Packet overhead -// - Queue max capacity +// Class simulating a network link. This is a simple and naive solution just +// faking capacity and adding an extra transport delay in addition to the +// capacity introduced delay. class SimulatedNetwork : public SimulatedNetworkInterface { public: using Config = BuiltInNetworkBehaviorConfig; explicit SimulatedNetwork(Config config, uint64_t random_seed = 1); ~SimulatedNetwork() override; - // Sets a new configuration. This will affect packets that will be sent with - // EnqueuePacket but also packets in the network that have not left the - // network emulation. Packets that are ready to be retrieved by - // DequeueDeliverablePackets are not affected by the new configuration. - // TODO(bugs.webrtc.org/14525): Fix SetConfig and make it apply only to the - // part of the packet that is currently being sent (instead of applying to - // all of it). + // Sets a new configuration. This won't affect packets already in the pipe. void SetConfig(const Config& config) override; void UpdateConfig(std::function config_modifier) override; @@ -64,7 +53,6 @@ class SimulatedNetwork : public SimulatedNetworkInterface { private: struct PacketInfo { PacketInFlightInfo packet; - // Time when the packet has left (or will leave) the network. int64_t arrival_time_us; }; // Contains current configuration state. @@ -87,46 +75,25 @@ class SimulatedNetwork : public SimulatedNetworkInterface { mutable Mutex config_lock_; - // Guards the data structures involved in delay and loss processing, such as - // the packet queues. + // `process_checker_` guards the data structures involved in delay and loss + // processes, such as the packet queues. rtc::RaceChecker process_checker_; - // Models the capacity of the network by rejecting packets if the queue is - // full and keeping them in the queue until they are ready to exit (according - // to the link capacity, which cannot be violated, e.g. a 1 kbps link will - // only be able to deliver 1000 bits per second). - // - // Invariant: - // The head of the `capacity_link_` has arrival_time_us correctly set to the - // time when the packet is supposed to be delivered (without accounting - // potential packet loss or potential extra delay and without accounting for a - // new configuration of the network, which requires a re-computation of the - // arrival_time_us). std::queue capacity_link_ RTC_GUARDED_BY(process_checker_); - // Models the extra delay of the network (see `queue_delay_ms` - // and `delay_standard_deviation_ms` in BuiltInNetworkBehaviorConfig), packets - // in the `delay_link_` have technically already left the network and don't - // use its capacity but they are not delivered yet. + Random random_; + std::deque delay_link_ RTC_GUARDED_BY(process_checker_); - // Represents the next moment in time when the network is supposed to deliver - // packets to the client (either by pulling them from `delay_link_` or - // `capacity_link_` or both). - absl::optional next_process_time_us_ - RTC_GUARDED_BY(process_checker_); ConfigState config_state_ RTC_GUARDED_BY(config_lock_); - Random random_ RTC_GUARDED_BY(process_checker_); // Are we currently dropping a burst of packets? bool bursting_; - // The send time of the last enqueued packet, this is only used to check that - // the send time of enqueued packets is monotonically increasing. - int64_t last_enqueue_time_us_; - - // The last time a packet left the capacity_link_ (used to enforce - // the capacity of the link and avoid packets starts to get sent before - // the link it free). - int64_t last_capacity_link_exit_time_; + int64_t queue_size_bytes_ RTC_GUARDED_BY(process_checker_) = 0; + int64_t pending_drain_bits_ RTC_GUARDED_BY(process_checker_) = 0; + absl::optional last_capacity_link_visit_us_ + RTC_GUARDED_BY(process_checker_); + absl::optional next_process_time_us_ + RTC_GUARDED_BY(process_checker_); }; } // namespace webrtc diff --git a/call/simulated_network_unittest.cc b/call/simulated_network_unittest.cc deleted file mode 100644 index 825dd6d065..0000000000 --- a/call/simulated_network_unittest.cc +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright 2022 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#include "call/simulated_network.h" - -#include -#include -#include -#include -#include - -#include "absl/algorithm/container.h" -#include "api/test/simulated_network.h" -#include "api/units/data_rate.h" -#include "api/units/time_delta.h" -#include "test/gmock.h" -#include "test/gtest.h" - -namespace webrtc { -namespace { - -using ::testing::ElementsAre; - -PacketInFlightInfo PacketWithSize(size_t size) { - return PacketInFlightInfo(/*size=*/size, /*send_time_us=*/0, /*packet_id=*/1); -} - -TEST(SimulatedNetworkTest, NextDeliveryTimeIsUnknownOnEmptyNetwork) { - SimulatedNetwork network = SimulatedNetwork({}); - EXPECT_EQ(network.NextDeliveryTimeUs(), absl::nullopt); -} - -TEST(SimulatedNetworkTest, EnqueueFirstPacketOnNetworkWithInfiniteCapacity) { - // A packet of 1 kB that gets enqueued on a network with infinite capacity - // should be ready to exit the network immediately. - SimulatedNetwork network = SimulatedNetwork({}); - ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(1'000))); - - EXPECT_EQ(network.NextDeliveryTimeUs(), 0); -} - -TEST(SimulatedNetworkTest, EnqueueFirstPacketOnNetworkWithLimitedCapacity) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125))); - - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); -} - -TEST(SimulatedNetworkTest, - EnqueuePacketsButNextDeliveryIsBasedOnFirstEnqueuedPacket) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1))); - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); - - // Enqueuing another packet after 100 us doesn't change the next delivery - // time. - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/100, /*packet_id=*/2))); - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); - - // Enqueuing another packet after 2 seconds doesn't change the next delivery - // time since the first packet has not left the network yet. - ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo( - /*size=*/125, /*send_time_us=*/TimeDelta::Seconds(2).us(), - /*packet_id=*/3))); - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); -} - -TEST(SimulatedNetworkTest, EnqueueFailsWhenQueueLengthIsReached) { - SimulatedNetwork network = - SimulatedNetwork({.queue_length_packets = 1, .link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1))); - - // Until there is 1 packet in the queue, no other packets can be enqueued, - // the only way to make space for new packets is calling - // DequeueDeliverablePackets at a time greater than or equal to - // NextDeliveryTimeUs. - EXPECT_FALSE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, - /*send_time_us=*/TimeDelta::Seconds(0.5).us(), - /*packet_id=*/2))); - - // Even if the send_time_us is after NextDeliveryTimeUs, it is still not - // possible to enqueue a new packet since the client didn't deque any packet - // from the queue (in this case the client is introducing unbounded delay but - // the network cannot do anything about it). - EXPECT_FALSE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, - /*send_time_us=*/TimeDelta::Seconds(2).us(), - /*packet_id=*/3))); -} - -TEST(SimulatedNetworkTest, PacketOverhead) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second, but since there is an - // overhead per packet of 125 bytes, it will exit the network after 2 seconds. - SimulatedNetwork network = - SimulatedNetwork({.link_capacity_kbps = 1, .packet_overhead = 125}); - ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125))); - - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(2).us()); -} - -TEST(SimulatedNetworkTest, - DequeueDeliverablePacketsLeavesPacketsInCapacityLink) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1))); - // Enqueue another packet of 125 bytes (this one should exit after 2 seconds). - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, - /*send_time_us=*/TimeDelta::Seconds(1).us(), - /*packet_id=*/2))); - - // The first packet will exit after 1 second, so that is the next delivery - // time. - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); - - // After 1 seconds, we collect the delivered packets... - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(1).us()); - ASSERT_EQ(delivered_packets.size(), 1ul); - EXPECT_EQ(delivered_packets[0].packet_id, 1ul); - EXPECT_EQ(delivered_packets[0].receive_time_us, TimeDelta::Seconds(1).us()); - - // ... And after the first enqueued packet has left the network, the next - // delivery time reflects the delivery time of the next packet. - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(2).us()); -} - -TEST(SimulatedNetworkTest, - DequeueDeliverablePacketsAppliesConfigChangesToCapacityLink) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - const PacketInFlightInfo packet_1 = - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1); - ASSERT_TRUE(network.EnqueuePacket(packet_1)); - - // Enqueue another packet of 125 bytes with send time 1 second so this should - // exit after 2 seconds. - PacketInFlightInfo packet_2 = - PacketInFlightInfo(/*size=*/125, - /*send_time_us=*/TimeDelta::Seconds(1).us(), - /*packet_id=*/2); - ASSERT_TRUE(network.EnqueuePacket(packet_2)); - - // The first packet will exit after 1 second, so that is the next delivery - // time. - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); - - // Since the link capacity changes from 1 kbps to 10 kbps, packets will take - // 100 ms each to leave the network. - network.SetConfig({.link_capacity_kbps = 10}); - - // The next delivery time doesn't change (it will be updated, if needed at - // DequeueDeliverablePackets time). - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); - - // Getting the first enqueued packet after 100 ms. - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Millis(100).us()); - ASSERT_EQ(delivered_packets.size(), 1ul); - EXPECT_THAT(delivered_packets, - ElementsAre(PacketDeliveryInfo( - /*source=*/packet_1, - /*receive_time_us=*/TimeDelta::Millis(100).us()))); - - // Getting the second enqueued packet that cannot be delivered before its send - // time, hence it will be delivered after 1.1 seconds. - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Millis(1100).us()); - delivered_packets = network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Millis(1100).us()); - ASSERT_EQ(delivered_packets.size(), 1ul); - EXPECT_THAT(delivered_packets, - ElementsAre(PacketDeliveryInfo( - /*source=*/packet_2, - /*receive_time_us=*/TimeDelta::Millis(1100).us()))); -} - -TEST(SimulatedNetworkTest, NetworkEmptyAfterLastPacketDequeued) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125))); - - // Collecting all the delivered packets ... - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(1).us()); - EXPECT_EQ(delivered_packets.size(), 1ul); - - // ... leaves the network empty. - EXPECT_EQ(network.NextDeliveryTimeUs(), absl::nullopt); -} - -TEST(SimulatedNetworkTest, DequeueDeliverablePacketsOnLateCall) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1))); - - // Enqueue another packet of 125 bytes with send time 1 second so this should - // exit after 2 seconds. - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, - /*send_time_us=*/TimeDelta::Seconds(1).us(), - /*packet_id=*/2))); - - // Collecting delivered packets after 3 seconds will result in the delivery of - // both the enqueued packets. - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(3).us()); - EXPECT_EQ(delivered_packets.size(), 2ul); -} - -TEST(SimulatedNetworkTest, - DequeueDeliverablePacketsOnEarlyCallReturnsNoPackets) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125))); - - // Collecting delivered packets after 0.5 seconds will result in the delivery - // of 0 packets. - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(0.5).us()); - EXPECT_EQ(delivered_packets.size(), 0ul); - - // Since the first enqueued packet was supposed to exit after 1 second. - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); -} - -TEST(SimulatedNetworkTest, QueueDelayMsWithoutStandardDeviation) { - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - SimulatedNetwork network = - SimulatedNetwork({.queue_delay_ms = 100, .link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125))); - // The next delivery time is still 1 second even if there are 100 ms of - // extra delay but this will be applied at DequeueDeliverablePackets time. - ASSERT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); - - // Since all packets are delayed by 100 ms, after 1 second, no packets will - // exit the network. - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(1).us()); - EXPECT_EQ(delivered_packets.size(), 0ul); - - // And the updated next delivery time takes into account the extra delay of - // 100 ms so the first packet in the network will be delivered after 1.1 - // seconds. - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Millis(1100).us()); - delivered_packets = network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Millis(1100).us()); - EXPECT_EQ(delivered_packets.size(), 1ul); -} - -TEST(SimulatedNetworkTest, - QueueDelayMsWithStandardDeviationAndReorderNotAllowed) { - SimulatedNetwork network = - SimulatedNetwork({.queue_delay_ms = 100, - .delay_standard_deviation_ms = 90, - .link_capacity_kbps = 1, - .allow_reordering = false}); - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1))); - - // But 3 more packets of size 1 byte are enqueued at the same time. - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/2))); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/3))); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/4))); - - // After 5 seconds all of them exit the network. - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(5).us()); - ASSERT_EQ(delivered_packets.size(), 4ul); - - // And they are still in order even if the delay was applied. - EXPECT_EQ(delivered_packets[0].packet_id, 1ul); - EXPECT_EQ(delivered_packets[1].packet_id, 2ul); - EXPECT_GE(delivered_packets[1].receive_time_us, - delivered_packets[0].receive_time_us); - EXPECT_EQ(delivered_packets[2].packet_id, 3ul); - EXPECT_GE(delivered_packets[2].receive_time_us, - delivered_packets[1].receive_time_us); - EXPECT_EQ(delivered_packets[3].packet_id, 4ul); - EXPECT_GE(delivered_packets[3].receive_time_us, - delivered_packets[2].receive_time_us); -} - -TEST(SimulatedNetworkTest, QueueDelayMsWithStandardDeviationAndReorderAllowed) { - SimulatedNetwork network = - SimulatedNetwork({.queue_delay_ms = 100, - .delay_standard_deviation_ms = 90, - .link_capacity_kbps = 1, - .allow_reordering = true}, - /*random_seed=*/1); - // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network in 1 second. - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1))); - - // But 3 more packets of size 1 byte are enqueued at the same time. - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/2))); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/3))); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/4))); - - // After 5 seconds all of them exit the network. - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(5).us()); - ASSERT_EQ(delivered_packets.size(), 4ul); - - // And they have been reordered accorting to the applied extra delay. - EXPECT_EQ(delivered_packets[0].packet_id, 3ul); - EXPECT_EQ(delivered_packets[1].packet_id, 1ul); - EXPECT_GE(delivered_packets[1].receive_time_us, - delivered_packets[0].receive_time_us); - EXPECT_EQ(delivered_packets[2].packet_id, 2ul); - EXPECT_GE(delivered_packets[2].receive_time_us, - delivered_packets[1].receive_time_us); - EXPECT_EQ(delivered_packets[3].packet_id, 4ul); - EXPECT_GE(delivered_packets[3].receive_time_us, - delivered_packets[2].receive_time_us); -} - -TEST(SimulatedNetworkTest, PacketLoss) { - // On a network with 50% probablility of packet loss ... - SimulatedNetwork network = SimulatedNetwork({.loss_percent = 50}); - - // Enqueueing 8 packets ... - for (int i = 0; i < 8; i++) { - ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo( - /*size=*/1, /*send_time_us=*/0, /*packet_id=*/i + 1))); - } - - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(5).us()); - EXPECT_EQ(delivered_packets.size(), 8ul); - - // Results in the loss of 4 of them. - int lost_packets = 0; - for (const auto& packet : delivered_packets) { - if (packet.receive_time_us == PacketDeliveryInfo::kNotReceived) { - lost_packets++; - } - } - EXPECT_EQ(lost_packets, 4); -} - -TEST(SimulatedNetworkTest, PacketLossBurst) { - // On a network with 50% probablility of packet loss and an average burst loss - // length of 100 ... - SimulatedNetwork network = SimulatedNetwork( - {.loss_percent = 50, .avg_burst_loss_length = 100}, /*random_seed=*/1); - - // Enqueueing 20 packets ... - for (int i = 0; i < 20; i++) { - ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo( - /*size=*/1, /*send_time_us=*/0, /*packet_id=*/i + 1))); - } - - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(5).us()); - EXPECT_EQ(delivered_packets.size(), 20ul); - - // Results in a burst of lost packets after the first packet lost. - // With the current random seed, the first 12 are not lost, while the - // last 8 are. - int current_packet = 0; - for (const auto& packet : delivered_packets) { - if (current_packet < 12) { - EXPECT_NE(packet.receive_time_us, PacketDeliveryInfo::kNotReceived); - current_packet++; - } else { - EXPECT_EQ(packet.receive_time_us, PacketDeliveryInfo::kNotReceived); - current_packet++; - } - } -} - -TEST(SimulatedNetworkTest, PauseTransmissionUntil) { - // 3 packets of 125 bytes that gets enqueued on a network with 1 kbps capacity - // should be ready to exit the network after 1, 2 and 3 seconds respectively. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1))); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/2))); - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/3))); - ASSERT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us()); - - // The network gets paused for 5 seconds, which means that the first packet - // can exit after 5 seconds instead of 1 second. - network.PauseTransmissionUntil(TimeDelta::Seconds(5).us()); - - // No packets after 1 second. - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(1).us()); - EXPECT_EQ(delivered_packets.size(), 0ul); - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(5).us()); - - // The first packet exits after 5 seconds. - delivered_packets = network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(5).us()); - EXPECT_EQ(delivered_packets.size(), 1ul); - - // After the first packet is exited, the next delivery time reflects the - // delivery time of the next packet which accounts for the network pause. - EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(6).us()); - - // And 2 seconds after the exit of the first enqueued packet, the following 2 - // packets are also delivered. - delivered_packets = network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(7).us()); - EXPECT_EQ(delivered_packets.size(), 2ul); -} - -TEST(SimulatedNetworkTest, CongestedNetworkRespectsLinkCapacity) { - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - for (size_t i = 0; i < 1'000; ++i) { - ASSERT_TRUE(network.EnqueuePacket( - PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/i))); - } - PacketDeliveryInfo last_delivered_packet{ - PacketInFlightInfo(/*size=*/0, /*send_time_us=*/0, /*packet_id=*/0), 0}; - while (network.NextDeliveryTimeUs().has_value()) { - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/network.NextDeliveryTimeUs().value()); - if (!delivered_packets.empty()) { - last_delivered_packet = delivered_packets.back(); - } - } - // 1000 packets of 1000 bits each will take 1000 seconds to exit a 1 kpbs - // network. - EXPECT_EQ(last_delivered_packet.receive_time_us, - TimeDelta::Seconds(1000).us()); - EXPECT_EQ(last_delivered_packet.packet_id, 999ul); -} - -TEST(SimulatedNetworkTest, EnqueuePacketWithSubSecondNonMonotonicBehaviour) { - // On multi-core systems, different threads can experience sub-millisecond non - // monothonic behaviour when running on different cores. This test checks that - // when a non monotonic packet enqueue, the network continues to work and the - // out of order packet is sent anyway. - SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); - ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo( - /*size=*/125, /*send_time_us=*/TimeDelta::Seconds(1).us(), - /*packet_id=*/0))); - ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo( - /*size=*/125, /*send_time_us=*/TimeDelta::Seconds(1).us() - 1, - /*packet_id=*/1))); - - std::vector delivered_packets = - network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(2).us()); - ASSERT_EQ(delivered_packets.size(), 1ul); - EXPECT_EQ(delivered_packets[0].packet_id, 0ul); - EXPECT_EQ(delivered_packets[0].receive_time_us, TimeDelta::Seconds(2).us()); - - delivered_packets = network.DequeueDeliverablePackets( - /*receive_time_us=*/TimeDelta::Seconds(3).us()); - ASSERT_EQ(delivered_packets.size(), 1ul); - EXPECT_EQ(delivered_packets[0].packet_id, 1ul); - EXPECT_EQ(delivered_packets[0].receive_time_us, TimeDelta::Seconds(3).us()); -} - -// TODO(bugs.webrtc.org/14525): Re-enable when the DCHECK will be uncommented -// and the non-monotonic events on real time clock tests is solved/understood. -// TEST(SimulatedNetworkDeathTest, EnqueuePacketExpectMonotonicSendTime) { -// SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1}); -// ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo( -// /*size=*/125, /*send_time_us=*/2'000'000, /*packet_id=*/0))); -// EXPECT_DEATH_IF_SUPPORTED(network.EnqueuePacket(PacketInFlightInfo( -// /*size=*/125, /*send_time_us=*/900'000, /*packet_id=*/1)), ""); -// } -} // namespace -} // namespace webrtc diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc index 44054f10db..8ba556c20e 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc @@ -677,8 +677,8 @@ TEST(GoogCcScenario, LossBasedRecoversFasterAfterCrossInducedLoss) { DataRate average_bitrate_with_loss_based = AverageBitrateAfterCrossInducedLoss("googcc_unit/cross_loss_based"); - EXPECT_GT(average_bitrate_with_loss_based, - average_bitrate_without_loss_based); + EXPECT_GE(average_bitrate_with_loss_based, + average_bitrate_without_loss_based * 1.05); } TEST(GoogCcScenario, LossBasedEstimatorCapsRateAtModerateLoss) { diff --git a/test/peer_scenario/tests/remote_estimate_test.cc b/test/peer_scenario/tests/remote_estimate_test.cc index 2dfbfdd3c9..9190f5c92e 100644 --- a/test/peer_scenario/tests/remote_estimate_test.cc +++ b/test/peer_scenario/tests/remote_estimate_test.cc @@ -96,10 +96,7 @@ TEST(RemoteEstimateEndToEnd, AudioUsesAbsSendTimeExtension) { // want to ignore those and we can do that on the basis that the first // byte of RTP packets are guaranteed to not be 0. RtpPacket rtp_packet(&extension_map); - // TODO(bugs.webrtc.org/14525): Look why there are RTP packets with - // payload 72 or 73 (these don't have the RTP AbsoluteSendTime - // Extension). - if (rtp_packet.Parse(packet.data) && rtp_packet.PayloadType() == 111) { + if (rtp_packet.Parse(packet.data)) { EXPECT_TRUE(rtp_packet.HasExtension()); received_abs_send_time = true; }