diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/libwebrtc/call/simulated_network_unittest.cc | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/call/simulated_network_unittest.cc')
-rw-r--r-- | third_party/libwebrtc/call/simulated_network_unittest.cc | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/third_party/libwebrtc/call/simulated_network_unittest.cc b/third_party/libwebrtc/call/simulated_network_unittest.cc new file mode 100644 index 0000000000..825dd6d065 --- /dev/null +++ b/third_party/libwebrtc/call/simulated_network_unittest.cc @@ -0,0 +1,513 @@ +/* + * 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 <algorithm> +#include <map> +#include <optional> +#include <set> +#include <vector> + +#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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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<PacketDeliveryInfo> 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 |