// Copyright 2016 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/socket/socket_bio_adapter.h"

#include <string.h>

#include <memory>

#include "base/containers/span.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "crypto/openssl_util.h"
#include "net/base/address_list.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_source.h"
#include "net/socket/socket_test_util.h"
#include "net/socket/stream_socket.h"
#include "net/ssl/openssl_ssl_util.h"
#include "net/test/test_with_scoped_task_environment.h"
#include "starboard/memory.h"
#include "starboard/types.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/bio.h"
#include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"

namespace net {

enum ReadIfReadySupport {
  // ReadIfReady() field trial is enabled, and ReadyIfReady() is implemented.
  READ_IF_READY_ENABLED_SUPPORTED,
  // ReadIfReady() field trial is enabled, but ReadyIfReady() is unimplemented.
  READ_IF_READY_ENABLED_NOT_SUPPORTED,
  // ReadIfReady() field trial is disabled.
  READ_IF_READY_DISABLED,
};

class SocketBIOAdapterTest : public testing::TestWithParam<ReadIfReadySupport>,
                             public SocketBIOAdapter::Delegate,
                             public WithScopedTaskEnvironment {
 protected:
  void SetUp() override {
    if (GetParam() == READ_IF_READY_DISABLED) {
      scoped_feature_list_.InitAndDisableFeature(
          Socket::kReadIfReadyExperiment);
    } else if (GetParam() == READ_IF_READY_ENABLED_SUPPORTED) {
      factory_.set_enable_read_if_ready(true);
    }
  }

  std::unique_ptr<StreamSocket> MakeTestSocket(SocketDataProvider* data) {
    data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
    factory_.AddSocketDataProvider(data);
    std::unique_ptr<StreamSocket> socket = factory_.CreateTransportClientSocket(
        AddressList(), nullptr, nullptr, NetLogSource());
    CHECK_EQ(OK, socket->Connect(CompletionOnceCallback()));
    return socket;
  }

  void set_reset_on_write_ready(
      std::unique_ptr<SocketBIOAdapter>* reset_on_write_ready) {
    reset_on_write_ready_ = reset_on_write_ready;
  }

  void ExpectReadError(BIO* bio,
                       int error,
                       const crypto::OpenSSLErrStackTracer& tracer) {
    // BIO_read should fail.
    char buf;
    EXPECT_EQ(-1, BIO_read(bio, &buf, 1));
    EXPECT_EQ(error, MapOpenSSLError(SSL_ERROR_SSL, tracer));
    EXPECT_FALSE(BIO_should_read(bio));

    // Repeating the operation should replay the error.
    EXPECT_EQ(-1, BIO_read(bio, &buf, 1));
    EXPECT_EQ(error, MapOpenSSLError(SSL_ERROR_SSL, tracer));
    EXPECT_FALSE(BIO_should_read(bio));
  }

  void ExpectBlockingRead(BIO* bio, void* buf, int len) {
    // BIO_read should return a retryable error.
    EXPECT_EQ(-1, BIO_read(bio, buf, len));
    EXPECT_TRUE(BIO_should_read(bio));
    EXPECT_EQ(0u, ERR_peek_error());

    // Repeating the operation has the same result.
    EXPECT_EQ(-1, BIO_read(bio, buf, len));
    EXPECT_TRUE(BIO_should_read(bio));
    EXPECT_EQ(0u, ERR_peek_error());
  }

  void ExpectWriteError(BIO* bio,
                        int error,
                        const crypto::OpenSSLErrStackTracer& tracer) {
    // BIO_write should fail.
    char buf = '?';
    EXPECT_EQ(-1, BIO_write(bio, &buf, 1));
    EXPECT_EQ(error, MapOpenSSLError(SSL_ERROR_SSL, tracer));
    EXPECT_FALSE(BIO_should_write(bio));

    // Repeating the operation should replay the error.
    EXPECT_EQ(-1, BIO_write(bio, &buf, 1));
    EXPECT_EQ(error, MapOpenSSLError(SSL_ERROR_SSL, tracer));
    EXPECT_FALSE(BIO_should_write(bio));
  }

  void ExpectBlockingWrite(BIO* bio, const void* buf, int len) {
    // BIO_write should return a retryable error.
    EXPECT_EQ(-1, BIO_write(bio, buf, len));
    EXPECT_TRUE(BIO_should_write(bio));
    EXPECT_EQ(0u, ERR_peek_error());

    // Repeating the operation has the same result.
    EXPECT_EQ(-1, BIO_write(bio, buf, len));
    EXPECT_TRUE(BIO_should_write(bio));
    EXPECT_EQ(0u, ERR_peek_error());
  }

  void WaitForReadReady() {
    expect_read_ready_ = true;
    base::RunLoop().RunUntilIdle();
    EXPECT_FALSE(expect_read_ready_);
  }

  void WaitForWriteReady(SequencedSocketData* to_resume) {
    expect_write_ready_ = true;
    if (to_resume) {
      to_resume->Resume();
    }
    base::RunLoop().RunUntilIdle();
    EXPECT_FALSE(expect_write_ready_);
  }

  void WaitForBothReady() {
    expect_read_ready_ = true;
    expect_write_ready_ = true;
    base::RunLoop().RunUntilIdle();
    EXPECT_FALSE(expect_read_ready_);
    EXPECT_FALSE(expect_write_ready_);
  }

  // SocketBIOAdapter::Delegate implementation:
  void OnReadReady() override {
    EXPECT_TRUE(expect_read_ready_);
    expect_read_ready_ = false;
  }

  void OnWriteReady() override {
    EXPECT_TRUE(expect_write_ready_);
    expect_write_ready_ = false;
    if (reset_on_write_ready_)
      reset_on_write_ready_->reset();
  }

 private:
  bool expect_read_ready_ = false;
  bool expect_write_ready_ = false;
  MockClientSocketFactory factory_;
  std::unique_ptr<SocketBIOAdapter>* reset_on_write_ready_ = nullptr;
  base::test::ScopedFeatureList scoped_feature_list_;
};

INSTANTIATE_TEST_CASE_P(/* no prefix */,
                        SocketBIOAdapterTest,
                        testing::Values(READ_IF_READY_ENABLED_SUPPORTED,
                                        READ_IF_READY_ENABLED_NOT_SUPPORTED,
                                        READ_IF_READY_DISABLED));

// Test that data can be read synchronously.
TEST_P(SocketBIOAdapterTest, ReadSync) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockRead reads[] = {
      MockRead(SYNCHRONOUS, 0, "hello"), MockRead(SYNCHRONOUS, 1, "world"),
      MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET, 2),
  };

  SequencedSocketData data(reads, base::span<MockWrite>());
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 100, 100, this);
  BIO* bio = adapter->bio();
  EXPECT_FALSE(adapter->HasPendingReadData());

  // Read the data synchronously. Although the buffer has room for both,
  // BIO_read only reports one socket-level Read.
  char buf[10];
  EXPECT_EQ(5, BIO_read(bio, buf, sizeof(buf)));
  EXPECT_EQ(0, memcmp("hello", buf, 5));
  EXPECT_FALSE(adapter->HasPendingReadData());

  // Consume the next portion one byte at a time.
  EXPECT_EQ(1, BIO_read(bio, buf, 1));
  EXPECT_EQ('w', buf[0]);
  EXPECT_TRUE(adapter->HasPendingReadData());

  EXPECT_EQ(1, BIO_read(bio, buf, 1));
  EXPECT_EQ('o', buf[0]);
  EXPECT_TRUE(adapter->HasPendingReadData());

  // The remainder may be consumed in a single BIO_read.
  EXPECT_EQ(3, BIO_read(bio, buf, sizeof(buf)));
  EXPECT_EQ(0, memcmp("rld", buf, 3));
  EXPECT_FALSE(adapter->HasPendingReadData());

  // The error is available synchoronously.
  ExpectReadError(bio, ERR_CONNECTION_RESET, tracer);
}

