// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/quic/quic_socket_data_provider.h"

#include <memory>

#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "net/base/io_buffer.h"
#include "net/base/request_priority.h"
#include "net/quic/mock_quic_context.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_test_packet_maker.h"
#include "net/socket/datagram_client_socket.h"
#include "net/socket/diff_serv_code_point.h"
#include "net/socket/socket_test_util.h"
#include "net/test/test_with_task_environment.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gtest/include/gtest/gtest-spi.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net::test {

class QuicSocketDataProviderTest : public TestWithTaskEnvironment {
 public:
  QuicSocketDataProviderTest()
      : packet_maker_(std::make_unique<QuicTestPacketMaker>(
            version_,
            quic::QuicUtils::CreateRandomConnectionId(
                context_.random_generator()),
            context_.clock(),
            "hostname",
            quic::Perspective::IS_CLIENT,
            /*client_priority_uses_incremental=*/true,
            /*use_priority_header=*/true)) {}

  // Create a simple test packet.
  std::unique_ptr<quic::QuicReceivedPacket> TestPacket(uint64_t packet_number) {
    return packet_maker_->Packet(packet_number)
        .AddMessageFrame(base::NumberToString(packet_number))
        .Build();
  }

  std::unique_ptr<quic::QuicReceivedPacket> TestInitialSettingsPacket(
      uint64_t packet_number) {
    return packet_maker_->MakeInitialSettingsPacket(packet_number);
  }

  // Create a simple request header packet.
  std::unique_ptr<quic::QuicReceivedPacket>
  TestHeadersPacket(uint64_t packet_number, std::string path, bool fin) {
    quiche::HttpHeaderBlock headers;
    headers[":scheme"] = "https";
    headers[":path"] = path;
    spdy::SpdyPriority priority =
        ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
    size_t spdy_headers_frame_len;
    // Headers frame should be sent with stream 0.
    auto rv = packet_maker_->MakeRequestHeadersPacket(
        packet_number, 0, fin, priority, std::move(headers),
        &spdy_headers_frame_len, /*should_include_priority_frame=*/false);
    return rv;
  }

 protected:
  NetLogWithSource net_log_with_source_{
      NetLogWithSource::Make(NetLogSourceType::NONE)};
  quic::ParsedQuicVersion version_ = quic::ParsedQuicVersion::RFCv1();
  MockQuicContext context_;
  std::unique_ptr<QuicTestPacketMaker> packet_maker_;
};

// A linear sequence of sync expectations completes.
TEST_F(QuicSocketDataProviderTest, LinearSequenceSync) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddWrite("p1", TestPacket(1)).Sync();
  socket_data.AddWrite("p2", TestPacket(2)).Sync();
  socket_data.AddWrite("p3", TestPacket(3)).Sync();

  socket_factory.AddSocketDataProvider(&socket_data);
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, base::BindLambdaForTesting([&]() {
        std::unique_ptr<DatagramClientSocket> socket =
            socket_factory.CreateDatagramClientSocket(
                DatagramSocket::BindType::DEFAULT_BIND,
                handles::kInvalidNetworkHandle, nullptr,
                net_log_with_source_.source());
        socket->Connect(IPEndPoint());

        for (uint64_t packet_number = 1; packet_number < 4; packet_number++) {
          std::unique_ptr<quic::QuicReceivedPacket> packet =
              TestPacket(packet_number);
          scoped_refptr<StringIOBuffer> buffer =
              base::MakeRefCounted<StringIOBuffer>(
                  std::string(packet->data(), packet->length()));
          EXPECT_EQ(
              static_cast<int>(packet->length()),
              socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                            TRAFFIC_ANNOTATION_FOR_TESTS));
        }
      }));

  socket_data.RunUntilAllConsumed();
}

// A linear sequence of async expectations completes.
TEST_F(QuicSocketDataProviderTest, LinearSequenceAsync) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddWrite("p1", TestPacket(1));
  socket_data.AddWrite("p2", TestPacket(2));
  socket_data.AddWrite("p3", TestPacket(3));

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  int next_packet = 1;
  base::RepeatingCallback<void(int)> callback =
      base::BindLambdaForTesting([&](int result) {
        EXPECT_GT(result, 0);  // Bytes written or, on the first call, one.
        if (next_packet <= 3) {
          std::unique_ptr<quic::QuicReceivedPacket> packet =
              TestPacket(next_packet++);
          scoped_refptr<StringIOBuffer> buffer =
              base::MakeRefCounted<StringIOBuffer>(
                  std::string(packet->data(), packet->length()));
          EXPECT_EQ(ERR_IO_PENDING,
                    socket->Write(buffer.get(), packet->length(), callback,
                                  TRAFFIC_ANNOTATION_FOR_TESTS));
        }
      });
  callback.Run(1);
  socket_data.RunUntilAllConsumed();
}

