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:
BufferedSocketWriterTest()27 BufferedSocketWriterTest()
28 : write_error_(0) {
29 }
30
OnDone()31 void OnDone() {
32 base::MessageLoop::current()->PostTask(FROM_HERE,
33 base::MessageLoop::QuitClosure());
34 }
35
DestroyWriterAndQuit()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
Unexpected()44 void Unexpected() {
45 EXPECT_TRUE(false);
46 }
47
48 protected:
SetUp()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
OnWriteFailed(int error)62 void OnWriteFailed(int error) {
63 write_error_ = error;
64 }
65
TestWrite()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
TestAppendInCallback()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.
TEST_F(BufferedSocketWriterTest,WriteFull)109 TEST_F(BufferedSocketWriterTest, WriteFull) {
110 TestWrite();
111 }
112
113 // Test synchronous write in 1k chunks.
TEST_F(BufferedSocketWriterTest,WriteChunks)114 TEST_F(BufferedSocketWriterTest, WriteChunks) {
115 socket_->set_write_limit(kWriteChunkSize);
116 TestWrite();
117 }
118
119 // Test asynchronous write.
TEST_F(BufferedSocketWriterTest,WriteAsync)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.
TEST_F(BufferedSocketWriterTest,AppendInCallbackSync)127 TEST_F(BufferedSocketWriterTest, AppendInCallbackSync) {
128 TestAppendInCallback();
129 }
130
131 // Make sure we can call Write() from the done callback.
TEST_F(BufferedSocketWriterTest,AppendInCallbackAsync)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.
TEST_F(BufferedSocketWriterTest,DestroyFromCallback)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.
TEST_F(BufferedSocketWriterTest,TestWriteErrorSync)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.
TEST_F(BufferedSocketWriterTest,TestWriteErrorAsync)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