// Test that data can be read asynchronously.
TEST_P(SocketBIOAdapterTest, ReadAsync) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockRead reads[] = {
      MockRead(ASYNC, 0, "hello"), MockRead(ASYNC, 1, "world"),
      MockRead(ASYNC, ERR_CONNECTION_RESET, 2),
  };

  SequencedSocketData data(reads, base::span<MockWrite>());
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 100, 100, this);
  BIO* bio = adapter->bio();
  EXPECT_FALSE(adapter->HasPendingReadData());

  // Attempt to read data. It will fail but schedule a Read.
  char buf[10];
  ExpectBlockingRead(bio, buf, sizeof(buf));
  EXPECT_FALSE(adapter->HasPendingReadData());

  // After waiting, the data is available if Read() is used.
  WaitForReadReady();
  if (GetParam() == READ_IF_READY_ENABLED_SUPPORTED) {
    EXPECT_FALSE(adapter->HasPendingReadData());
  } else {
    EXPECT_TRUE(adapter->HasPendingReadData());
  }

  // The first read is now available synchronously.
  EXPECT_EQ(5, BIO_read(bio, buf, sizeof(buf)));
  EXPECT_EQ(0, memcmp("hello", buf, 5));
  EXPECT_FALSE(adapter->HasPendingReadData());

  // The adapter does not schedule another Read until BIO_read is next called.
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(adapter->HasPendingReadData());

  // This time, under-request the data. The adapter should still read the full
  // amount.
  ExpectBlockingRead(bio, buf, 1);
  EXPECT_FALSE(adapter->HasPendingReadData());

  // After waiting, the data is available if Read() is used.
  WaitForReadReady();
  if (GetParam() == READ_IF_READY_ENABLED_SUPPORTED) {
    EXPECT_FALSE(adapter->HasPendingReadData());
  } else {
    EXPECT_TRUE(adapter->HasPendingReadData());
  }

  // The next read is now available synchronously.
  EXPECT_EQ(5, BIO_read(bio, buf, sizeof(buf)));
  EXPECT_EQ(0, memcmp("world", buf, 5));
  EXPECT_FALSE(adapter->HasPendingReadData());

  // The error is not yet available.
  ExpectBlockingRead(bio, buf, sizeof(buf));
  WaitForReadReady();

  // The error is now available synchoronously.
  ExpectReadError(bio, ERR_CONNECTION_RESET, tracer);
}

