Add support for lost packets to FeedbackGenerator

Feedback can include lost packets. Ensure FeedbackGenerator support lost packets to be able to use this class properly when testing with loss.

Bug: none
Change-Id: Ibd740dfae358c0543fbee62cd40ef13a7ac1123f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/247372
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35740}
diff --git a/test/network/BUILD.gn b/test/network/BUILD.gn
index fb0bc55..4113978 100644
--- a/test/network/BUILD.gn
+++ b/test/network/BUILD.gn
@@ -157,6 +157,7 @@
     ]
     deps = [
       ":emulated_network",
+      "../../api/transport:network_control",
       "../../api/transport:test_feedback_generator_interface",
       "../../call:simulated_network",
       "../../rtc_base:checks",
diff --git a/test/network/feedback_generator.cc b/test/network/feedback_generator.cc
index f0903dd..68fbcc0 100644
--- a/test/network/feedback_generator.cc
+++ b/test/network/feedback_generator.cc
@@ -10,6 +10,7 @@
 #include "test/network/feedback_generator.h"
 
 #include "absl/memory/memory.h"
+#include "api/transport/network_types.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
@@ -39,6 +40,7 @@
   sent.send_time = Now();
   sent.size = DataSize::Bytes(size);
   sent.sequence_number = sequence_number_++;
+  sent_packets_.push(sent);
   route_.SendRequest(size, sent);
 }
 
@@ -69,18 +71,41 @@
   PacketResult result;
   result.sent_packet = packet;
   result.receive_time = arrival_time;
-  builder_.packet_feedbacks.push_back(result);
-  Timestamp first_recv = builder_.packet_feedbacks.front().receive_time;
+  received_packets_.push_back(result);
+  Timestamp first_recv = received_packets_.front().receive_time;
   if (Now() - first_recv > conf_.feedback_interval) {
-    route_.SendResponse(conf_.feedback_packet_size.bytes<size_t>(), builder_);
-    builder_ = {};
+    route_.SendResponse(conf_.feedback_packet_size.bytes<size_t>(),
+                        std::move(received_packets_));
+    received_packets_ = {};
   }
 }
 
-void FeedbackGeneratorImpl::OnResponse(TransportPacketsFeedback packet,
+void FeedbackGeneratorImpl::OnResponse(std::vector<PacketResult> packet_results,
                                        Timestamp arrival_time) {
-  packet.feedback_time = arrival_time;
-  feedback_.push_back(packet);
+  TransportPacketsFeedback feedback;
+  feedback.feedback_time = arrival_time;
+  std::vector<PacketResult>::const_iterator received_packet_iterator =
+      packet_results.begin();
+  while (received_packet_iterator != packet_results.end()) {
+    RTC_DCHECK(!sent_packets_.empty() &&
+               sent_packets_.front().sequence_number <=
+                   received_packet_iterator->sent_packet.sequence_number)
+        << "reordering not implemented";
+    if (sent_packets_.front().sequence_number <
+        received_packet_iterator->sent_packet.sequence_number) {
+      // Packet lost.
+      PacketResult lost;
+      lost.sent_packet = sent_packets_.front();
+      feedback.packet_feedbacks.push_back(lost);
+    }
+    if (sent_packets_.front().sequence_number ==
+        received_packet_iterator->sent_packet.sequence_number) {
+      feedback.packet_feedbacks.push_back(*received_packet_iterator);
+      ++received_packet_iterator;
+    }
+    sent_packets_.pop();
+  }
+  feedback_.push_back(feedback);
 }
 
 }  // namespace webrtc
diff --git a/test/network/feedback_generator.h b/test/network/feedback_generator.h
index 98ac01c..ecd4597 100644
--- a/test/network/feedback_generator.h
+++ b/test/network/feedback_generator.h
@@ -10,10 +10,12 @@
 #ifndef TEST_NETWORK_FEEDBACK_GENERATOR_H_
 #define TEST_NETWORK_FEEDBACK_GENERATOR_H_
 
-#include <map>
+#include <cstdint>
+#include <queue>
 #include <utility>
 #include <vector>
 
+#include "api/transport/network_types.h"
 #include "api/transport/test/feedback_generator_interface.h"
 #include "call/simulated_network.h"
 #include "test/network/network_emulation.h"
@@ -24,7 +26,7 @@
 
 class FeedbackGeneratorImpl
     : public FeedbackGenerator,
-      public TwoWayFakeTrafficRoute<SentPacket, TransportPacketsFeedback>::
+      public TwoWayFakeTrafficRoute<SentPacket, std::vector<PacketResult>>::
           TrafficHandlerInterface {
  public:
   explicit FeedbackGeneratorImpl(Config config);
@@ -39,7 +41,7 @@
   void SetSendLinkCapacity(DataRate capacity) override;
 
   void OnRequest(SentPacket packet, Timestamp arrival_time) override;
-  void OnResponse(TransportPacketsFeedback packet,
+  void OnResponse(std::vector<PacketResult> packet_results,
                   Timestamp arrival_time) override;
 
  private:
@@ -47,9 +49,10 @@
   ::webrtc::test::NetworkEmulationManagerImpl net_;
   SimulatedNetwork* const send_link_;
   SimulatedNetwork* const ret_link_;
-  TwoWayFakeTrafficRoute<SentPacket, TransportPacketsFeedback> route_;
+  TwoWayFakeTrafficRoute<SentPacket, std::vector<PacketResult>> route_;
 
-  TransportPacketsFeedback builder_;
+  std::queue<SentPacket> sent_packets_;
+  std::vector<PacketResult> received_packets_;
   std::vector<TransportPacketsFeedback> feedback_;
   int64_t sequence_number_ = 1;
 };
diff --git a/test/network/feedback_generator_unittest.cc b/test/network/feedback_generator_unittest.cc
index ca04bd3..9a577be 100644
--- a/test/network/feedback_generator_unittest.cc
+++ b/test/network/feedback_generator_unittest.cc
@@ -28,4 +28,20 @@
     }
   }
 }
+
+TEST(FeedbackGeneratorTest, FeedbackIncludesLostPackets) {
+  size_t kPacketSize = 1000;
+  auto gen = CreateFeedbackGenerator(FeedbackGenerator::Config());
+  BuiltInNetworkBehaviorConfig send_config_with_loss;
+  send_config_with_loss.loss_percent = 50;
+  gen->SetSendConfig(send_config_with_loss);
+  for (int i = 0; i < 20; ++i) {
+    gen->SendPacket(kPacketSize);
+    gen->Sleep(TimeDelta::Millis(5));
+  }
+  auto feedback_list = gen->PopFeedback();
+  ASSERT_GT(feedback_list.size(), 0u);
+  EXPECT_NEAR(feedback_list[0].LostWithSendInfo().size(),
+              feedback_list[0].ReceivedWithSendInfo().size(), 2);
+}
 }  // namespace webrtc