// The `TosByte` builder method results in a correct TOS byte in the read.
TEST_F(QuicSocketDataProviderTest, ReadTos) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;
  const uint8_t kTestTos = (DSCP_CS1 << 2) + ECN_CE;

  socket_data.AddRead("p1", TestPacket(1)).Sync().TosByte(kTestTos);

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  scoped_refptr<GrowableIOBuffer> read_buffer =
      base::MakeRefCounted<GrowableIOBuffer>();
  read_buffer->SetCapacity(100);
  EXPECT_EQ(static_cast<int>(TestPacket(1)->length()),
            socket->Read(read_buffer.get(), 100, base::DoNothing()));
  DscpAndEcn dscp_and_ecn = socket->GetLastTos();
  EXPECT_EQ(dscp_and_ecn.dscp, DSCP_CS1);
  EXPECT_EQ(dscp_and_ecn.ecn, ECN_CE);

  socket_data.RunUntilAllConsumed();
}

// AddReadError creates a read returning an error.
TEST_F(QuicSocketDataProviderTest, AddReadError) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddReadError("p1", ERR_CONNECTION_ABORTED).Sync();

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  scoped_refptr<GrowableIOBuffer> read_buffer =
      base::MakeRefCounted<GrowableIOBuffer>();
  read_buffer->SetCapacity(100);
  EXPECT_EQ(ERR_CONNECTION_ABORTED,
            socket->Read(read_buffer.get(), 100, base::DoNothing()));

  socket_data.RunUntilAllConsumed();
}

// AddRead with a QuicReceivedPacket correctly sets the ECN.
TEST_F(QuicSocketDataProviderTest, AddReadQuicReceivedPacketGetsEcn) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  packet_maker_->set_ecn_codepoint(quic::QuicEcnCodepoint::ECN_ECT0);
  socket_data.AddRead("p1", TestPacket(1)).Sync();

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  scoped_refptr<GrowableIOBuffer> read_buffer =
      base::MakeRefCounted<GrowableIOBuffer>();
  read_buffer->SetCapacity(100);
  EXPECT_EQ(static_cast<int>(TestPacket(1)->length()),
            socket->Read(read_buffer.get(), 100, base::DoNothing()));
  DscpAndEcn dscp_and_ecn = socket->GetLastTos();
  EXPECT_EQ(dscp_and_ecn.ecn, ECN_ECT0);

  socket_data.RunUntilAllConsumed();
  EXPECT_TRUE(socket_data.AllReadDataConsumed());
  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}

// A write of data different from the expectation generates a failure.
TEST_F(QuicSocketDataProviderTest, MismatchedWrite) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddWrite("p1", TestPacket(1)).Sync();

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(999);
  scoped_refptr<StringIOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
      std::string(packet->data(), packet->length()));
  EXPECT_NONFATAL_FAILURE(
      EXPECT_EQ(ERR_UNEXPECTED,
                socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                              TRAFFIC_ANNOTATION_FOR_TESTS)),
      "Expectation 'p1' not met.");
}

// AllDataConsumed is false if there are still pending expectations.
TEST_F(QuicSocketDataProviderTest, NotAllConsumed) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddWrite("p1", TestPacket(1)).Sync();
  socket_data.AddWrite("p2", TestPacket(2)).Sync();

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(1);
  scoped_refptr<StringIOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
      std::string(packet->data(), packet->length()));
  EXPECT_EQ(static_cast<int>(packet->length()),
            socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                          TRAFFIC_ANNOTATION_FOR_TESTS));

  EXPECT_FALSE(socket_data.AllDataConsumed());
}

// When a Write call occurs with no matching expectation, that is treated as an
// error.
TEST_F(QuicSocketDataProviderTest, ReadBlocksWrite) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddRead("p1", TestPacket(1)).Sync();
  socket_data.AddWrite("p2", TestPacket(2)).Sync();

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(1);
  scoped_refptr<StringIOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
      std::string(packet->data(), packet->length()));
  EXPECT_NONFATAL_FAILURE(
      EXPECT_EQ(ERR_UNEXPECTED,
                socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                              TRAFFIC_ANNOTATION_FOR_TESTS)),
      "Write call when none is expected:");
}

