xref: /aosp_15_r20/external/webrtc/call/simulated_network_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2022 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker #include "call/simulated_network.h"
11*d9f75844SAndroid Build Coastguard Worker 
12*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
13*d9f75844SAndroid Build Coastguard Worker #include <map>
14*d9f75844SAndroid Build Coastguard Worker #include <optional>
15*d9f75844SAndroid Build Coastguard Worker #include <set>
16*d9f75844SAndroid Build Coastguard Worker #include <vector>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/test/simulated_network.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/units/data_rate.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
22*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
23*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
24*d9f75844SAndroid Build Coastguard Worker 
25*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
26*d9f75844SAndroid Build Coastguard Worker namespace {
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker using ::testing::ElementsAre;
29*d9f75844SAndroid Build Coastguard Worker 
PacketWithSize(size_t size)30*d9f75844SAndroid Build Coastguard Worker PacketInFlightInfo PacketWithSize(size_t size) {
31*d9f75844SAndroid Build Coastguard Worker   return PacketInFlightInfo(/*size=*/size, /*send_time_us=*/0, /*packet_id=*/1);
32*d9f75844SAndroid Build Coastguard Worker }
33*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,NextDeliveryTimeIsUnknownOnEmptyNetwork)34*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, NextDeliveryTimeIsUnknownOnEmptyNetwork) {
35*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({});
36*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), absl::nullopt);
37*d9f75844SAndroid Build Coastguard Worker }
38*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,EnqueueFirstPacketOnNetworkWithInfiniteCapacity)39*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, EnqueueFirstPacketOnNetworkWithInfiniteCapacity) {
40*d9f75844SAndroid Build Coastguard Worker   // A packet of 1 kB that gets enqueued on a network with infinite capacity
41*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network immediately.
42*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({});
43*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(1'000)));
44*d9f75844SAndroid Build Coastguard Worker 
45*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), 0);
46*d9f75844SAndroid Build Coastguard Worker }
47*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,EnqueueFirstPacketOnNetworkWithLimitedCapacity)48*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, EnqueueFirstPacketOnNetworkWithLimitedCapacity) {
49*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
50*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
51*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
52*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125)));
53*d9f75844SAndroid Build Coastguard Worker 
54*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
55*d9f75844SAndroid Build Coastguard Worker }
56*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,EnqueuePacketsButNextDeliveryIsBasedOnFirstEnqueuedPacket)57*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest,
58*d9f75844SAndroid Build Coastguard Worker      EnqueuePacketsButNextDeliveryIsBasedOnFirstEnqueuedPacket) {
59*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
60*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
61*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
62*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
63*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1)));
64*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
65*d9f75844SAndroid Build Coastguard Worker 
66*d9f75844SAndroid Build Coastguard Worker   // Enqueuing another packet after 100 us doesn't change the next delivery
67*d9f75844SAndroid Build Coastguard Worker   // time.
68*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
69*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/100, /*packet_id=*/2)));
70*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker   // Enqueuing another packet after 2 seconds doesn't change the next delivery
73*d9f75844SAndroid Build Coastguard Worker   // time since the first packet has not left the network yet.
74*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo(
75*d9f75844SAndroid Build Coastguard Worker       /*size=*/125, /*send_time_us=*/TimeDelta::Seconds(2).us(),
76*d9f75844SAndroid Build Coastguard Worker       /*packet_id=*/3)));
77*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,EnqueueFailsWhenQueueLengthIsReached)80*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, EnqueueFailsWhenQueueLengthIsReached) {
81*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network =
82*d9f75844SAndroid Build Coastguard Worker       SimulatedNetwork({.queue_length_packets = 1, .link_capacity_kbps = 1});
83*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
84*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1)));
85*d9f75844SAndroid Build Coastguard Worker 
86*d9f75844SAndroid Build Coastguard Worker   // Until there is 1 packet in the queue, no other packets can be enqueued,
87*d9f75844SAndroid Build Coastguard Worker   // the only way to make space for new packets is calling
88*d9f75844SAndroid Build Coastguard Worker   // DequeueDeliverablePackets at a time greater than or equal to
89*d9f75844SAndroid Build Coastguard Worker   // NextDeliveryTimeUs.
90*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(network.EnqueuePacket(
91*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125,
92*d9f75844SAndroid Build Coastguard Worker                          /*send_time_us=*/TimeDelta::Seconds(0.5).us(),
93*d9f75844SAndroid Build Coastguard Worker                          /*packet_id=*/2)));
94*d9f75844SAndroid Build Coastguard Worker 
95*d9f75844SAndroid Build Coastguard Worker   // Even if the send_time_us is after NextDeliveryTimeUs, it is still not
96*d9f75844SAndroid Build Coastguard Worker   // possible to enqueue a new packet since the client didn't deque any packet
97*d9f75844SAndroid Build Coastguard Worker   // from the queue (in this case the client is introducing unbounded delay but
98*d9f75844SAndroid Build Coastguard Worker   // the network cannot do anything about it).
99*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(network.EnqueuePacket(
100*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125,
101*d9f75844SAndroid Build Coastguard Worker                          /*send_time_us=*/TimeDelta::Seconds(2).us(),
102*d9f75844SAndroid Build Coastguard Worker                          /*packet_id=*/3)));
103*d9f75844SAndroid Build Coastguard Worker }
104*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,PacketOverhead)105*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, PacketOverhead) {
106*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
107*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second, but since there is an
108*d9f75844SAndroid Build Coastguard Worker   // overhead per packet of 125 bytes, it will exit the network after 2 seconds.
109*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network =
110*d9f75844SAndroid Build Coastguard Worker       SimulatedNetwork({.link_capacity_kbps = 1, .packet_overhead = 125});
111*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125)));
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(2).us());
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,DequeueDeliverablePacketsLeavesPacketsInCapacityLink)116*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest,
117*d9f75844SAndroid Build Coastguard Worker      DequeueDeliverablePacketsLeavesPacketsInCapacityLink) {
118*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
119*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
120*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
121*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
122*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1)));
123*d9f75844SAndroid Build Coastguard Worker   // Enqueue another packet of 125 bytes (this one should exit after 2 seconds).
124*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
125*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125,
126*d9f75844SAndroid Build Coastguard Worker                          /*send_time_us=*/TimeDelta::Seconds(1).us(),
127*d9f75844SAndroid Build Coastguard Worker                          /*packet_id=*/2)));
128*d9f75844SAndroid Build Coastguard Worker 
129*d9f75844SAndroid Build Coastguard Worker   // The first packet will exit after 1 second, so that is the next delivery
130*d9f75844SAndroid Build Coastguard Worker   // time.
131*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
132*d9f75844SAndroid Build Coastguard Worker 
133*d9f75844SAndroid Build Coastguard Worker   // After 1 seconds, we collect the delivered packets...
134*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
135*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
136*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(1).us());
137*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(delivered_packets.size(), 1ul);
138*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[0].packet_id, 1ul);
139*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[0].receive_time_us, TimeDelta::Seconds(1).us());
140*d9f75844SAndroid Build Coastguard Worker 
141*d9f75844SAndroid Build Coastguard Worker   // ... And after the first enqueued packet has left the network, the next
142*d9f75844SAndroid Build Coastguard Worker   // delivery time reflects the delivery time of the next packet.
143*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(2).us());
144*d9f75844SAndroid Build Coastguard Worker }
145*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,DequeueDeliverablePacketsAppliesConfigChangesToCapacityLink)146*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest,
147*d9f75844SAndroid Build Coastguard Worker      DequeueDeliverablePacketsAppliesConfigChangesToCapacityLink) {
148*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
149*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
150*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
151*d9f75844SAndroid Build Coastguard Worker   const PacketInFlightInfo packet_1 =
152*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1);
153*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(packet_1));
154*d9f75844SAndroid Build Coastguard Worker 
155*d9f75844SAndroid Build Coastguard Worker   // Enqueue another packet of 125 bytes with send time 1 second so this should
156*d9f75844SAndroid Build Coastguard Worker   // exit after 2 seconds.
157*d9f75844SAndroid Build Coastguard Worker   PacketInFlightInfo packet_2 =
158*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125,
159*d9f75844SAndroid Build Coastguard Worker                          /*send_time_us=*/TimeDelta::Seconds(1).us(),
160*d9f75844SAndroid Build Coastguard Worker                          /*packet_id=*/2);
161*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(packet_2));
162*d9f75844SAndroid Build Coastguard Worker 
163*d9f75844SAndroid Build Coastguard Worker   // The first packet will exit after 1 second, so that is the next delivery
164*d9f75844SAndroid Build Coastguard Worker   // time.
165*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
166*d9f75844SAndroid Build Coastguard Worker 
167*d9f75844SAndroid Build Coastguard Worker   // Since the link capacity changes from 1 kbps to 10 kbps, packets will take
168*d9f75844SAndroid Build Coastguard Worker   // 100 ms each to leave the network.
169*d9f75844SAndroid Build Coastguard Worker   network.SetConfig({.link_capacity_kbps = 10});
170*d9f75844SAndroid Build Coastguard Worker 
171*d9f75844SAndroid Build Coastguard Worker   // The next delivery time doesn't change (it will be updated, if needed at
172*d9f75844SAndroid Build Coastguard Worker   // DequeueDeliverablePackets time).
173*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
174*d9f75844SAndroid Build Coastguard Worker 
175*d9f75844SAndroid Build Coastguard Worker   // Getting the first enqueued packet after 100 ms.
176*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
177*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
178*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Millis(100).us());
179*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(delivered_packets.size(), 1ul);
180*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(delivered_packets,
181*d9f75844SAndroid Build Coastguard Worker               ElementsAre(PacketDeliveryInfo(
182*d9f75844SAndroid Build Coastguard Worker                   /*source=*/packet_1,
183*d9f75844SAndroid Build Coastguard Worker                   /*receive_time_us=*/TimeDelta::Millis(100).us())));
184*d9f75844SAndroid Build Coastguard Worker 
185*d9f75844SAndroid Build Coastguard Worker   // Getting the second enqueued packet that cannot be delivered before its send
186*d9f75844SAndroid Build Coastguard Worker   // time, hence it will be delivered after 1.1 seconds.
187*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Millis(1100).us());
188*d9f75844SAndroid Build Coastguard Worker   delivered_packets = network.DequeueDeliverablePackets(
189*d9f75844SAndroid Build Coastguard Worker       /*receive_time_us=*/TimeDelta::Millis(1100).us());
190*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(delivered_packets.size(), 1ul);
191*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(delivered_packets,
192*d9f75844SAndroid Build Coastguard Worker               ElementsAre(PacketDeliveryInfo(
193*d9f75844SAndroid Build Coastguard Worker                   /*source=*/packet_2,
194*d9f75844SAndroid Build Coastguard Worker                   /*receive_time_us=*/TimeDelta::Millis(1100).us())));
195*d9f75844SAndroid Build Coastguard Worker }
196*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,NetworkEmptyAfterLastPacketDequeued)197*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, NetworkEmptyAfterLastPacketDequeued) {
198*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
199*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
200*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
201*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125)));
202*d9f75844SAndroid Build Coastguard Worker 
203*d9f75844SAndroid Build Coastguard Worker   // Collecting all the delivered packets ...
204*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
205*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
206*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(1).us());
207*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 1ul);
208*d9f75844SAndroid Build Coastguard Worker 
209*d9f75844SAndroid Build Coastguard Worker   // ... leaves the network empty.
210*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), absl::nullopt);
211*d9f75844SAndroid Build Coastguard Worker }
212*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,DequeueDeliverablePacketsOnLateCall)213*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, DequeueDeliverablePacketsOnLateCall) {
214*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
215*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
216*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
217*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
218*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1)));
219*d9f75844SAndroid Build Coastguard Worker 
220*d9f75844SAndroid Build Coastguard Worker   // Enqueue another packet of 125 bytes with send time 1 second so this should
221*d9f75844SAndroid Build Coastguard Worker   // exit after 2 seconds.
222*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
223*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125,
224*d9f75844SAndroid Build Coastguard Worker                          /*send_time_us=*/TimeDelta::Seconds(1).us(),
225*d9f75844SAndroid Build Coastguard Worker                          /*packet_id=*/2)));
226*d9f75844SAndroid Build Coastguard Worker 
227*d9f75844SAndroid Build Coastguard Worker   // Collecting delivered packets after 3 seconds will result in the delivery of
228*d9f75844SAndroid Build Coastguard Worker   // both the enqueued packets.
229*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
230*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
231*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(3).us());
232*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 2ul);
233*d9f75844SAndroid Build Coastguard Worker }
234*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,DequeueDeliverablePacketsOnEarlyCallReturnsNoPackets)235*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest,
236*d9f75844SAndroid Build Coastguard Worker      DequeueDeliverablePacketsOnEarlyCallReturnsNoPackets) {
237*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
238*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
239*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
240*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125)));
241*d9f75844SAndroid Build Coastguard Worker 
242*d9f75844SAndroid Build Coastguard Worker   // Collecting delivered packets after 0.5 seconds will result in the delivery
243*d9f75844SAndroid Build Coastguard Worker   // of 0 packets.
244*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
245*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
246*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(0.5).us());
247*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 0ul);
248*d9f75844SAndroid Build Coastguard Worker 
249*d9f75844SAndroid Build Coastguard Worker   // Since the first enqueued packet was supposed to exit after 1 second.
250*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
251*d9f75844SAndroid Build Coastguard Worker }
252*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,QueueDelayMsWithoutStandardDeviation)253*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, QueueDelayMsWithoutStandardDeviation) {
254*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
255*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
256*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network =
257*d9f75844SAndroid Build Coastguard Worker       SimulatedNetwork({.queue_delay_ms = 100, .link_capacity_kbps = 1});
258*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketWithSize(125)));
259*d9f75844SAndroid Build Coastguard Worker   // The next delivery time is still 1 second even if there are 100 ms of
260*d9f75844SAndroid Build Coastguard Worker   // extra delay but this will be applied at DequeueDeliverablePackets time.
261*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
262*d9f75844SAndroid Build Coastguard Worker 
263*d9f75844SAndroid Build Coastguard Worker   // Since all packets are delayed by 100 ms, after 1 second, no packets will
264*d9f75844SAndroid Build Coastguard Worker   // exit the network.
265*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
266*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
267*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(1).us());
268*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 0ul);
269*d9f75844SAndroid Build Coastguard Worker 
270*d9f75844SAndroid Build Coastguard Worker   // And the updated next delivery time takes into account the extra delay of
271*d9f75844SAndroid Build Coastguard Worker   // 100 ms so the first packet in the network will be delivered after 1.1
272*d9f75844SAndroid Build Coastguard Worker   // seconds.
273*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Millis(1100).us());
274*d9f75844SAndroid Build Coastguard Worker   delivered_packets = network.DequeueDeliverablePackets(
275*d9f75844SAndroid Build Coastguard Worker       /*receive_time_us=*/TimeDelta::Millis(1100).us());
276*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 1ul);
277*d9f75844SAndroid Build Coastguard Worker }
278*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,QueueDelayMsWithStandardDeviationAndReorderNotAllowed)279*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest,
280*d9f75844SAndroid Build Coastguard Worker      QueueDelayMsWithStandardDeviationAndReorderNotAllowed) {
281*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network =
282*d9f75844SAndroid Build Coastguard Worker       SimulatedNetwork({.queue_delay_ms = 100,
283*d9f75844SAndroid Build Coastguard Worker                         .delay_standard_deviation_ms = 90,
284*d9f75844SAndroid Build Coastguard Worker                         .link_capacity_kbps = 1,
285*d9f75844SAndroid Build Coastguard Worker                         .allow_reordering = false});
286*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
287*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
288*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
289*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1)));
290*d9f75844SAndroid Build Coastguard Worker 
291*d9f75844SAndroid Build Coastguard Worker   // But 3 more packets of size 1 byte are enqueued at the same time.
292*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
293*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/2)));
294*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
295*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/3)));
296*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
297*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/4)));
298*d9f75844SAndroid Build Coastguard Worker 
299*d9f75844SAndroid Build Coastguard Worker   // After 5 seconds all of them exit the network.
300*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
301*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
302*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(5).us());
303*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(delivered_packets.size(), 4ul);
304*d9f75844SAndroid Build Coastguard Worker 
305*d9f75844SAndroid Build Coastguard Worker   // And they are still in order even if the delay was applied.
306*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[0].packet_id, 1ul);
307*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[1].packet_id, 2ul);
308*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(delivered_packets[1].receive_time_us,
309*d9f75844SAndroid Build Coastguard Worker             delivered_packets[0].receive_time_us);
310*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[2].packet_id, 3ul);
311*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(delivered_packets[2].receive_time_us,
312*d9f75844SAndroid Build Coastguard Worker             delivered_packets[1].receive_time_us);
313*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[3].packet_id, 4ul);
314*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(delivered_packets[3].receive_time_us,
315*d9f75844SAndroid Build Coastguard Worker             delivered_packets[2].receive_time_us);
316*d9f75844SAndroid Build Coastguard Worker }
317*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,QueueDelayMsWithStandardDeviationAndReorderAllowed)318*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, QueueDelayMsWithStandardDeviationAndReorderAllowed) {
319*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network =
320*d9f75844SAndroid Build Coastguard Worker       SimulatedNetwork({.queue_delay_ms = 100,
321*d9f75844SAndroid Build Coastguard Worker                         .delay_standard_deviation_ms = 90,
322*d9f75844SAndroid Build Coastguard Worker                         .link_capacity_kbps = 1,
323*d9f75844SAndroid Build Coastguard Worker                         .allow_reordering = true},
324*d9f75844SAndroid Build Coastguard Worker                        /*random_seed=*/1);
325*d9f75844SAndroid Build Coastguard Worker   // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity
326*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network in 1 second.
327*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
328*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1)));
329*d9f75844SAndroid Build Coastguard Worker 
330*d9f75844SAndroid Build Coastguard Worker   // But 3 more packets of size 1 byte are enqueued at the same time.
331*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
332*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/2)));
333*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
334*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/3)));
335*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
336*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/4)));
337*d9f75844SAndroid Build Coastguard Worker 
338*d9f75844SAndroid Build Coastguard Worker   // After 5 seconds all of them exit the network.
339*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
340*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
341*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(5).us());
342*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(delivered_packets.size(), 4ul);
343*d9f75844SAndroid Build Coastguard Worker 
344*d9f75844SAndroid Build Coastguard Worker   // And they have been reordered accorting to the applied extra delay.
345*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[0].packet_id, 3ul);
346*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[1].packet_id, 1ul);
347*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(delivered_packets[1].receive_time_us,
348*d9f75844SAndroid Build Coastguard Worker             delivered_packets[0].receive_time_us);
349*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[2].packet_id, 2ul);
350*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(delivered_packets[2].receive_time_us,
351*d9f75844SAndroid Build Coastguard Worker             delivered_packets[1].receive_time_us);
352*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[3].packet_id, 4ul);
353*d9f75844SAndroid Build Coastguard Worker   EXPECT_GE(delivered_packets[3].receive_time_us,
354*d9f75844SAndroid Build Coastguard Worker             delivered_packets[2].receive_time_us);
355*d9f75844SAndroid Build Coastguard Worker }
356*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,PacketLoss)357*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, PacketLoss) {
358*d9f75844SAndroid Build Coastguard Worker   // On a network with 50% probablility of packet loss ...
359*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.loss_percent = 50});
360*d9f75844SAndroid Build Coastguard Worker 
361*d9f75844SAndroid Build Coastguard Worker   // Enqueueing 8 packets ...
362*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 8; i++) {
363*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo(
364*d9f75844SAndroid Build Coastguard Worker         /*size=*/1, /*send_time_us=*/0, /*packet_id=*/i + 1)));
365*d9f75844SAndroid Build Coastguard Worker   }
366*d9f75844SAndroid Build Coastguard Worker 
367*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
368*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
369*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(5).us());
370*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 8ul);
371*d9f75844SAndroid Build Coastguard Worker 
372*d9f75844SAndroid Build Coastguard Worker   // Results in the loss of 4 of them.
373*d9f75844SAndroid Build Coastguard Worker   int lost_packets = 0;
374*d9f75844SAndroid Build Coastguard Worker   for (const auto& packet : delivered_packets) {
375*d9f75844SAndroid Build Coastguard Worker     if (packet.receive_time_us == PacketDeliveryInfo::kNotReceived) {
376*d9f75844SAndroid Build Coastguard Worker       lost_packets++;
377*d9f75844SAndroid Build Coastguard Worker     }
378*d9f75844SAndroid Build Coastguard Worker   }
379*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(lost_packets, 4);
380*d9f75844SAndroid Build Coastguard Worker }
381*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,PacketLossBurst)382*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, PacketLossBurst) {
383*d9f75844SAndroid Build Coastguard Worker   // On a network with 50% probablility of packet loss and an average burst loss
384*d9f75844SAndroid Build Coastguard Worker   // length of 100 ...
385*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork(
386*d9f75844SAndroid Build Coastguard Worker       {.loss_percent = 50, .avg_burst_loss_length = 100}, /*random_seed=*/1);
387*d9f75844SAndroid Build Coastguard Worker 
388*d9f75844SAndroid Build Coastguard Worker   // Enqueueing 20 packets ...
389*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 20; i++) {
390*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo(
391*d9f75844SAndroid Build Coastguard Worker         /*size=*/1, /*send_time_us=*/0, /*packet_id=*/i + 1)));
392*d9f75844SAndroid Build Coastguard Worker   }
393*d9f75844SAndroid Build Coastguard Worker 
394*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
395*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
396*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(5).us());
397*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 20ul);
398*d9f75844SAndroid Build Coastguard Worker 
399*d9f75844SAndroid Build Coastguard Worker   // Results in a burst of lost packets after the first packet lost.
400*d9f75844SAndroid Build Coastguard Worker   // With the current random seed, the first 12 are not lost, while the
401*d9f75844SAndroid Build Coastguard Worker   // last 8 are.
402*d9f75844SAndroid Build Coastguard Worker   int current_packet = 0;
403*d9f75844SAndroid Build Coastguard Worker   for (const auto& packet : delivered_packets) {
404*d9f75844SAndroid Build Coastguard Worker     if (current_packet < 12) {
405*d9f75844SAndroid Build Coastguard Worker       EXPECT_NE(packet.receive_time_us, PacketDeliveryInfo::kNotReceived);
406*d9f75844SAndroid Build Coastguard Worker       current_packet++;
407*d9f75844SAndroid Build Coastguard Worker     } else {
408*d9f75844SAndroid Build Coastguard Worker       EXPECT_EQ(packet.receive_time_us, PacketDeliveryInfo::kNotReceived);
409*d9f75844SAndroid Build Coastguard Worker       current_packet++;
410*d9f75844SAndroid Build Coastguard Worker     }
411*d9f75844SAndroid Build Coastguard Worker   }
412*d9f75844SAndroid Build Coastguard Worker }
413*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,PauseTransmissionUntil)414*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, PauseTransmissionUntil) {
415*d9f75844SAndroid Build Coastguard Worker   // 3 packets of 125 bytes that gets enqueued on a network with 1 kbps capacity
416*d9f75844SAndroid Build Coastguard Worker   // should be ready to exit the network after 1, 2 and 3 seconds respectively.
417*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
418*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
419*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1)));
420*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
421*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/2)));
422*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(
423*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/3)));
424*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(1).us());
425*d9f75844SAndroid Build Coastguard Worker 
426*d9f75844SAndroid Build Coastguard Worker   // The network gets paused for 5 seconds, which means that the first packet
427*d9f75844SAndroid Build Coastguard Worker   // can exit after 5 seconds instead of 1 second.
428*d9f75844SAndroid Build Coastguard Worker   network.PauseTransmissionUntil(TimeDelta::Seconds(5).us());
429*d9f75844SAndroid Build Coastguard Worker 
430*d9f75844SAndroid Build Coastguard Worker   // No packets after 1 second.
431*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
432*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
433*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(1).us());
434*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 0ul);
435*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(5).us());
436*d9f75844SAndroid Build Coastguard Worker 
437*d9f75844SAndroid Build Coastguard Worker   // The first packet exits after 5 seconds.
438*d9f75844SAndroid Build Coastguard Worker   delivered_packets = network.DequeueDeliverablePackets(
439*d9f75844SAndroid Build Coastguard Worker       /*receive_time_us=*/TimeDelta::Seconds(5).us());
440*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 1ul);
441*d9f75844SAndroid Build Coastguard Worker 
442*d9f75844SAndroid Build Coastguard Worker   // After the first packet is exited, the next delivery time reflects the
443*d9f75844SAndroid Build Coastguard Worker   // delivery time of the next packet which accounts for the network pause.
444*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(network.NextDeliveryTimeUs(), TimeDelta::Seconds(6).us());
445*d9f75844SAndroid Build Coastguard Worker 
446*d9f75844SAndroid Build Coastguard Worker   // And 2 seconds after the exit of the first enqueued packet, the following 2
447*d9f75844SAndroid Build Coastguard Worker   // packets are also delivered.
448*d9f75844SAndroid Build Coastguard Worker   delivered_packets = network.DequeueDeliverablePackets(
449*d9f75844SAndroid Build Coastguard Worker       /*receive_time_us=*/TimeDelta::Seconds(7).us());
450*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets.size(), 2ul);
451*d9f75844SAndroid Build Coastguard Worker }
452*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,CongestedNetworkRespectsLinkCapacity)453*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, CongestedNetworkRespectsLinkCapacity) {
454*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
455*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < 1'000; ++i) {
456*d9f75844SAndroid Build Coastguard Worker     ASSERT_TRUE(network.EnqueuePacket(
457*d9f75844SAndroid Build Coastguard Worker         PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/i)));
458*d9f75844SAndroid Build Coastguard Worker   }
459*d9f75844SAndroid Build Coastguard Worker   PacketDeliveryInfo last_delivered_packet{
460*d9f75844SAndroid Build Coastguard Worker       PacketInFlightInfo(/*size=*/0, /*send_time_us=*/0, /*packet_id=*/0), 0};
461*d9f75844SAndroid Build Coastguard Worker   while (network.NextDeliveryTimeUs().has_value()) {
462*d9f75844SAndroid Build Coastguard Worker     std::vector<PacketDeliveryInfo> delivered_packets =
463*d9f75844SAndroid Build Coastguard Worker         network.DequeueDeliverablePackets(
464*d9f75844SAndroid Build Coastguard Worker             /*receive_time_us=*/network.NextDeliveryTimeUs().value());
465*d9f75844SAndroid Build Coastguard Worker     if (!delivered_packets.empty()) {
466*d9f75844SAndroid Build Coastguard Worker       last_delivered_packet = delivered_packets.back();
467*d9f75844SAndroid Build Coastguard Worker     }
468*d9f75844SAndroid Build Coastguard Worker   }
469*d9f75844SAndroid Build Coastguard Worker   // 1000 packets of 1000 bits each will take 1000 seconds to exit a 1 kpbs
470*d9f75844SAndroid Build Coastguard Worker   // network.
471*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(last_delivered_packet.receive_time_us,
472*d9f75844SAndroid Build Coastguard Worker             TimeDelta::Seconds(1000).us());
473*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(last_delivered_packet.packet_id, 999ul);
474*d9f75844SAndroid Build Coastguard Worker }
475*d9f75844SAndroid Build Coastguard Worker 
TEST(SimulatedNetworkTest,EnqueuePacketWithSubSecondNonMonotonicBehaviour)476*d9f75844SAndroid Build Coastguard Worker TEST(SimulatedNetworkTest, EnqueuePacketWithSubSecondNonMonotonicBehaviour) {
477*d9f75844SAndroid Build Coastguard Worker   // On multi-core systems, different threads can experience sub-millisecond non
478*d9f75844SAndroid Build Coastguard Worker   // monothonic behaviour when running on different cores. This test checks that
479*d9f75844SAndroid Build Coastguard Worker   // when a non monotonic packet enqueue, the network continues to work and the
480*d9f75844SAndroid Build Coastguard Worker   // out of order packet is sent anyway.
481*d9f75844SAndroid Build Coastguard Worker   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
482*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo(
483*d9f75844SAndroid Build Coastguard Worker       /*size=*/125, /*send_time_us=*/TimeDelta::Seconds(1).us(),
484*d9f75844SAndroid Build Coastguard Worker       /*packet_id=*/0)));
485*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo(
486*d9f75844SAndroid Build Coastguard Worker       /*size=*/125, /*send_time_us=*/TimeDelta::Seconds(1).us() - 1,
487*d9f75844SAndroid Build Coastguard Worker       /*packet_id=*/1)));
488*d9f75844SAndroid Build Coastguard Worker 
489*d9f75844SAndroid Build Coastguard Worker   std::vector<PacketDeliveryInfo> delivered_packets =
490*d9f75844SAndroid Build Coastguard Worker       network.DequeueDeliverablePackets(
491*d9f75844SAndroid Build Coastguard Worker           /*receive_time_us=*/TimeDelta::Seconds(2).us());
492*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(delivered_packets.size(), 1ul);
493*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[0].packet_id, 0ul);
494*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[0].receive_time_us, TimeDelta::Seconds(2).us());
495*d9f75844SAndroid Build Coastguard Worker 
496*d9f75844SAndroid Build Coastguard Worker   delivered_packets = network.DequeueDeliverablePackets(
497*d9f75844SAndroid Build Coastguard Worker       /*receive_time_us=*/TimeDelta::Seconds(3).us());
498*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(delivered_packets.size(), 1ul);
499*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[0].packet_id, 1ul);
500*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(delivered_packets[0].receive_time_us, TimeDelta::Seconds(3).us());
501*d9f75844SAndroid Build Coastguard Worker }
502*d9f75844SAndroid Build Coastguard Worker 
503*d9f75844SAndroid Build Coastguard Worker // TODO(bugs.webrtc.org/14525): Re-enable when the DCHECK will be uncommented
504*d9f75844SAndroid Build Coastguard Worker // and the non-monotonic events on real time clock tests is solved/understood.
505*d9f75844SAndroid Build Coastguard Worker // TEST(SimulatedNetworkDeathTest, EnqueuePacketExpectMonotonicSendTime) {
506*d9f75844SAndroid Build Coastguard Worker //   SimulatedNetwork network = SimulatedNetwork({.link_capacity_kbps = 1});
507*d9f75844SAndroid Build Coastguard Worker //   ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo(
508*d9f75844SAndroid Build Coastguard Worker //       /*size=*/125, /*send_time_us=*/2'000'000, /*packet_id=*/0)));
509*d9f75844SAndroid Build Coastguard Worker //   EXPECT_DEATH_IF_SUPPORTED(network.EnqueuePacket(PacketInFlightInfo(
510*d9f75844SAndroid Build Coastguard Worker //       /*size=*/125, /*send_time_us=*/900'000, /*packet_id=*/1)), "");
511*d9f75844SAndroid Build Coastguard Worker // }
512*d9f75844SAndroid Build Coastguard Worker }  // namespace
513*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
514