// Test that synchronous EOF is mapped to ERR_CONNECTION_CLOSED.
TEST_P(SocketBIOAdapterTest, ReadEOFSync) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockRead reads[] = {
      MockRead(SYNCHRONOUS, 0, 0),
  };

  SequencedSocketData data(reads, base::span<MockWrite>());
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 100, 100, this);

  ExpectReadError(adapter->bio(), ERR_CONNECTION_CLOSED, tracer);
}

// Test that asynchronous EOF is mapped to ERR_CONNECTION_CLOSED.
TEST_P(SocketBIOAdapterTest, ReadEOFAsync) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockRead reads[] = {
      MockRead(ASYNC, 0, 0),
  };

  SequencedSocketData data(reads, base::span<MockWrite>());
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 100, 100, this);

  char buf;
  ExpectBlockingRead(adapter->bio(), &buf, 1);
  WaitForReadReady();
  ExpectReadError(adapter->bio(), ERR_CONNECTION_CLOSED, tracer);
}

// Test that data can be written synchronously.
TEST_P(SocketBIOAdapterTest, WriteSync) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockWrite writes[] = {
      MockWrite(SYNCHRONOUS, 0, "hello"),
      MockWrite(SYNCHRONOUS, 1, "wor"),
      MockWrite(SYNCHRONOUS, 2, "ld"),
      MockWrite(SYNCHRONOUS, 3, "helloworld"),
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 4),
  };

  SequencedSocketData data(base::span<MockRead>(), writes);
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 10, 10, this);
  BIO* bio = adapter->bio();

  // Test data entering and leaving the buffer synchronously. The second write
  // takes multiple iterations (events 0 to 2).
  EXPECT_EQ(5, BIO_write(bio, "hello", 5));
  EXPECT_EQ(5, BIO_write(bio, "world", 5));

  // If writing larger than the buffer size, only part of the data is written
  // (event 3).
  EXPECT_EQ(10, BIO_write(bio, "helloworldhelloworld", 20));

  // Writing "aaaaa" fails (event 4), but there is a write buffer, so errors
  // are delayed.
  EXPECT_EQ(5, BIO_write(bio, "aaaaa", 5));

  // However once the error is registered, subsequent writes fail.
  ExpectWriteError(bio, ERR_CONNECTION_RESET, tracer);
}