// When a Read call occurs with no matching expectation, it waits for a matching
// expectation to become read.
TEST_F(QuicSocketDataProviderTest, WriteDelaysRead) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddWrite("p1", TestPacket(1)).Sync();
  socket_data.AddRead("p2", TestPacket(22222)).Sync();

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  // Begin a read operation which should not complete yet.
  bool read_completed = false;
  base::OnceCallback<void(int)> read_callback =
      base::BindLambdaForTesting([&](int result) {
        EXPECT_EQ(result, static_cast<int>(TestPacket(22222)->length()));
        read_completed = true;
      });
  scoped_refptr<GrowableIOBuffer> read_buffer =
      base::MakeRefCounted<GrowableIOBuffer>();
  read_buffer->SetCapacity(100);
  EXPECT_EQ(ERR_IO_PENDING,
            socket->Read(read_buffer.get(), 100, std::move(read_callback)));

  EXPECT_FALSE(read_completed);

  // Perform the write on which the read depends.
  std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(1);
  scoped_refptr<StringIOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
      std::string(packet->data(), packet->length()));
  EXPECT_EQ(static_cast<int>(packet->length()),
            socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                          TRAFFIC_ANNOTATION_FOR_TESTS));

  socket_data.RunUntilAllConsumed();
  EXPECT_TRUE(read_completed);
}

// When a pause becomes ready, subsequent calls are delayed.
TEST_F(QuicSocketDataProviderTest, PauseDelaysCalls) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddWrite("p1", TestPacket(1)).Sync();
  auto pause = socket_data.AddPause("pause");
  socket_data.AddRead("p2", TestPacket(2)).After("pause");
  socket_data.AddWrite("p3", TestPacket(3)).After("pause");

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  // Perform a write in another task, and wait for the pause.
  bool write_completed = false;
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, base::BindLambdaForTesting([&]() {
        std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(1);
        scoped_refptr<StringIOBuffer> buffer =
            base::MakeRefCounted<StringIOBuffer>(
                std::string(packet->data(), packet->length()));
        EXPECT_EQ(
            static_cast<int>(packet->length()),
            socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                          TRAFFIC_ANNOTATION_FOR_TESTS));
        write_completed = true;
      }));

  EXPECT_FALSE(write_completed);
  socket_data.RunUntilPause(pause);
  EXPECT_TRUE(write_completed);

  // Begin a read operation which should not complete yet.
  bool read_completed = false;
  base::OnceCallback<void(int)> read_callback =
      base::BindLambdaForTesting([&](int result) {
        EXPECT_EQ(result, static_cast<int>(TestPacket(2)->length()));
        read_completed = true;
      });
  scoped_refptr<GrowableIOBuffer> read_buffer =
      base::MakeRefCounted<GrowableIOBuffer>();
  read_buffer->SetCapacity(100);
  EXPECT_EQ(ERR_IO_PENDING,
            socket->Read(read_buffer.get(), 100, std::move(read_callback)));

  // Begin a write operation which should not complete yet.
  write_completed = false;
  base::OnceCallback<void(int)> write_callback =
      base::BindLambdaForTesting([&](int result) {
        EXPECT_EQ(result, static_cast<int>(TestPacket(3)->length()));
        write_completed = true;
      });
  std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(3);
  scoped_refptr<StringIOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
      std::string(packet->data(), packet->length()));
  EXPECT_EQ(ERR_IO_PENDING, socket->Write(buffer.get(), packet->length(),
                                          std::move(write_callback),
                                          TRAFFIC_ANNOTATION_FOR_TESTS));

  EXPECT_FALSE(read_completed);
  EXPECT_FALSE(write_completed);

  socket_data.Resume();
  socket_data.RunUntilAllConsumed();
  RunUntilIdle();

  EXPECT_TRUE(read_completed);
  EXPECT_TRUE(write_completed);
}

