gfe-relnote: Default-initialize QUIC BBRv2 loss event threshold for exiting STARTUP from a flag. Protected by --gfe2_reloadable_flag_quic_default_to_bbr_v2.

PiperOrigin-RevId: 264298542
Change-Id: I304ab19e4820dec51d3f8ef53762a393f6b175fd
diff --git a/quic/qbone/qbone_packet_exchanger_test.cc b/quic/qbone/qbone_packet_exchanger_test.cc
new file mode 100644
index 0000000..4e63b99
--- /dev/null
+++ b/quic/qbone/qbone_packet_exchanger_test.cc
@@ -0,0 +1,253 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/qbone/mock_qbone_client.h"
+
+namespace quic {
+namespace {
+
+using ::testing::StrEq;
+using ::testing::StrictMock;
+
+const size_t kMaxPendingPackets = 2;
+
+class MockVisitor : public QbonePacketExchanger::Visitor {
+ public:
+  MOCK_METHOD1(OnReadError, void(const string&));
+  MOCK_METHOD1(OnWriteError, void(const string&));
+};
+
+class FakeQbonePacketExchanger : public QbonePacketExchanger {
+ public:
+  using QbonePacketExchanger::QbonePacketExchanger;
+
+  // Adds a packet to the end of list of packets to be returned by ReadPacket.
+  // When the list is empty, ReadPacket returns nullptr to signify error as
+  // defined by QbonePacketExchanger. If SetReadError is not called or called
+  // with empty error string, ReadPacket sets blocked to true.
+  void AddPacketToBeRead(std::unique_ptr<QuicData> packet) {
+    packets_to_be_read_.push_back(std::move(packet));
+  }
+
+  // Sets the error to be returned by ReadPacket when the list of packets is
+  // empty. If error is empty string, blocked is set by ReadPacket.
+  void SetReadError(const string& error) { read_error_ = error; }
+
+  // Force WritePacket to fail with the given status. WritePacket returns true
+  // when blocked == true and error is empty.
+  void ForceWriteFailure(bool blocked, const string& error) {
+    write_blocked_ = blocked;
+    write_error_ = error;
+  }
+
+  // Packets that have been successfully written by WritePacket.
+  const std::vector<string>& packets_written() const {
+    return packets_written_;
+  }
+
+ private:
+  // Implements QbonePacketExchanger::ReadPacket.
+  std::unique_ptr<QuicData> ReadPacket(bool* blocked, string* error) override {
+    *blocked = false;
+
+    if (packets_to_be_read_.empty()) {
+      *blocked = read_error_.empty();
+      *error = read_error_;
+      return nullptr;
+    }
+
+    std::unique_ptr<QuicData> packet = std::move(packets_to_be_read_.front());
+    packets_to_be_read_.pop_front();
+    return packet;
+  }
+
+  // Implements QbonePacketExchanger::WritePacket.
+  bool WritePacket(const char* packet,
+                   size_t size,
+                   bool* blocked,
+                   string* error) override {
+    *blocked = false;
+
+    if (write_blocked_ || !write_error_.empty()) {
+      *blocked = write_blocked_;
+      *error = write_error_;
+      return false;
+    }
+
+    packets_written_.push_back(string(packet, size));
+    return true;
+  }
+
+  string read_error_;
+  std::list<std::unique_ptr<QuicData>> packets_to_be_read_;
+
+  string write_error_;
+  bool write_blocked_ = false;
+  std::vector<string> packets_written_;
+};
+
+TEST(QbonePacketExchangerTest,
+     ReadAndDeliverPacketDeliversPacketToQboneClient) {
+  StrictMock<MockVisitor> visitor;
+  FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
+  StrictMock<MockQboneClient> client;
+
+  string packet = "data";
+  exchanger.AddPacketToBeRead(
+      QuicMakeUnique<QuicData>(packet.data(), packet.length()));
+  EXPECT_CALL(client, ProcessPacketFromNetwork(StrEq("data")));
+
+  EXPECT_TRUE(exchanger.ReadAndDeliverPacket(&client));
+}
+
+TEST(QbonePacketExchangerTest,
+     ReadAndDeliverPacketNotifiesVisitorOnReadFailure) {
+  MockVisitor visitor;
+  FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
+  MockQboneClient client;
+
+  // Force read error.
+  string io_error = "I/O error";
+  exchanger.SetReadError(io_error);
+  EXPECT_CALL(visitor, OnReadError(StrEq(io_error))).Times(1);
+
+  EXPECT_FALSE(exchanger.ReadAndDeliverPacket(&client));
+}
+
+TEST(QbonePacketExchangerTest,
+     ReadAndDeliverPacketDoesNotNotifyVisitorOnBlockedIO) {
+  MockVisitor visitor;
+  FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
+  MockQboneClient client;
+
+  // No more packets to read.
+  EXPECT_FALSE(exchanger.ReadAndDeliverPacket(&client));
+}
+
+TEST(QbonePacketExchangerTest,
+     WritePacketToNetworkWritesDirectlyToNetworkWhenNotBlocked) {
+  MockVisitor visitor;
+  FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
+  MockQboneClient client;
+
+  string packet = "data";
+  exchanger.WritePacketToNetwork(packet.data(), packet.length());
+
+  ASSERT_EQ(exchanger.packets_written().size(), 1);
+  EXPECT_THAT(exchanger.packets_written()[0], StrEq(packet));
+}
+
+TEST(QbonePacketExchangerTest,
+     WritePacketToNetworkQueuesPacketsAndProcessThemLater) {
+  MockVisitor visitor;
+  FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
+  MockQboneClient client;
+
+  // Force write to be blocked so that packets are queued.
+  exchanger.ForceWriteFailure(true, "");
+  std::vector<string> packets = {"packet0", "packet1"};
+  for (int i = 0; i < packets.size(); i++) {
+    exchanger.WritePacketToNetwork(packets[i].data(), packets[i].length());
+  }
+
+  // Nothing should have been written because of blockage.
+  ASSERT_TRUE(exchanger.packets_written().empty());
+
+  // Remove blockage and start proccessing queued packets.
+  exchanger.ForceWriteFailure(false, "");
+  exchanger.SetWritable();
+
+  // Queued packets are processed.
+  ASSERT_EQ(exchanger.packets_written().size(), 2);
+  for (int i = 0; i < packets.size(); i++) {
+    EXPECT_THAT(exchanger.packets_written()[i], StrEq(packets[i]));
+  }
+}
+
+TEST(QbonePacketExchangerTest,
+     SetWritableContinuesProcessingPacketIfPreviousCallBlocked) {
+  MockVisitor visitor;
+  FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
+  MockQboneClient client;
+
+  // Force write to be blocked so that packets are queued.
+  exchanger.ForceWriteFailure(true, "");
+  std::vector<string> packets = {"packet0", "packet1"};
+  for (int i = 0; i < packets.size(); i++) {
+    exchanger.WritePacketToNetwork(packets[i].data(), packets[i].length());
+  }
+
+  // Nothing should have been written because of blockage.
+  ASSERT_TRUE(exchanger.packets_written().empty());
+
+  // Start processing packets, but since writes are still blocked, nothing
+  // should have been written.
+  exchanger.SetWritable();
+  ASSERT_TRUE(exchanger.packets_written().empty());
+
+  // Remove blockage and start processing packets again.
+  exchanger.ForceWriteFailure(false, "");
+  exchanger.SetWritable();
+
+  ASSERT_EQ(exchanger.packets_written().size(), 2);
+  for (int i = 0; i < packets.size(); i++) {
+    EXPECT_THAT(exchanger.packets_written()[i], StrEq(packets[i]));
+  }
+}
+
+TEST(QbonePacketExchangerTest, WritePacketToNetworkDropsPacketIfQueueIfFull) {
+  std::vector<string> packets = {"packet0", "packet1", "packet2"};
+  size_t queue_size = packets.size() - 1;
+  MockVisitor visitor;
+  // exchanger has smaller queue than number of packets.
+  FakeQbonePacketExchanger exchanger(&visitor, queue_size);
+  MockQboneClient client;
+
+  exchanger.ForceWriteFailure(true, "");
+  for (int i = 0; i < packets.size(); i++) {
+    exchanger.WritePacketToNetwork(packets[i].data(), packets[i].length());
+  }
+
+  // Blocked writes cause packets to be queued or dropped.
+  ASSERT_TRUE(exchanger.packets_written().empty());
+
+  exchanger.ForceWriteFailure(false, "");
+  exchanger.SetWritable();
+
+  ASSERT_EQ(exchanger.packets_written().size(), queue_size);
+  for (int i = 0; i < queue_size; i++) {
+    EXPECT_THAT(exchanger.packets_written()[i], StrEq(packets[i]));
+  }
+}
+
+TEST(QbonePacketExchangerTest, WriteErrorsGetNotified) {
+  MockVisitor visitor;
+  FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
+  MockQboneClient client;
+  string packet = "data";
+
+  // Write error is delivered to visitor during WritePacketToNetwork.
+  string io_error = "I/O error";
+  exchanger.ForceWriteFailure(false, io_error);
+  EXPECT_CALL(visitor, OnWriteError(StrEq(io_error))).Times(1);
+  exchanger.WritePacketToNetwork(packet.data(), packet.length());
+  ASSERT_TRUE(exchanger.packets_written().empty());
+
+  // Write error is delivered to visitor during SetWritable.
+  exchanger.ForceWriteFailure(true, "");
+  exchanger.WritePacketToNetwork(packet.data(), packet.length());
+
+  string sys_error = "sys error";
+  exchanger.ForceWriteFailure(false, sys_error);
+  EXPECT_CALL(visitor, OnWriteError(StrEq(sys_error))).Times(1);
+  exchanger.SetWritable();
+  ASSERT_TRUE(exchanger.packets_written().empty());
+}
+
+}  // namespace
+}  // namespace quic