gfe-relnote: (n/a) Change the return value of QuicUdpSocketApi::ReadMultiplePackets from number of good packets to number of total packets read. Code not used yet.

PiperOrigin-RevId: 290802895
Change-Id: I44a83c052ac1fc20b67d8f5708575b2d40cb1cb0
diff --git a/quic/core/quic_udp_socket.h b/quic/core/quic_udp_socket.h
index 86972d1..b60386f 100644
--- a/quic/core/quic_udp_socket.h
+++ b/quic/core/quic_udp_socket.h
@@ -199,6 +199,8 @@
   using ReadPacketResults = std::vector<ReadPacketResult>;
   // Read up to |results->size()| packets from |fd|. The meaning of each element
   // in |*results| has been documented on top of |ReadPacket|.
+  // Return the number of elements populated into |*results|, note it is
+  // possible for some of the populated elements to have ok=false.
   size_t ReadMultiplePackets(QuicUdpSocketFd fd,
                              BitMask64 packet_info_interested,
                              ReadPacketResults* results);
diff --git a/quic/core/quic_udp_socket_posix.cc b/quic/core/quic_udp_socket_posix.cc
index f62dbe8..6a5f2d9 100644
--- a/quic/core/quic_udp_socket_posix.cc
+++ b/quic/core/quic_udp_socket_posix.cc
@@ -471,7 +471,6 @@
     return 0;
   }
 
-  size_t num_good_packets = 0;
   for (int i = 0; i < packets_read; ++i) {
     if (hdrs[i].msg_len == 0) {
       continue;
@@ -493,7 +492,6 @@
       continue;
     }
 
-    ++num_good_packets;
     (*results)[i].ok = true;
     (*results)[i].packet_buffer.buffer_len = hdrs[i].msg_len;
 
@@ -511,15 +509,16 @@
       }
     }
   }
