Commit 32320845 authored by rch's avatar rch Committed by Commit bot

Add CompleteRead to SequencedSocketData and convert all but 3 tests

to use SequencedSocketData.  Reduces runtime to 7 seconds from 11 seconds on my linux workstation

BUG=332112

Committed: https://crrev.com/d7b1887392866667126162a4e7854a2736449970
Cr-Commit-Position: refs/heads/master@{#328221}

Review URL: https://codereview.chromium.org/1124533002

Cr-Commit-Position: refs/heads/master@{#330288}
parent 08e3aa3e
......@@ -3686,22 +3686,22 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
MockWrite spdy_writes[] = {
CreateMockWrite(*connect, 1),
CreateMockWrite(*wrapped_get, 3),
CreateMockWrite(*window_update_get_resp, 5),
CreateMockWrite(*connect, 0),
CreateMockWrite(*wrapped_get, 2),
CreateMockWrite(*window_update_get_resp, 6),
CreateMockWrite(*window_update_body, 7),
};
MockRead spdy_reads[] = {
CreateMockRead(*conn_resp, 2, ASYNC),
CreateMockRead(*conn_resp, 1, ASYNC),
MockRead(ASYNC, ERR_IO_PENDING, 3),
CreateMockRead(*wrapped_get_resp, 4, ASYNC),
CreateMockRead(*wrapped_body, 6, ASYNC),
CreateMockRead(*wrapped_body, 5, ASYNC),
MockRead(ASYNC, 0, 8),
};
OrderedSocketData spdy_data(
spdy_reads, arraysize(spdy_reads),
spdy_writes, arraysize(spdy_writes));
SequencedSocketData spdy_data(spdy_reads, arraysize(spdy_reads), spdy_writes,
arraysize(spdy_writes));
session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
SSLSocketDataProvider ssl(ASYNC, OK);
......@@ -3716,6 +3716,10 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
int rv = trans->Start(&request, callback1.callback(), log.bound());
EXPECT_EQ(ERR_IO_PENDING, rv);
// Allow the SpdyProxyClientSocket's write callback to complete.
base::MessageLoop::current()->RunUntilIdle();
// Now allow the read of the response to complete.
spdy_data.CompleteRead();
rv = callback1.WaitForResult();
EXPECT_EQ(OK, rv);
......@@ -11861,8 +11865,8 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
reads.push_back(MockRead(ASYNC, OK, 3));
}
OrderedSocketData data(vector_as_array(&reads), reads.size(),
vector_as_array(&writes), writes.size());
SequencedSocketData data(vector_as_array(&reads), reads.size(),
vector_as_array(&writes), writes.size());
session_deps_.socket_factory->AddSocketDataProvider(&data);
// Connection to the origin fails.
......@@ -11907,6 +11911,10 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest {
int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
base::MessageLoop::current()->RunUntilIdle();
if (data.IsReadPaused()) {
data.CompleteRead();
}
rv = callback1.WaitForResult();
if (valid) {
EXPECT_EQ(OK, rv);
......
......@@ -194,6 +194,7 @@ class SequencedSocketDataTest : public testing::Test {
void AssertSyncWriteEquals(const char* data, int len);
void AssertAsyncWriteEquals(const char* data, int len);
void AssertWriteReturns(const char* data, int len, int rv);
void CompleteRead();
// When a given test completes, data_.at_eof() is expected to
// match the value specified here. Most test should consume all
......@@ -313,6 +314,10 @@ void SequencedSocketDataTest::AssertAsyncWriteEquals(const char* data,
ASSERT_EQ(len, write_callback_.WaitForResult());
}
void SequencedSocketDataTest::CompleteRead() {
data_->CompleteRead();
}
void SequencedSocketDataTest::AssertWriteReturns(const char* data,
int len,
int rv) {
......@@ -603,6 +608,28 @@ TEST_F(SequencedSocketDataTest, HangingRead) {
ASSERT_FALSE(read_callback_.have_result());
}
TEST_F(SequencedSocketDataTest, CompleteRead) {
MockRead reads[] = {
MockRead(ASYNC, ERR_IO_PENDING, 0), MockRead(ASYNC, kMsg1, kLen1, 1),
};
Initialize(reads, arraysize(reads), nullptr, 0);
AssertReadReturns(kLen1, ERR_IO_PENDING);
ASSERT_FALSE(read_callback_.have_result());
// Even though the read is scheduled to complete at sequence number 0,
// verify that the read callback in not called, until CompleteRead() is.
base::MessageLoop::current()->RunUntilIdle();
ASSERT_FALSE(read_callback_.have_result());
CompleteRead();
ASSERT_TRUE(read_callback_.have_result());
ASSERT_EQ(kLen1, read_callback_.WaitForResult());
AssertReadBufferEquals(kMsg1, kLen1);
}
// ----------- Write
TEST_F(SequencedSocketDataTest, SingleSyncWriteTooEarly) {
......
......@@ -524,15 +524,6 @@ MockRead SequencedSocketData::OnRead() {
NET_TRACE(1, " *** ") << "next_read: " << next_read.sequence_number;
CHECK_GE(next_read.sequence_number, sequence_number_);
// Special case handling for hanging reads.
if (next_read.mode == ASYNC && next_read.result == ERR_IO_PENDING) {
NET_TRACE(1, " *** ") << "Hanging read";
helper_.AdvanceRead();
++sequence_number_;
CHECK(helper_.at_read_eof());
return MockRead(SYNCHRONOUS, ERR_IO_PENDING);
}
if (next_read.sequence_number <= sequence_number_) {
if (next_read.mode == SYNCHRONOUS) {
NET_TRACE(1, " *** ") << "Returning synchronously";
......@@ -543,6 +534,15 @@ MockRead SequencedSocketData::OnRead() {
return next_read;
}
// If the result is ERR_IO_PENDING, then advance to the next state
// and pause reads.
if (next_read.result == ERR_IO_PENDING) {
NET_TRACE(1, " *** ") << "Pausing at: " << sequence_number_;
++sequence_number_;
helper_.AdvanceRead();
read_state_ = PAUSED;
return MockRead(SYNCHRONOUS, ERR_IO_PENDING);
}
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&SequencedSocketData::OnReadComplete,
weak_factory_.GetWeakPtr()));
......@@ -625,6 +625,19 @@ bool SequencedSocketData::at_write_eof() const {
return helper_.at_read_eof();
}
bool SequencedSocketData::IsReadPaused() {
return read_state_ == PAUSED;
}
void SequencedSocketData::CompleteRead() {
if (read_state_ != PAUSED) {
ADD_FAILURE() << "Unable to CompleteRead when not paused.";
return;
}
read_state_ = COMPLETING;
OnReadComplete();
}
void SequencedSocketData::MaybePostReadCompleteTask() {
NET_TRACE(1, " ****** ") << " current: " << sequence_number_;
// Only trigger the next read to complete if there is already a read pending
......@@ -634,6 +647,16 @@ void SequencedSocketData::MaybePostReadCompleteTask() {
return;
}
// If the result is ERR_IO_PENDING, then advance to the next state
// and pause reads.
if (helper_.PeekRead().result == ERR_IO_PENDING) {
NET_TRACE(1, " *** ") << "Pausing read at: " << sequence_number_;
++sequence_number_;
helper_.AdvanceRead();
read_state_ = PAUSED;
return;
}
NET_TRACE(1, " ****** ") << "Posting task to complete read: "
<< sequence_number_;
base::MessageLoop::current()->PostTask(
......@@ -681,7 +704,8 @@ void SequencedSocketData::OnReadComplete() {
// before calling that.
MaybePostWriteCompleteTask();
NET_TRACE(1, " *** ") << "Completing socket read for: " << sequence_number_;
NET_TRACE(1, " *** ") << "Completing socket read for: "
<< data.sequence_number;
DumpMockReadWrite(data);
socket()->OnReadComplete(data);
NET_TRACE(1, " *** ") << "Done";
......@@ -708,7 +732,8 @@ void SequencedSocketData::OnWriteComplete() {
// before calling that.
MaybePostReadCompleteTask();
NET_TRACE(1, " *** ") << " Completing socket write for: " << sequence_number_;
NET_TRACE(1, " *** ") << " Completing socket write for: "
<< data.sequence_number;
socket()->OnWriteComplete(rv);
NET_TRACE(1, " *** ") << "Done";
}
......
......@@ -512,6 +512,9 @@ class SequencedSocketData : public SocketDataProvider {
// Returns true if all data has been written.
bool at_write_eof() const;
bool IsReadPaused();
void CompleteRead();
private:
// Defines the state for the read or write path.
enum IoState {
......@@ -519,7 +522,9 @@ class SequencedSocketData : public SocketDataProvider {
PENDING, // An async operation in waiting for another opteration to
// complete.
COMPLETING, // A task has been posted to complet an async operation.
PAUSED, // IO is paused until CompleteRead() is called.
};
void OnReadComplete();
void OnWriteComplete();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment