1 // Copyright 2015 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.
5 #include "remoting/base/buffered_socket_writer.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 "net/socket/socket_test_util.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
22 const int kTestBufferSize
= 10000;
23 const size_t kWriteChunkSize
= 1024U;
25 class SocketDataProvider
: public net::SocketDataProvider
{
28 : write_limit_(-1), async_write_(false), next_write_error_(net::OK
) {}
30 net::MockRead
OnRead() override
{
31 return net::MockRead(net::ASYNC
, net::ERR_IO_PENDING
);
34 net::MockWriteResult
OnWrite(const std::string
& data
) override
{
35 if (next_write_error_
!= net::OK
) {
36 int r
= next_write_error_
;
37 next_write_error_
= net::OK
;
38 return net::MockWriteResult(async_write_
? net::ASYNC
: net::SYNCHRONOUS
,
41 int size
= data
.size();
43 size
= std::min(write_limit_
, size
);
44 written_data_
.append(data
, 0, size
);
45 return net::MockWriteResult(async_write_
? net::ASYNC
: net::SYNCHRONOUS
,
49 bool AllReadDataConsumed() const override
{
53 bool AllWriteDataConsumed() const override
{
57 void Reset() override
{}
59 std::string
written_data() { return written_data_
; }
61 void set_write_limit(int limit
) { write_limit_
= limit
; }
62 void set_async_write(bool async_write
) { async_write_
= async_write
; }
63 void set_next_write_error(int error
) { next_write_error_
= error
; }
66 std::string written_data_
;
69 int next_write_error_
;
74 class BufferedSocketWriterTest
: public testing::Test
{
76 BufferedSocketWriterTest()
80 void DestroyWriter() {
90 void SetUp() override
{
91 socket_
.reset(new net::MockTCPClientSocket(net::AddressList(), &net_log_
,
92 &socket_data_provider_
));
93 socket_data_provider_
.set_connect_data(
94 net::MockConnect(net::SYNCHRONOUS
, net::OK
));
95 EXPECT_EQ(net::OK
, socket_
->Connect(net::CompletionCallback()));
97 writer_
= BufferedSocketWriter::CreateForSocket(
98 socket_
.get(), base::Bind(&BufferedSocketWriterTest::OnWriteFailed
,
99 base::Unretained(this)));
100 test_buffer_
= new net::IOBufferWithSize(kTestBufferSize
);
101 test_buffer_2_
= new net::IOBufferWithSize(kTestBufferSize
);
102 for (int i
= 0; i
< kTestBufferSize
; ++i
) {
103 test_buffer_
->data()[i
] = rand() % 256;
104 test_buffer_2_
->data()[i
] = rand() % 256;
108 void OnWriteFailed(int error
) {
109 write_error_
= error
;
113 writer_
->Write(test_buffer_
, base::Closure());
114 writer_
->Write(test_buffer_2_
, base::Closure());
115 base::RunLoop().RunUntilIdle();
116 ASSERT_EQ(static_cast<size_t>(test_buffer_
->size() +
117 test_buffer_2_
->size()),
118 socket_data_provider_
.written_data().size());
119 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
120 socket_data_provider_
.written_data().data(),
121 test_buffer_
->size()));
122 EXPECT_EQ(0, memcmp(test_buffer_2_
->data(),
123 socket_data_provider_
.written_data().data() +
124 test_buffer_
->size(),
125 test_buffer_2_
->size()));
128 void TestAppendInCallback() {
129 writer_
->Write(test_buffer_
, base::Bind(
130 base::IgnoreResult(&BufferedSocketWriter::Write
),
131 base::Unretained(writer_
.get()), test_buffer_2_
,
133 base::RunLoop().RunUntilIdle();
134 ASSERT_EQ(static_cast<size_t>(test_buffer_
->size() +
135 test_buffer_2_
->size()),
136 socket_data_provider_
.written_data().size());
137 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
138 socket_data_provider_
.written_data().data(),
139 test_buffer_
->size()));
140 EXPECT_EQ(0, memcmp(test_buffer_2_
->data(),
141 socket_data_provider_
.written_data().data() +
142 test_buffer_
->size(),
143 test_buffer_2_
->size()));
146 base::MessageLoop message_loop_
;
147 net::NetLog net_log_
;
148 SocketDataProvider socket_data_provider_
;
149 scoped_ptr
<net::StreamSocket
> socket_
;
150 scoped_ptr
<BufferedSocketWriter
> writer_
;
151 scoped_refptr
<net::IOBufferWithSize
> test_buffer_
;
152 scoped_refptr
<net::IOBufferWithSize
> test_buffer_2_
;
156 // Test synchronous write.
157 TEST_F(BufferedSocketWriterTest
, WriteFull
) {
161 // Test synchronous write in 1k chunks.
162 TEST_F(BufferedSocketWriterTest
, WriteChunks
) {
163 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
167 // Test asynchronous write.
168 TEST_F(BufferedSocketWriterTest
, WriteAsync
) {
169 socket_data_provider_
.set_async_write(true);
170 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
174 // Make sure we can call Write() from the done callback.
175 TEST_F(BufferedSocketWriterTest
, AppendInCallbackSync
) {
176 TestAppendInCallback();
179 // Make sure we can call Write() from the done callback.
180 TEST_F(BufferedSocketWriterTest
, AppendInCallbackAsync
) {
181 socket_data_provider_
.set_async_write(true);
182 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
183 TestAppendInCallback();
186 // Test that the writer can be destroyed from callback.
187 TEST_F(BufferedSocketWriterTest
, DestroyFromCallback
) {
188 socket_data_provider_
.set_async_write(true);
189 writer_
->Write(test_buffer_
, base::Bind(
190 &BufferedSocketWriterTest::DestroyWriter
,
191 base::Unretained(this)));
192 writer_
->Write(test_buffer_2_
, base::Bind(
193 &BufferedSocketWriterTest::Unexpected
,
194 base::Unretained(this)));
195 socket_data_provider_
.set_async_write(false);
196 base::RunLoop().RunUntilIdle();
197 ASSERT_GE(socket_data_provider_
.written_data().size(),
198 static_cast<size_t>(test_buffer_
->size()));
199 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
200 socket_data_provider_
.written_data().data(),
201 test_buffer_
->size()));
204 // Verify that it stops writing after the first error.
205 TEST_F(BufferedSocketWriterTest
, TestWriteErrorSync
) {
206 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
207 writer_
->Write(test_buffer_
, base::Closure());
208 socket_data_provider_
.set_async_write(true);
209 socket_data_provider_
.set_next_write_error(net::ERR_FAILED
);
210 writer_
->Write(test_buffer_2_
,
211 base::Bind(&BufferedSocketWriterTest::Unexpected
,
212 base::Unretained(this)));
213 socket_data_provider_
.set_async_write(false);
214 base::RunLoop().RunUntilIdle();
215 EXPECT_EQ(net::ERR_FAILED
, write_error_
);
216 EXPECT_EQ(static_cast<size_t>(test_buffer_
->size()),
217 socket_data_provider_
.written_data().size());
220 // Verify that it stops writing after the first error.
221 TEST_F(BufferedSocketWriterTest
, TestWriteErrorAsync
) {
222 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
223 writer_
->Write(test_buffer_
, base::Closure());
224 socket_data_provider_
.set_async_write(true);
225 socket_data_provider_
.set_next_write_error(net::ERR_FAILED
);
226 writer_
->Write(test_buffer_2_
,
227 base::Bind(&BufferedSocketWriterTest::Unexpected
,
228 base::Unretained(this)));
229 base::RunLoop().RunUntilIdle();
230 EXPECT_EQ(net::ERR_FAILED
, write_error_
);
231 EXPECT_EQ(static_cast<size_t>(test_buffer_
->size()),
232 socket_data_provider_
.written_data().size());
235 } // namespace remoting