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