diff options
author | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-05 18:14:20 +0000 |
---|---|---|
committer | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-05 18:14:20 +0000 |
commit | 5e660958562309f075c7fcb01c98bb08e5d1e07f (patch) | |
tree | 62e23f9c8a5d381259f669ad4805d6891d123942 /net/socket/deterministic_socket_data_unittest.cc | |
parent | e4234829356ce2d10f940ebe021910a187d07298 (diff) | |
download | chromium_src-5e660958562309f075c7fcb01c98bb08e5d1e07f.zip chromium_src-5e660958562309f075c7fcb01c98bb08e5d1e07f.tar.gz chromium_src-5e660958562309f075c7fcb01c98bb08e5d1e07f.tar.bz2 |
Clean up DeterministicSocketData class. Add unit tests to document
the correct usage of the class. Enable the class to support
async writes.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/3614002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61531 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/deterministic_socket_data_unittest.cc')
-rw-r--r-- | net/socket/deterministic_socket_data_unittest.cc | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/net/socket/deterministic_socket_data_unittest.cc b/net/socket/deterministic_socket_data_unittest.cc new file mode 100644 index 0000000..199dd0b --- /dev/null +++ b/net/socket/deterministic_socket_data_unittest.cc @@ -0,0 +1,530 @@ +// Copyright (c) 2010 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_test_util.h" + +#include "testing/platform_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +//----------------------------------------------------------------------------- + +namespace { + +static const char kMsg1[] = "\0hello!\xff"; +static const int kLen1 = arraysize(kMsg1); +static const char kMsg2[] = "\012345678\0"; +static const int kLen2 = arraysize(kMsg2); +static const char kMsg3[] = "bye!"; +static const int kLen3 = arraysize(kMsg3); + +} // anonymous namespace + +namespace net { + +class DeterministicSocketDataTest : public PlatformTest { + public: + DeterministicSocketDataTest(); + + virtual void TearDown(); + + protected: + void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes, + size_t writes_count); + + void AssertSyncReadEquals(const char* data, int len); + void AssertAsyncReadEquals(const char* data, int len); + void AssertReadReturns(const char* data, int len, int rv); + void AssertReadBufferEquals(const char* data, int len); + + void AssertSyncWriteEquals(const char* data, int len); + void AssertAsyncWriteEquals(const char* data, int len); + void AssertWriteReturns(const char* data, int len, int rv); + + TestCompletionCallback read_callback_; + TestCompletionCallback write_callback_; + ClientSocket* sock_; + scoped_refptr<DeterministicSocketData> data_; + + private: + scoped_refptr<IOBuffer> read_buf_; + MockConnect connect_data_; + + GURL url_; + HostPortPair endpoint_; + scoped_refptr<TCPSocketParams> tcp_params_; + ClientSocketPoolHistograms histograms_; + DeterministicMockClientSocketFactory socket_factory_; + MockTCPClientSocketPool socket_pool_; + ClientSocketHandle connection_; + + DISALLOW_COPY_AND_ASSIGN(DeterministicSocketDataTest); +}; + +DeterministicSocketDataTest::DeterministicSocketDataTest() + : read_callback_(), + write_callback_(), + sock_(NULL), + data_(NULL), + read_buf_(NULL), + connect_data_(false, OK), + url_("https://www.google.com"), + endpoint_("www.google.com", 443), + tcp_params_(new TCPSocketParams(endpoint_, LOWEST, url_, false)), + histograms_(""), + socket_pool_(10, 10, &histograms_, &socket_factory_) { +} + +void DeterministicSocketDataTest::TearDown() { + // Empty the current queue. + MessageLoop::current()->RunAllPending(); + PlatformTest::TearDown(); +} + +void DeterministicSocketDataTest::Initialize(MockRead* reads, + size_t reads_count, + MockWrite* writes, + size_t writes_count) { + data_ = new DeterministicSocketData(reads, reads_count, writes, writes_count); + data_->set_connect_data(connect_data_); + socket_factory_.AddSocketDataProvider(data_.get()); + + // Perform the TCP connect + EXPECT_EQ(OK, + connection_.Init(endpoint_.ToString(), tcp_params_, + LOWEST, NULL, (TCPClientSocketPool*)&socket_pool_, + BoundNetLog())); + sock_ = connection_.socket(); +} + +void DeterministicSocketDataTest::AssertSyncReadEquals(const char* data, + int len) { + // Issue the read, which will complete immediately + AssertReadReturns(data, len, len); + AssertReadBufferEquals(data, len); +} + +void DeterministicSocketDataTest::AssertAsyncReadEquals(const char* data, + int len) { + // Issue the read, which will be completed asynchronously + AssertReadReturns(data, len, ERR_IO_PENDING); + + EXPECT_FALSE(read_callback_.have_result()); + EXPECT_TRUE(sock_->IsConnected()); + data_->RunFor(1); // Runs 1 step, to cause the callbacks to be invoked + + // Now the read should complete + ASSERT_EQ(len, read_callback_.WaitForResult()); + AssertReadBufferEquals(data, len); +} + +void DeterministicSocketDataTest::AssertReadReturns(const char* data, + int len, int rv) { + read_buf_ = new IOBuffer(len); + ASSERT_EQ(rv, sock_->Read(read_buf_, len, &read_callback_)); +} + +void DeterministicSocketDataTest::AssertReadBufferEquals(const char* data, + int len) { + ASSERT_EQ(std::string(data, len), std::string(read_buf_->data(), len)); +} + +void DeterministicSocketDataTest::AssertSyncWriteEquals(const char* data, + int len) { + scoped_refptr<IOBuffer> buf = new IOBuffer(len); + memcpy(buf->data(), data, len); + + // Issue the write, which will complete immediately + ASSERT_EQ(len, sock_->Write(buf, len, &write_callback_)); +} + +void DeterministicSocketDataTest::AssertAsyncWriteEquals(const char* data, + int len) { + // Issue the read, which will be completed asynchronously + AssertWriteReturns(data, len, ERR_IO_PENDING); + + EXPECT_FALSE(read_callback_.have_result()); + EXPECT_TRUE(sock_->IsConnected()); + data_->RunFor(1); // Runs 1 step, to cause the callbacks to be invoked + + ASSERT_EQ(len, write_callback_.WaitForResult()); +} + +void DeterministicSocketDataTest::AssertWriteReturns(const char* data, + int len, int rv) { + scoped_refptr<IOBuffer> buf = new IOBuffer(len); + memcpy(buf->data(), data, len); + + // Issue the read, which will complete asynchronously + ASSERT_EQ(rv, sock_->Write(buf, len, &write_callback_)); +} + +// ----------- Read + +TEST_F(DeterministicSocketDataTest, SingleSyncReadWhileStopped) { + MockRead reads[] = { + MockRead(false, kMsg1, kLen1, 0), // Sync Read + MockRead(false, 0, 1), // EOF + }; + + Initialize(reads, arraysize(reads), NULL, 0); + + data_->SetStopped(true); + AssertReadReturns(kMsg1, kLen1, ERR_UNEXPECTED); +} + +TEST_F(DeterministicSocketDataTest, SingleSyncReadTooEarly) { + MockRead reads[] = { + MockRead(false, kMsg1, kLen1, 1), // Sync Read + MockRead(false, 0, 2), // EOF + }; + + Initialize(reads, arraysize(reads), NULL, 0); + + data_->StopAfter(2); + ASSERT_FALSE(data_->stopped()); + AssertReadReturns(kMsg1, kLen1, ERR_UNEXPECTED); +} + +TEST_F(DeterministicSocketDataTest, SingleSyncRead) { + MockRead reads[] = { + MockRead(false, kMsg1, kLen1, 0), // Sync Read + MockRead(false, 0, 1), // EOF + }; + + Initialize(reads, arraysize(reads), NULL, 0); + // Make sure we don't stop before we've read all the data + data_->StopAfter(1); + AssertSyncReadEquals(kMsg1, kLen1); +} + +TEST_F(DeterministicSocketDataTest, MultipleSyncReads) { + MockRead reads[] = { + MockRead(false, kMsg1, kLen1, 0), // Sync Read + MockRead(false, kMsg2, kLen2, 1), // Sync Read + MockRead(false, kMsg3, kLen3, 2), // Sync Read + MockRead(false, kMsg3, kLen3, 3), // Sync Read + MockRead(false, kMsg2, kLen2, 4), // Sync Read + MockRead(false, kMsg3, kLen3, 5), // Sync Read + MockRead(false, kMsg1, kLen1, 6), // Sync Read + MockRead(false, 0, 7), // EOF + }; + + Initialize(reads, arraysize(reads), NULL, 0); + + // Make sure we don't stop before we've read all the data + data_->StopAfter(10); + AssertSyncReadEquals(kMsg1, kLen1); + AssertSyncReadEquals(kMsg2, kLen2); + AssertSyncReadEquals(kMsg3, kLen3); + AssertSyncReadEquals(kMsg3, kLen3); + AssertSyncReadEquals(kMsg2, kLen2); + AssertSyncReadEquals(kMsg3, kLen3); + AssertSyncReadEquals(kMsg1, kLen1); +} + +TEST_F(DeterministicSocketDataTest, SingleAsyncRead) { + MockRead reads[] = { + MockRead(true, kMsg1, kLen1, 0), // Async Read + MockRead(false, 0, 1), // EOF + }; + + Initialize(reads, arraysize(reads), NULL, 0); + + AssertAsyncReadEquals(kMsg1, kLen1); +} + +TEST_F(DeterministicSocketDataTest, MultipleAsyncReads) { + MockRead reads[] = { + MockRead(true, kMsg1, kLen1, 0), // Async Read + MockRead(true, kMsg2, kLen2, 1), // Async Read + MockRead(true, kMsg3, kLen3, 2), // Async Read + MockRead(true, kMsg3, kLen3, 3), // Async Read + MockRead(true, kMsg2, kLen2, 4), // Async Read + MockRead(true, kMsg3, kLen3, 5), // Async Read + MockRead(true, kMsg1, kLen1, 6), // Async Read + MockRead(false, 0, 7), // EOF + }; + + Initialize(reads, arraysize(reads), NULL, 0); + + AssertAsyncReadEquals(kMsg1, kLen1); + AssertAsyncReadEquals(kMsg2, kLen2); + AssertAsyncReadEquals(kMsg3, kLen3); + AssertAsyncReadEquals(kMsg3, kLen3); + AssertAsyncReadEquals(kMsg2, kLen2); + AssertAsyncReadEquals(kMsg3, kLen3); + AssertAsyncReadEquals(kMsg1, kLen1); +} + +TEST_F(DeterministicSocketDataTest, MixedReads) { + MockRead reads[] = { + MockRead(false, kMsg1, kLen1, 0), // Sync Read + MockRead(true, kMsg2, kLen2, 1), // Async Read + MockRead(false, kMsg3, kLen3, 2), // Sync Read + MockRead(true, kMsg3, kLen3, 3), // Async Read + MockRead(false, kMsg2, kLen2, 4), // Sync Read + MockRead(true, kMsg3, kLen3, 5), // Async Read + MockRead(false, kMsg1, kLen1, 6), // Sync Read + MockRead(false, 0, 7), // EOF + }; + + Initialize(reads, arraysize(reads), NULL, 0); + + data_->StopAfter(1); + AssertSyncReadEquals(kMsg1, kLen1); + AssertAsyncReadEquals(kMsg2, kLen2); + data_->StopAfter(1); + AssertSyncReadEquals(kMsg3, kLen3); + AssertAsyncReadEquals(kMsg3, kLen3); + data_->StopAfter(1); + AssertSyncReadEquals(kMsg2, kLen2); + AssertAsyncReadEquals(kMsg3, kLen3); + data_->StopAfter(1); + AssertSyncReadEquals(kMsg1, kLen1); +} + +// ----------- Write + +TEST_F(DeterministicSocketDataTest, SingleSyncWriteWhileStopped) { + MockWrite writes[] = { + MockWrite(false, kMsg1, kLen1, 0), // Sync Read + }; + + Initialize(NULL, 0, writes, arraysize(writes)); + + data_->SetStopped(true); + AssertWriteReturns(kMsg1, kLen1, ERR_UNEXPECTED); +} + +TEST_F(DeterministicSocketDataTest, SingleSyncWriteTooEarly) { + MockWrite writes[] = { + MockWrite(false, kMsg1, kLen1, 1), // Sync Write + }; + + Initialize(NULL, 0, writes, arraysize(writes)); + + data_->StopAfter(2); + ASSERT_FALSE(data_->stopped()); + AssertWriteReturns(kMsg1, kLen1, ERR_UNEXPECTED); +} + +TEST_F(DeterministicSocketDataTest, SingleSyncWrite) { + MockWrite writes[] = { + MockWrite(false, kMsg1, kLen1, 0), // Sync Write + }; + + Initialize(NULL, 0, writes, arraysize(writes)); + + // Make sure we don't stop before we've read all the data + data_->StopAfter(1); + AssertSyncWriteEquals(kMsg1, kLen1); +} + +TEST_F(DeterministicSocketDataTest, MultipleSyncWrites) { + MockWrite writes[] = { + MockWrite(false, kMsg1, kLen1, 0), // Sync Write + MockWrite(false, kMsg2, kLen2, 1), // Sync Write + MockWrite(false, kMsg3, kLen3, 2), // Sync Write + MockWrite(false, kMsg3, kLen3, 3), // Sync Write + MockWrite(false, kMsg2, kLen2, 4), // Sync Write + MockWrite(false, kMsg3, kLen3, 5), // Sync Write + MockWrite(false, kMsg1, kLen1, 6), // Sync Write + }; + + Initialize(NULL, 0, writes, arraysize(writes)); + + // Make sure we don't stop before we've read all the data + data_->StopAfter(10); + AssertSyncWriteEquals(kMsg1, kLen1); + AssertSyncWriteEquals(kMsg2, kLen2); + AssertSyncWriteEquals(kMsg3, kLen3); + AssertSyncWriteEquals(kMsg3, kLen3); + AssertSyncWriteEquals(kMsg2, kLen2); + AssertSyncWriteEquals(kMsg3, kLen3); + AssertSyncWriteEquals(kMsg1, kLen1); +} + +TEST_F(DeterministicSocketDataTest, SingleAsyncWrite) { + MockWrite writes[] = { + MockWrite(true, kMsg1, kLen1, 0), // Async Write + }; + + Initialize(NULL, 0, writes, arraysize(writes)); + + AssertAsyncWriteEquals(kMsg1, kLen1); +} + +TEST_F(DeterministicSocketDataTest, MultipleAsyncWrites) { + MockWrite writes[] = { + MockWrite(true, kMsg1, kLen1, 0), // Async Write + MockWrite(true, kMsg2, kLen2, 1), // Async Write + MockWrite(true, kMsg3, kLen3, 2), // Async Write + MockWrite(true, kMsg3, kLen3, 3), // Async Write + MockWrite(true, kMsg2, kLen2, 4), // Async Write + MockWrite(true, kMsg3, kLen3, 5), // Async Write + MockWrite(true, kMsg1, kLen1, 6), // Async Write + }; + + Initialize(NULL, 0, writes, arraysize(writes)); + + AssertAsyncWriteEquals(kMsg1, kLen1); + AssertAsyncWriteEquals(kMsg2, kLen2); + AssertAsyncWriteEquals(kMsg3, kLen3); + AssertAsyncWriteEquals(kMsg3, kLen3); + AssertAsyncWriteEquals(kMsg2, kLen2); + AssertAsyncWriteEquals(kMsg3, kLen3); + AssertAsyncWriteEquals(kMsg1, kLen1); +} + +TEST_F(DeterministicSocketDataTest, MixedWrites) { + MockWrite writes[] = { + MockWrite(false, kMsg1, kLen1, 0), // Sync Write + MockWrite(true, kMsg2, kLen2, 1), // Async Write + MockWrite(false, kMsg3, kLen3, 2), // Sync Write + MockWrite(true, kMsg3, kLen3, 3), // Async Write + MockWrite(false, kMsg2, kLen2, 4), // Sync Write + MockWrite(true, kMsg3, kLen3, 5), // Async Write + MockWrite(false, kMsg1, kLen1, 6), // Sync Write + }; + + Initialize(NULL, 0, writes, arraysize(writes)); + + data_->StopAfter(1); + AssertSyncWriteEquals(kMsg1, kLen1); + AssertAsyncWriteEquals(kMsg2, kLen2); + data_->StopAfter(1); + AssertSyncWriteEquals(kMsg3, kLen3); + AssertAsyncWriteEquals(kMsg3, kLen3); + data_->StopAfter(1); + AssertSyncWriteEquals(kMsg2, kLen2); + AssertAsyncWriteEquals(kMsg3, kLen3); + data_->StopAfter(1); + AssertSyncWriteEquals(kMsg1, kLen1); +} + +// ----------- Mixed Reads and Writes + +TEST_F(DeterministicSocketDataTest, MixedSyncOperations) { + MockRead reads[] = { + MockRead(false, kMsg1, kLen1, 0), // Sync Read + MockRead(false, kMsg2, kLen2, 3), // Sync Read + MockRead(false, 0, 4), // EOF + }; + + MockWrite writes[] = { + MockWrite(false, kMsg2, kLen2, 1), // Sync Write + MockWrite(false, kMsg3, kLen3, 2), // Sync Write + }; + + Initialize(reads, arraysize(reads), writes, arraysize(writes)); + + // Make sure we don't stop before we've read/written everything + data_->StopAfter(10); + AssertSyncReadEquals(kMsg1, kLen1); + AssertSyncWriteEquals(kMsg2, kLen2); + AssertSyncWriteEquals(kMsg3, kLen3); + AssertSyncReadEquals(kMsg2, kLen2); +} + +TEST_F(DeterministicSocketDataTest, MixedAsyncOperations) { + MockRead reads[] = { + MockRead(true, kMsg1, kLen1, 0), // Sync Read + MockRead(true, kMsg2, kLen2, 3), // Sync Read + MockRead(true, 0, 4), // EOF + }; + + MockWrite writes[] = { + MockWrite(true, kMsg2, kLen2, 1), // Sync Write + MockWrite(true, kMsg3, kLen3, 2), // Sync Write + }; + + Initialize(reads, arraysize(reads), writes, arraysize(writes)); + + AssertAsyncReadEquals(kMsg1, kLen1); + AssertAsyncWriteEquals(kMsg2, kLen2); + AssertAsyncWriteEquals(kMsg3, kLen3); + AssertAsyncReadEquals(kMsg2, kLen2); +} + +TEST_F(DeterministicSocketDataTest, InterleavedAsyncOperations) { + // Order of completion is read, write, write, read + MockRead reads[] = { + MockRead(true, kMsg1, kLen1, 0), // Async Read + MockRead(true, kMsg2, kLen2, 3), // Async Read + MockRead(true, 0, 4), // EOF + }; + + MockWrite writes[] = { + MockWrite(true, kMsg2, kLen2, 1), // Async Write + MockWrite(true, kMsg3, kLen3, 2), // Async Write + }; + + Initialize(reads, arraysize(reads), writes, arraysize(writes)); + + // Issue the write, which will block until the read completes + AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING); + + // Issue the read which will return first + AssertReadReturns(kMsg1, kLen1, ERR_IO_PENDING); + + data_->RunFor(1); + ASSERT_EQ(kLen1, read_callback_.WaitForResult()); + AssertReadBufferEquals(kMsg1, kLen1); + + data_->RunFor(1); + ASSERT_EQ(kLen2, write_callback_.WaitForResult()); + + data_->StopAfter(1); + // Issue the read, which will block until the write completes + AssertReadReturns(kMsg2, kLen2, ERR_IO_PENDING); + + // Issue the writes which will return first + AssertWriteReturns(kMsg3, kLen3, ERR_IO_PENDING); + + data_->RunFor(1); + ASSERT_EQ(kLen3, write_callback_.WaitForResult()); + + data_->RunFor(1); + ASSERT_EQ(kLen2, read_callback_.WaitForResult()); + AssertReadBufferEquals(kMsg2, kLen2); +} + +TEST_F(DeterministicSocketDataTest, InterleavedMixedOperations) { + // Order of completion is read, write, write, read + MockRead reads[] = { + MockRead(false, kMsg1, kLen1, 0), // Sync Read + MockRead(true, kMsg2, kLen2, 3), // Async Read + MockRead(false, 0, 4), // EOF + }; + + MockWrite writes[] = { + MockWrite(true, kMsg2, kLen2, 1), // Async Write + MockWrite(false, kMsg3, kLen3, 2), // Sync Write + }; + + Initialize(reads, arraysize(reads), writes, arraysize(writes)); + + // Issue the write, which will block until the read completes + AssertWriteReturns(kMsg2, kLen2, ERR_IO_PENDING); + + // Issue the writes which will complete immediately + data_->StopAfter(1); + AssertSyncReadEquals(kMsg1, kLen1); + + data_->RunFor(1); + ASSERT_EQ(kLen2, write_callback_.WaitForResult()); + + // Issue the read, which will block until the write completes + AssertReadReturns(kMsg2, kLen2, ERR_IO_PENDING); + + // Issue the writes which will complete immediately + data_->StopAfter(1); + AssertSyncWriteEquals(kMsg3, kLen3); + + data_->RunFor(1); + ASSERT_EQ(kLen2, read_callback_.WaitForResult()); + AssertReadBufferEquals(kMsg2, kLen2); +} + +} // namespace net |