// Test that data can be written asynchronously.
TEST_P(SocketBIOAdapterTest, WriteAsync) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockWrite writes[] = {
      MockWrite(ASYNC, 0, "aaa"),
      MockWrite(ASYNC, ERR_IO_PENDING, 1),  // pause
      MockWrite(ASYNC, 2, "aabbbbb"),
      MockWrite(ASYNC, 3, "ccc"),
      MockWrite(ASYNC, 4, "ddd"),
      MockWrite(ASYNC, ERR_IO_PENDING, 5),  // pause
      MockWrite(ASYNC, 6, "dd"),
      MockWrite(SYNCHRONOUS, 7, "e"),
      MockWrite(SYNCHRONOUS, 8, "e"),
      MockWrite(ASYNC, 9, "e"),
      MockWrite(ASYNC, 10, "ee"),
      MockWrite(ASYNC, ERR_IO_PENDING, 11),  // pause
      MockWrite(ASYNC, 12, "eff"),
      MockWrite(ASYNC, 13, "ggggggg"),
      MockWrite(ASYNC, ERR_CONNECTION_RESET, 14),
  };

  SequencedSocketData data(base::span<MockRead>(), writes);
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 10, 10, this);
  BIO* bio = adapter->bio();

  // Data which fits in the buffer is returned synchronously, even if not
  // flushed synchronously.
  EXPECT_EQ(5, BIO_write(bio, "aaaaa", 5));
  EXPECT_EQ(5, BIO_write(bio, "bbbbb", 5));

  // The buffer contains:
  //
  //   [aaaaabbbbb]
  //    ^

  // The buffer is full now, so the next write will block.
  ExpectBlockingWrite(bio, "zzzzz", 5);

  // Let the first socket write complete (event 0) and pause (event 1).
  WaitForWriteReady(nullptr);
  EXPECT_TRUE(data.IsPaused());

  // The buffer contains:
  //
  //   [...aabbbbb]
  //       ^

  // The ring buffer now has 3 bytes of space with "aabbbbb" still to be
  // written. Attempting to write 3 bytes means 3 succeed.
  EXPECT_EQ(3, BIO_write(bio, "cccccccccc", 10));

  // The buffer contains:
  //
  //   [cccaabbbbb]
  //       ^

  // Drain the buffer (events 2 and 3).
  WaitForWriteReady(&data);

  // The buffer is now empty.

  // Now test something similar but arrange for a BIO_write (the 'e's below) to
  // wrap around the buffer.  Write five bytes into the buffer, flush the first
  // three (event 4), and pause (event 5). OnWriteReady is not signaled because
  // the buffer was not full.
  EXPECT_EQ(5, BIO_write(bio, "ddddd", 5));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(data.IsPaused());

  // The buffer contains:
  //
  //   [...dd.....]
  //       ^

  // The adapter maintains a ring buffer, so 6 bytes fit.
  EXPECT_EQ(6, BIO_write(bio, "eeeeee", 6));

  // The buffer contains:
  //
  //   [e..ddeeeee]
  //       ^

  // The remaining space may be filled in.
  EXPECT_EQ(2, BIO_write(bio, "ffffffffff", 10));

  // The buffer contains:
  //
  //   [effddeeeee]
  //       ^

  // Drain to the end of the ring buffer, so it wraps around (events 6 to 10)
  // and pause (event 11). Test that synchronous and asynchronous writes both
  // drain. The start of the buffer has now wrapped around.
  WaitForWriteReady(&data);
  EXPECT_TRUE(data.IsPaused());

  // The buffer contains:
  //
  //   [eff.......]
  //    ^

  // Test wrapping around works correctly and the buffer may be appended to.
  EXPECT_EQ(7, BIO_write(bio, "gggggggggg", 10));

  // The buffer contains:
  //
  //   [effggggggg]
  //    ^

  // The buffer is full now, so the next write will block.
  ExpectBlockingWrite(bio, "zzzzz", 5);

  // Drain the buffer to confirm the ring buffer's contents are as expected
  // (events 12 and 13).
  WaitForWriteReady(&data);

  // Write again so the write error may be discovered.
  EXPECT_EQ(5, BIO_write(bio, "hhhhh", 5));

  // Release the write error (event 14). At this point future BIO_write calls
  // fail. The buffer was not full, so OnWriteReady is not signalled.
  base::RunLoop().RunUntilIdle();
  ExpectWriteError(bio, ERR_CONNECTION_RESET, tracer);
}

// Test that a failed socket write is reported through BIO_read and prevents it
// from scheduling a socket read. See https://crbug.com/249848.
TEST_P(SocketBIOAdapterTest, WriteStopsRead) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockWrite writes[] = {
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 0),
  };

  SequencedSocketData data(base::span<MockRead>(), writes);
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 100, 100, this);
  BIO* bio = adapter->bio();

  // The write fails, but there is a write buffer, so errors are delayed.
  EXPECT_EQ(5, BIO_write(bio, "aaaaa", 5));

  // The write error is surfaced out of BIO_read. There are no MockReads, so
  // this also tests that no socket reads are attempted.
  ExpectReadError(bio, ERR_CONNECTION_RESET, tracer);
}