// Using `After`, a `Read` and `Write` can be allowed in either order.
TEST_F(QuicSocketDataProviderTest, ParallelReadAndWrite) {
  for (bool read_first : {false, true}) {
    SCOPED_TRACE(::testing::Message() << "read_first: " << read_first);
    QuicSocketDataProvider socket_data(version_);
    MockClientSocketFactory socket_factory;

    socket_data.AddWrite("p1", TestPacket(1)).Sync();
    socket_data.AddRead("p2", TestPacket(2)).Sync().After("p1");
    socket_data.AddWrite("p3", TestPacket(3)).Sync().After("p1");

    socket_factory.AddSocketDataProvider(&socket_data);
    std::unique_ptr<DatagramClientSocket> socket =
        socket_factory.CreateDatagramClientSocket(
            DatagramSocket::BindType::DEFAULT_BIND,
            handles::kInvalidNetworkHandle, nullptr,
            net_log_with_source_.source());
    socket->Connect(IPEndPoint());

    // Write p1 to get things started.
    std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(1);
    scoped_refptr<IOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
        std::string(packet->data(), packet->length()));
    EXPECT_EQ(static_cast<int>(packet->length()),
              socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                            TRAFFIC_ANNOTATION_FOR_TESTS));

    scoped_refptr<GrowableIOBuffer> read_buffer =
        base::MakeRefCounted<GrowableIOBuffer>();
    read_buffer->SetCapacity(100);
    auto do_read = [&]() {
      EXPECT_EQ(static_cast<int>(TestPacket(2)->length()),
                socket->Read(read_buffer.get(), 100, base::DoNothing()));
    };

    std::unique_ptr<quic::QuicReceivedPacket> write_packet = TestPacket(3);
    buffer = base::MakeRefCounted<StringIOBuffer>(
        std::string(write_packet->data(), write_packet->length()));

    auto do_write = [&]() {
      EXPECT_EQ(static_cast<int>(write_packet->length()),
                socket->Write(buffer.get(), write_packet->length(),
                              base::DoNothing(), TRAFFIC_ANNOTATION_FOR_TESTS));
    };

    // Read p2 and write p3 in both orders.
    if (read_first) {
      do_read();
      do_write();
    } else {
      do_write();
      do_read();
    }

    socket_data.RunUntilAllConsumed();
  }
}

// When multiple Read expectations become ready at the same time, fail with a
// CHECK error.
TEST_F(QuicSocketDataProviderTest, MultipleReadsReady) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddWrite("p1", TestPacket(1)).Sync();
  socket_data.AddRead("p2", TestPacket(2)).After("p1");
  socket_data.AddRead("p3", TestPacket(3)).After("p1");

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());

  std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(1);
  scoped_refptr<StringIOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
      std::string(packet->data(), packet->length()));
  EXPECT_EQ(static_cast<int>(packet->length()),
            socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                          TRAFFIC_ANNOTATION_FOR_TESTS));
  EXPECT_CHECK_DEATH(
      socket->Read(buffer.get(), buffer->size(), base::DoNothing()));
}

// Test an HTTP header packet is decoded by the server session.
TEST_F(QuicSocketDataProviderTest, PrintHTTPHeadersPacket) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  const std::string path = "/.well-known/masque/udp/www.example.org/443/";
  socket_data.AddWrite("connect-udp", TestHeadersPacket(2, path, false));

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());
  std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(999);
  scoped_refptr<StringIOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
      std::string(packet->data(), packet->length()));

  EXPECT_NONFATAL_FAILURE(
      EXPECT_EQ(ERR_UNEXPECTED,
                socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                              TRAFFIC_ANNOTATION_FOR_TESTS)),
      // Path should be decoded by the server session and appear in the output.
      base::StringPrintf(":path=%s", path));
}

// Test an HTTP's initial settings packet is decoded by the server session.
TEST_F(QuicSocketDataProviderTest, PrintInitialSettingsPacket) {
  QuicSocketDataProvider socket_data(version_);
  MockClientSocketFactory socket_factory;

  socket_data.AddWrite("InitialSettings", TestInitialSettingsPacket(2));

  socket_factory.AddSocketDataProvider(&socket_data);
  std::unique_ptr<DatagramClientSocket> socket =
      socket_factory.CreateDatagramClientSocket(
          DatagramSocket::BindType::DEFAULT_BIND,
          handles::kInvalidNetworkHandle, nullptr,
          net_log_with_source_.source());
  socket->Connect(IPEndPoint());
  std::unique_ptr<quic::QuicReceivedPacket> packet = TestPacket(999);
  scoped_refptr<StringIOBuffer> buffer = base::MakeRefCounted<StringIOBuffer>(
      std::string(packet->data(), packet->length()));

  EXPECT_NONFATAL_FAILURE(
      EXPECT_EQ(ERR_UNEXPECTED,
                socket->Write(buffer.get(), packet->length(), base::DoNothing(),
                              TRAFFIC_ANNOTATION_FOR_TESTS)),
      // Content of the setting frame should be decoded in the output.
      "SETTINGS_H3_DATAGRAM = 1;");
}

}  // namespace net::test
