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_stream_test.cc b/quic/qbone/qbone_stream_test.cc
new file mode 100644
index 0000000..1920aa5
--- /dev/null
+++ b/quic/qbone/qbone_stream_test.cc
@@ -0,0 +1,249 @@
+// 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_stream.h"
+
+#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.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/platform/api/quic_test_loopback.h"
+#include "net/third_party/quiche/src/quic/qbone/qbone_constants.h"
+#include "net/third_party/quiche/src/quic/qbone/qbone_session_base.h"
+#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
+
+namespace quic {
+
+namespace {
+
+using ::testing::_;
+using ::testing::StrictMock;
+
+// MockQuicSession that does not create streams and writes data from
+// QuicStream to a string.
+class MockQuicSession : public QboneSessionBase {
+ public:
+  MockQuicSession(QuicConnection* connection, const QuicConfig& config)
+      : QboneSessionBase(connection,
+                         nullptr /*visitor*/,
+                         config,
+                         CurrentSupportedVersions(),
+                         nullptr /*writer*/) {}
+
+  ~MockQuicSession() override {}
+
+  // Writes outgoing data from QuicStream to a string.
+  QuicConsumedData WritevData(QuicStream* stream,
+                              QuicStreamId id,
+                              size_t write_length,
+                              QuicStreamOffset offset,
+                              StreamSendingState state) override {
+    if (!writable_) {
+      return QuicConsumedData(0, false);
+    }
+
+    return QuicConsumedData(write_length, state != StreamSendingState::NO_FIN);
+  }
+
+  QboneReadOnlyStream* CreateIncomingStream(QuicStreamId id) override {
+    return nullptr;
+  }
+
+  const QuicCryptoStream* GetCryptoStream() const override { return nullptr; }
+  QuicCryptoStream* GetMutableCryptoStream() override { return nullptr; }
+
+  // Called by QuicStream when they want to close stream.
+  MOCK_METHOD3(SendRstStream,
+               void(QuicStreamId, QuicRstStreamErrorCode, QuicStreamOffset));
+
+  // Sets whether data is written to buffer, or else if this is write blocked.
+  void set_writable(bool writable) { writable_ = writable; }
+
+  // Tracks whether the stream is write blocked and its priority.
+  void RegisterReliableStream(QuicStreamId stream_id) {
+    // The priority effectively does not matter. Put all streams on the same
+    // priority.
+    write_blocked_streams()->RegisterStream(
+        stream_id,
+        /*is_static_stream=*/false,
+        /* precedence= */ spdy::SpdyStreamPrecedence(3));
+  }
+
+  // The session take ownership of the stream.
+  void ActivateReliableStream(std::unique_ptr<QuicStream> stream) {
+    ActivateStream(std::move(stream));
+  }
+
+  std::unique_ptr<QuicCryptoStream> CreateCryptoStream() override {
+    return nullptr;
+  }
+
+  MOCK_METHOD1(ProcessPacketFromPeer, void(QuicStringPiece));
+  MOCK_METHOD1(ProcessPacketFromNetwork, void(QuicStringPiece));
+
+ private:
+  // Whether data is written to write_buffer_.
+  bool writable_ = true;
+};
+
+// Packet writer that does nothing. This is required for QuicConnection but
+// isn't used for writing data.
+class DummyPacketWriter : public QuicPacketWriter {
+ public:
+  DummyPacketWriter() {}
+
+  // QuicPacketWriter overrides.
+  WriteResult WritePacket(const char* buffer,
+                          size_t buf_len,
+                          const QuicIpAddress& self_address,
+                          const QuicSocketAddress& peer_address,
+                          PerPacketOptions* options) override {
+    return WriteResult(WRITE_STATUS_ERROR, 0);
+  }
+
+  bool IsWriteBlocked() const override { return false; };
+
+  void SetWritable() override {}
+
+  QuicByteCount GetMaxPacketSize(
+      const QuicSocketAddress& peer_address) const override {
+    return 0;
+  }
+
+  bool SupportsReleaseTime() const override { return false; }
+
+  bool IsBatchMode() const override { return false; }
+
+  char* GetNextWriteLocation(const QuicIpAddress& self_address,
+                             const QuicSocketAddress& peer_address) override {
+    return nullptr;
+  }
+
+  WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
+};
+
+class QboneReadOnlyStreamTest : public ::testing::Test,
+                                public QuicConnectionHelperInterface {
+ public:
+  void CreateReliableQuicStream() {
+    // Arbitrary values for QuicConnection.
+    Perspective perspective = Perspective::IS_SERVER;
+    bool owns_writer = true;
+
+    alarm_factory_ = QuicMakeUnique<test::MockAlarmFactory>();
+
+    connection_.reset(new QuicConnection(
+        test::TestConnectionId(0), QuicSocketAddress(TestLoopback(), 0),
+        this /*QuicConnectionHelperInterface*/, alarm_factory_.get(),
+        new DummyPacketWriter(), owns_writer, perspective,
+        ParsedVersionOfIndex(CurrentSupportedVersions(), 0)));
+    clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+    session_ = QuicMakeUnique<StrictMock<MockQuicSession>>(connection_.get(),
+                                                           QuicConfig());
+    stream_ = new QboneReadOnlyStream(kStreamId, session_.get());
+    session_->ActivateReliableStream(
+        std::unique_ptr<QboneReadOnlyStream>(stream_));
+  }
+
+  ~QboneReadOnlyStreamTest() override {}
+
+  const QuicClock* GetClock() const override { return &clock_; }
+
+  QuicRandom* GetRandomGenerator() override {
+    return QuicRandom::GetInstance();
+  }
+
+  QuicBufferAllocator* GetStreamSendBufferAllocator() override {
+    return &buffer_allocator_;
+  }
+
+ protected:
+  // The QuicSession will take the ownership.
+  QboneReadOnlyStream* stream_;
+  std::unique_ptr<StrictMock<MockQuicSession>> session_;
+  std::unique_ptr<QuicAlarmFactory> alarm_factory_;
+  std::unique_ptr<QuicConnection> connection_;
+  // Used to implement the QuicConnectionHelperInterface.
+  SimpleBufferAllocator buffer_allocator_;
+  MockClock clock_;
+  const QuicStreamId kStreamId = QuicUtils::GetFirstUnidirectionalStreamId(
+      CurrentSupportedVersions()[0].transport_version,
+      Perspective::IS_CLIENT);
+};
+
+// Read an entire string.
+TEST_F(QboneReadOnlyStreamTest, ReadDataWhole) {
+  string packet = "Stuff";
+  CreateReliableQuicStream();
+  QuicStreamFrame frame(kStreamId, true, 0, packet);
+  EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
+  stream_->OnStreamFrame(frame);
+}
+
+// Test buffering.
+TEST_F(QboneReadOnlyStreamTest, ReadBuffered) {
+  CreateReliableQuicStream();
+  string packet = "Stuf";
+  {
+    QuicStreamFrame frame(kStreamId, false, 0, packet);
+    stream_->OnStreamFrame(frame);
+  }
+  // We didn't write 5 bytes yet...
+
+  packet = "f";
+  EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
+  {
+    QuicStreamFrame frame(kStreamId, true, 4, packet);
+    stream_->OnStreamFrame(frame);
+  }
+}
+
+TEST_F(QboneReadOnlyStreamTest, ReadOutOfOrder) {
+  CreateReliableQuicStream();
+  string packet = "f";
+  {
+    QuicStreamFrame frame(kStreamId, true, 4, packet);
+    stream_->OnStreamFrame(frame);
+  }
+
+  packet = "S";
+  {
+    QuicStreamFrame frame(kStreamId, false, 0, packet);
+    stream_->OnStreamFrame(frame);
+  }
+
+  packet = "tuf";
+  EXPECT_CALL(*session_, ProcessPacketFromPeer("Stuff"));
+  {
+    QuicStreamFrame frame(kStreamId, false, 1, packet);
+    stream_->OnStreamFrame(frame);
+  }
+}
+
+// Test buffering too many bytes.
+TEST_F(QboneReadOnlyStreamTest, ReadBufferedTooLarge) {
+  CreateReliableQuicStream();
+  string packet = "0123456789";
+  int iterations = (QboneConstants::kMaxQbonePacketBytes / packet.size()) + 2;
+  EXPECT_CALL(*session_,
+              SendRstStream(kStreamId, QUIC_BAD_APPLICATION_PAYLOAD, _));
+  for (int i = 0; i < iterations; ++i) {
+    QuicStreamFrame frame(kStreamId, i == (iterations - 1), i * packet.size(),
+                          packet);
+    if (!stream_->reading_stopped()) {
+      stream_->OnStreamFrame(frame);
+    }
+  }
+  // We should have nothing written to the network and the stream
+  // should have stopped reading.
+  EXPECT_TRUE(stream_->reading_stopped());
+}
+
+}  // namespace
+
+}  // namespace quic