1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "remoting/protocol/buffered_socket_writer.h" 6 7 #include <stdlib.h> 8 9 #include "base/bind.h" 10 #include "base/message_loop/message_loop.h" 11 #include "net/base/io_buffer.h" 12 #include "net/base/net_errors.h" 13 #include "remoting/protocol/fake_session.h" 14 #include "testing/gmock/include/gmock/gmock.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace remoting { 18 namespace protocol { 19 20 namespace { 21 const int kTestBufferSize = 10 * 1024; // 10k; 22 const size_t kWriteChunkSize = 1024U; 23 } // namespace 24 25 class BufferedSocketWriterTest : public testing::Test { 26 public: 27 BufferedSocketWriterTest() 28 : write_error_(0) { 29 } 30 31 void OnDone() { 32 base::MessageLoop::current()->PostTask(FROM_HERE, 33 base::MessageLoop::QuitClosure()); 34 } 35 36 void DestroyWriterAndQuit() { 37 written_data_ = socket_->written_data(); 38 writer_.reset(); 39 socket_.reset(); 40 base::MessageLoop::current()->PostTask(FROM_HERE, 41 base::MessageLoop::QuitClosure()); 42 } 43 44 void Unexpected() { 45 EXPECT_TRUE(false); 46 } 47 48 protected: 49 virtual void SetUp() OVERRIDE { 50 socket_.reset(new FakeSocket()); 51 writer_.reset(new BufferedSocketWriter()); 52 writer_->Init(socket_.get(), base::Bind( 53 &BufferedSocketWriterTest::OnWriteFailed, base::Unretained(this))); 54 test_buffer_ = new net::IOBufferWithSize(kTestBufferSize); 55 test_buffer_2_ = new net::IOBufferWithSize(kTestBufferSize); 56 for (int i = 0; i< kTestBufferSize; ++i) { 57 test_buffer_->data()[i] = rand() % 256; 58 test_buffer_2_->data()[i] = rand() % 256; 59 } 60 } 61 62 void OnWriteFailed(int error) { 63 write_error_ = error; 64 } 65 66 void TestWrite() { 67 writer_->Write(test_buffer_, base::Bind(&BufferedSocketWriterTest::OnDone, 68 base::Unretained(this))); 69 writer_->Write(test_buffer_2_, base::Bind(&BufferedSocketWriterTest::OnDone, 70 base::Unretained(this))); 71 message_loop_.Run(); 72 ASSERT_EQ(static_cast<size_t>(test_buffer_->size() + 73 test_buffer_2_->size()), 74 socket_->written_data().size()); 75 EXPECT_EQ(0, memcmp(test_buffer_->data(), socket_->written_data().data(), 76 test_buffer_->size())); 77 EXPECT_EQ(0, memcmp(test_buffer_2_->data(), 78 socket_->written_data().data() + test_buffer_->size(), 79 test_buffer_2_->size())); 80 } 81 82 void TestAppendInCallback() { 83 writer_->Write(test_buffer_, base::Bind( 84 base::IgnoreResult(&BufferedSocketWriterBase::Write), 85 base::Unretained(writer_.get()), test_buffer_2_, 86 base::Bind(&BufferedSocketWriterTest::OnDone, 87 base::Unretained(this)))); 88 message_loop_.Run(); 89 ASSERT_EQ(static_cast<size_t>(test_buffer_->size() + 90 test_buffer_2_->size()), 91 socket_->written_data().size()); 92 EXPECT_EQ(0, memcmp(test_buffer_->data(), socket_->written_data().data(), 93 test_buffer_->size())); 94 EXPECT_EQ(0, memcmp(test_buffer_2_->data(), 95 socket_->written_data().data() + test_buffer_->size(), 96 test_buffer_2_->size())); 97 } 98 99 base::MessageLoop message_loop_; 100 scoped_ptr<FakeSocket> socket_; 101 scoped_ptr<BufferedSocketWriter> writer_; 102 scoped_refptr<net::IOBufferWithSize> test_buffer_; 103 scoped_refptr<net::IOBufferWithSize> test_buffer_2_; 104 std::string written_data_; 105 int write_error_; 106 }; 107 108 // Test synchronous write. 109 TEST_F(BufferedSocketWriterTest, WriteFull) { 110 TestWrite(); 111 } 112 113 // Test synchronous write in 1k chunks. 114 TEST_F(BufferedSocketWriterTest, WriteChunks) { 115 socket_->set_write_limit(kWriteChunkSize); 116 TestWrite(); 117 } 118 119 // Test asynchronous write. 120 TEST_F(BufferedSocketWriterTest, WriteAsync) { 121 socket_->set_async_write(true); 122 socket_->set_write_limit(kWriteChunkSize); 123 TestWrite(); 124 } 125 126 // Make sure we can call Write() from the done callback. 127 TEST_F(BufferedSocketWriterTest, AppendInCallbackSync) { 128 TestAppendInCallback(); 129 } 130 131 // Make sure we can call Write() from the done callback. 132 TEST_F(BufferedSocketWriterTest, AppendInCallbackAsync) { 133 socket_->set_async_write(true); 134 socket_->set_write_limit(kWriteChunkSize); 135 TestAppendInCallback(); 136 } 137 138 // Test that the writer can be destroyed from callback. 139 TEST_F(BufferedSocketWriterTest, DestroyFromCallback) { 140 socket_->set_async_write(true); 141 writer_->Write(test_buffer_, base::Bind( 142 &BufferedSocketWriterTest::DestroyWriterAndQuit, 143 base::Unretained(this))); 144 writer_->Write(test_buffer_2_, base::Bind( 145 &BufferedSocketWriterTest::Unexpected, 146 base::Unretained(this))); 147 socket_->set_async_write(false); 148 message_loop_.Run(); 149 ASSERT_GE(written_data_.size(), 150 static_cast<size_t>(test_buffer_->size())); 151 EXPECT_EQ(0, memcmp(test_buffer_->data(), written_data_.data(), 152 test_buffer_->size())); 153 } 154 155 // Verify that it stops writing after the first error. 156 TEST_F(BufferedSocketWriterTest, TestWriteErrorSync) { 157 socket_->set_write_limit(kWriteChunkSize); 158 writer_->Write(test_buffer_, base::Closure()); 159 socket_->set_async_write(true); 160 writer_->Write(test_buffer_2_, 161 base::Bind(&BufferedSocketWriterTest::Unexpected, 162 base::Unretained(this))); 163 socket_->set_next_write_error(net::ERR_FAILED); 164 socket_->set_async_write(false); 165 message_loop_.RunUntilIdle(); 166 EXPECT_EQ(net::ERR_FAILED, write_error_); 167 EXPECT_EQ(static_cast<size_t>(test_buffer_->size()), 168 socket_->written_data().size()); 169 } 170 171 // Verify that it stops writing after the first error. 172 TEST_F(BufferedSocketWriterTest, TestWriteErrorAsync) { 173 socket_->set_write_limit(kWriteChunkSize); 174 writer_->Write(test_buffer_, base::Closure()); 175 socket_->set_async_write(true); 176 writer_->Write(test_buffer_2_, 177 base::Bind(&BufferedSocketWriterTest::Unexpected, 178 base::Unretained(this))); 179 socket_->set_next_write_error(net::ERR_FAILED); 180 message_loop_.RunUntilIdle(); 181 EXPECT_EQ(net::ERR_FAILED, write_error_); 182 EXPECT_EQ(static_cast<size_t>(test_buffer_->size()), 183 socket_->written_data().size()); 184 } 185 186 } // namespace protocol 187 } // namespace remoting 188 189