// Test that a synchronous failed socket write interrupts a blocked
// BIO_read. See https://crbug.com/249848.
TEST_P(SocketBIOAdapterTest, SyncWriteInterruptsRead) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockRead reads[] = {
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0),
  };

  MockWrite writes[] = {
      MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 1),
  };

  SequencedSocketData data(reads, writes);
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 100, 100, this);
  BIO* bio = adapter->bio();

  // Attempt to read from the transport. It will block indefinitely.
  char buf;
  ExpectBlockingRead(adapter->bio(), &buf, 1);

  // Schedule a socket write.
  EXPECT_EQ(5, BIO_write(bio, "aaaaa", 5));

  // The write error triggers OnReadReady.
  WaitForReadReady();

  // The write error is surfaced out of BIO_read.
  ExpectReadError(bio, ERR_CONNECTION_RESET, tracer);
}

// Test that an asynchronous failed socket write interrupts a blocked
// BIO_read. See https://crbug.com/249848.
TEST_P(SocketBIOAdapterTest, AsyncWriteInterruptsRead) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockRead reads[] = {
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0),
  };

  MockWrite writes[] = {
      MockWrite(ASYNC, ERR_CONNECTION_RESET, 1),
  };

  SequencedSocketData data(reads, writes);
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 100, 100, this);
  BIO* bio = adapter->bio();

  // Attempt to read from the transport. It will block indefinitely.
  char buf;
  ExpectBlockingRead(adapter->bio(), &buf, 1);

  // Schedule a socket write.
  EXPECT_EQ(5, BIO_write(bio, "aaaaa", 5));

  // The write error is signaled asynchronously and interrupts BIO_read, so
  // OnReadReady is signaled. The write buffer was not full, so OnWriteReady is
  // not signaled.
  WaitForReadReady();

  // The write error is surfaced out of BIO_read.
  ExpectReadError(bio, ERR_CONNECTION_RESET, tracer);
}

// Test that an asynchronous failed socket write interrupts a blocked BIO_read,
// signaling both if the buffer was full. See https://crbug.com/249848.
TEST_P(SocketBIOAdapterTest, AsyncWriteInterruptsBoth) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockRead reads[] = {
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0),
  };

  MockWrite writes[] = {
      MockWrite(ASYNC, ERR_CONNECTION_RESET, 1),
  };

  SequencedSocketData data(reads, writes);
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 5, 5, this);
  BIO* bio = adapter->bio();

  // Attempt to read from the transport. It will block indefinitely.
  char buf;
  ExpectBlockingRead(adapter->bio(), &buf, 1);

  // Schedule a socket write.
  EXPECT_EQ(5, BIO_write(bio, "aaaaa", 5));

  // The write error is signaled asynchronously and interrupts BIO_read, so
  // OnReadReady is signaled. The write buffer was full, so both OnWriteReady is
  // also signaled.
  WaitForBothReady();

  // The write error is surfaced out of BIO_read.
  ExpectReadError(bio, ERR_CONNECTION_RESET, tracer);
}

// Test that SocketBIOAdapter handles OnWriteReady deleting itself when both
// need to be signaled.
TEST_P(SocketBIOAdapterTest, DeleteOnWriteReady) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  MockRead reads[] = {
      MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0),
  };

  MockWrite writes[] = {
      MockWrite(ASYNC, ERR_CONNECTION_RESET, 1),
  };

  SequencedSocketData data(reads, writes);
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 5, 5, this);
  BIO* bio = adapter->bio();

  // Arrange for OnReadReady and OnWriteReady to both be signaled due to write
  // error propagation (see the AsyncWriteInterruptsBoth test).
  char buf;
  ExpectBlockingRead(adapter->bio(), &buf, 1);
  EXPECT_EQ(5, BIO_write(bio, "aaaaa", 5));

  // Both OnWriteReady and OnReadReady would be signaled, but OnWriteReady
  // deletes the adapter first.
  set_reset_on_write_ready(&adapter);
  WaitForWriteReady(nullptr);

  EXPECT_FALSE(adapter);
}

// Test that using a BIO after the underlying adapter is destroyed fails
// gracefully.
TEST_P(SocketBIOAdapterTest, Detached) {
  crypto::OpenSSLErrStackTracer tracer(FROM_HERE);

  SequencedSocketData data;
  std::unique_ptr<StreamSocket> socket = MakeTestSocket(&data);
  std::unique_ptr<SocketBIOAdapter> adapter =
      std::make_unique<SocketBIOAdapter>(socket.get(), 100, 100, this);

  // Retain an additional reference to the BIO.
  bssl::UniquePtr<BIO> bio = bssl::UpRef(adapter->bio());

  // Release the adapter.
  adapter.reset();

  ExpectReadError(bio.get(), ERR_UNEXPECTED, tracer);
  ExpectWriteError(bio.get(), ERR_UNEXPECTED, tracer);
}

}  // namespace net