-  return num_good_packets;
+  return packets_read;
 #else
   size_t num_packets = 0;
   for (ReadPacketResult& result : *results) {
     result.ok = false;
   }
   for (ReadPacketResult& result : *results) {
+    errno = 0;
     ReadPacket(fd, packet_info_interested, &result);
-    if (!result.ok) {
+    if (!result.ok && errno == EAGAIN) {
       break;
     }
     ++num_packets;
diff --git a/quic/core/quic_udp_socket_test.cc b/quic/core/quic_udp_socket_test.cc
index 697e5e9..eaa9f4c 100644
--- a/quic/core/quic_udp_socket_test.cc
+++ b/quic/core/quic_udp_socket_test.cc
@@ -9,6 +9,13 @@
 
 namespace quic {
 namespace test {
+namespace {
+// Used by ReadMultiplePackets tests.
+struct ReadBuffers {
+  char control_buffer[512];
+  char packet_buffer[1536];
+};
+}  // namespace
 
 class QuicUdpSocketTest : public QuicTest {
  protected:
@@ -95,6 +102,17 @@
     return memcmp(client_packet_buffer_, server_packet_buffer_, packet_size);
   }
 
+  bool VerifyBufferIsFilledWith(const char* buffer,
+                                size_t buffer_length,
+                                char c) {
+    for (size_t i = 0; i < buffer_length; ++i) {
+      if (buffer[i] != c) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   QuicUdpSocketApi api_;
   QuicUdpSocketFd fd_client_;
   QuicUdpSocketFd fd_server_;
@@ -250,5 +268,122 @@
   EXPECT_EQ(13, read_result.packet_info.ttl());
 }
 
+TEST_F(QuicUdpSocketTest, ReadMultiplePackets) {
+  const QuicUdpPacketInfoBit self_ip_bit =
+      (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP
+                                   : QuicUdpPacketInfoBit::V6_SELF_IP;
+  const size_t kPacketSize = kDefaultMaxPacketSize;
+  const size_t kNumPackets = 90;
+  for (size_t i = 0; i < kNumPackets; ++i) {
+    memset(client_packet_buffer_, ' ' + i, kPacketSize);
+    ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+              SendPacketFromClient(kPacketSize));
+  }
+
+  const size_t kNumPacketsPerRead = 16;
+  size_t total_packets_read = 0;
+  while (total_packets_read < kNumPackets) {
+    std::unique_ptr<ReadBuffers[]> read_buffers =
+        std::make_unique<ReadBuffers[]>(kNumPacketsPerRead);
+    QuicUdpSocketApi::ReadPacketResults results(kNumPacketsPerRead);
+    for (size_t i = 0; i < kNumPacketsPerRead; ++i) {
+      results[i].packet_buffer.buffer = read_buffers[i].packet_buffer;
+      results[i].packet_buffer.buffer_len =
+          sizeof(read_buffers[i].packet_buffer);
+
+      results[i].control_buffer.buffer = read_buffers[i].control_buffer;
+      results[i].control_buffer.buffer_len =
+          sizeof(read_buffers[i].control_buffer);
+    }
+    size_t packets_read =
+        api_.ReadMultiplePackets(fd_server_, BitMask64(self_ip_bit), &results);
+    if (packets_read == 0) {
+      ASSERT_TRUE(
+          api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5)));
+      packets_read = api_.ReadMultiplePackets(fd_server_,
+                                              BitMask64(self_ip_bit), &results);
+      ASSERT_GT(packets_read, 0u);
+    }
+
+    for (size_t i = 0; i < packets_read; ++i) {
+      const auto& result = results[i];
+      ASSERT_TRUE(result.ok);
+      ASSERT_EQ(kPacketSize, result.packet_buffer.buffer_len);
+      ASSERT_TRUE(VerifyBufferIsFilledWith(result.packet_buffer.buffer,
+                                           result.packet_buffer.buffer_len,
+                                           ' ' + total_packets_read));
+      ASSERT_TRUE(result.packet_info.HasValue(self_ip_bit));
+      EXPECT_EQ(Loopback(), (address_family_ == AF_INET)
+                                ? result.packet_info.self_v4_ip()
+                                : result.packet_info.self_v6_ip());
+      total_packets_read++;
+    }
+  }
+}
+
+TEST_F(QuicUdpSocketTest, ReadMultiplePacketsSomeTruncated) {
+  const QuicUdpPacketInfoBit self_ip_bit =
+      (address_family_ == AF_INET) ? QuicUdpPacketInfoBit::V4_SELF_IP
+                                   : QuicUdpPacketInfoBit::V6_SELF_IP;
+  const size_t kPacketSize = kDefaultMaxPacketSize;
+  const size_t kNumPackets = 90;
+  for (size_t i = 0; i < kNumPackets; ++i) {
+    memset(client_packet_buffer_, ' ' + i, kPacketSize);
+    ASSERT_EQ(WriteResult(WRITE_STATUS_OK, kPacketSize),
+              SendPacketFromClient(kPacketSize));
+  }
+
+  const size_t kNumPacketsPerRead = 16;
+  size_t total_packets_read = 0;  // Including truncated packets.
+  while (total_packets_read < kNumPackets) {
+    std::unique_ptr<ReadBuffers[]> read_buffers =
+        std::make_unique<ReadBuffers[]>(kNumPacketsPerRead);
+    QuicUdpSocketApi::ReadPacketResults results(kNumPacketsPerRead);
+    // Use small packet buffer for all even-numbered packets and expect them to
+    // be truncated.
+    auto is_truncated = [total_packets_read](size_t i) {
+      return ((total_packets_read + i) % 2) == 1;
+    };
+
+    for (size_t i = 0; i < kNumPacketsPerRead; ++i) {
+      results[i].packet_buffer.buffer = read_buffers[i].packet_buffer;
+      results[i].packet_buffer.buffer_len =
+          is_truncated(i) ? kPacketSize - 1
+                          : sizeof(read_buffers[i].packet_buffer);
+
+      results[i].control_buffer.buffer = read_buffers[i].control_buffer;
+      results[i].control_buffer.buffer_len =
+          sizeof(read_buffers[i].control_buffer);
+    }
+    size_t packets_read =
+        api_.ReadMultiplePackets(fd_server_, BitMask64(self_ip_bit), &results);
+    if (packets_read == 0) {
+      ASSERT_TRUE(
+          api_.WaitUntilReadable(fd_server_, QuicTime::Delta::FromSeconds(5)));
+      packets_read = api_.ReadMultiplePackets(fd_server_,
+                                              BitMask64(self_ip_bit), &results);
+      ASSERT_GT(packets_read, 0u);
+    }
+
+    for (size_t i = 0; i < packets_read; ++i) {
+      const auto& result = results[i];
+      if (is_truncated(i)) {
+        ASSERT_FALSE(result.ok);
+      } else {
+        ASSERT_TRUE(result.ok);
+        ASSERT_EQ(kPacketSize, result.packet_buffer.buffer_len);
+        ASSERT_TRUE(VerifyBufferIsFilledWith(result.packet_buffer.buffer,
+                                             result.packet_buffer.buffer_len,
+                                             ' ' + total_packets_read));
+        ASSERT_TRUE(result.packet_info.HasValue(self_ip_bit));
+        EXPECT_EQ(Loopback(), (address_family_ == AF_INET)
+                                  ? result.packet_info.self_v4_ip()
+                                  : result.packet_info.self_v6_ip());
+      }
+      total_packets_read++;
+    }
+  }
+}
+
 }  // namespace test
 }  // namespace quic