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"
21 const int kTestBufferSize
= 10 * 1024; // 10k;
22 const size_t kWriteChunkSize
= 1024U;
24 class SocketDataProvider
: public net::SocketDataProvider
{
27 : write_limit_(-1), async_write_(false), next_write_error_(net::OK
) {}
29 net::MockRead
GetNextRead() override
{
30 return net::MockRead(net::ASYNC
, net::ERR_IO_PENDING
);
33 net::MockWriteResult
OnWrite(const std::string
& data
) override
{
34 if (next_write_error_
!= net::OK
) {
35 int r
= next_write_error_
;
36 next_write_error_
= net::OK
;
37 return net::MockWriteResult(async_write_
? net::ASYNC
: net::SYNCHRONOUS
,
40 int size
= data
.size();
42 size
= std::min(write_limit_
, size
);
43 written_data_
.append(data
, 0, size
);
44 return net::MockWriteResult(async_write_
? net::ASYNC
: net::SYNCHRONOUS
,
48 void Reset() override
{}
50 std::string
written_data() { return written_data_
; }
52 void set_write_limit(int limit
) { write_limit_
= limit
; }
53 void set_async_write(bool async_write
) { async_write_
= async_write
; }
54 void set_next_write_error(int error
) { next_write_error_
= error
; }
57 std::string written_data_
;
60 int next_write_error_
;
65 class BufferedSocketWriterTest
: public testing::Test
{
67 BufferedSocketWriterTest()
71 void DestroyWriter() {
81 void SetUp() override
{
82 socket_
.reset(new net::MockTCPClientSocket(net::AddressList(), &net_log_
,
83 &socket_data_provider_
));
84 socket_data_provider_
.set_connect_data(
85 net::MockConnect(net::SYNCHRONOUS
, net::OK
));
86 EXPECT_EQ(net::OK
, socket_
->Connect(net::CompletionCallback()));
88 writer_
.reset(new BufferedSocketWriter());
89 writer_
->Init(socket_
.get(), base::Bind(
90 &BufferedSocketWriterTest::OnWriteFailed
, base::Unretained(this)));
91 test_buffer_
= new net::IOBufferWithSize(kTestBufferSize
);
92 test_buffer_2_
= new net::IOBufferWithSize(kTestBufferSize
);
93 for (int i
= 0; i
< kTestBufferSize
; ++i
) {
94 test_buffer_
->data()[i
] = rand() % 256;
95 test_buffer_2_
->data()[i
] = rand() % 256;
99 void OnWriteFailed(int error
) {
100 write_error_
= error
;
104 writer_
->Write(test_buffer_
, base::Closure());
105 writer_
->Write(test_buffer_2_
, base::Closure());
106 base::RunLoop().RunUntilIdle();
107 ASSERT_EQ(static_cast<size_t>(test_buffer_
->size() +
108 test_buffer_2_
->size()),
109 socket_data_provider_
.written_data().size());
110 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
111 socket_data_provider_
.written_data().data(),
112 test_buffer_
->size()));
113 EXPECT_EQ(0, memcmp(test_buffer_2_
->data(),
114 socket_data_provider_
.written_data().data() +
115 test_buffer_
->size(),
116 test_buffer_2_
->size()));
119 void TestAppendInCallback() {
120 writer_
->Write(test_buffer_
, base::Bind(
121 base::IgnoreResult(&BufferedSocketWriterBase::Write
),
122 base::Unretained(writer_
.get()), test_buffer_2_
,
124 base::RunLoop().RunUntilIdle();
125 ASSERT_EQ(static_cast<size_t>(test_buffer_
->size() +
126 test_buffer_2_
->size()),
127 socket_data_provider_
.written_data().size());
128 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
129 socket_data_provider_
.written_data().data(),
130 test_buffer_
->size()));
131 EXPECT_EQ(0, memcmp(test_buffer_2_
->data(),
132 socket_data_provider_
.written_data().data() +
133 test_buffer_
->size(),
134 test_buffer_2_
->size()));
137 base::MessageLoop message_loop_
;
138 net::NetLog net_log_
;
139 SocketDataProvider socket_data_provider_
;
140 scoped_ptr
<net::StreamSocket
> socket_
;
141 scoped_ptr
<BufferedSocketWriter
> writer_
;
142 scoped_refptr
<net::IOBufferWithSize
> test_buffer_
;
143 scoped_refptr
<net::IOBufferWithSize
> test_buffer_2_
;
147 // Test synchronous write.
148 TEST_F(BufferedSocketWriterTest
, WriteFull
) {
152 // Test synchronous write in 1k chunks.
153 TEST_F(BufferedSocketWriterTest
, WriteChunks
) {
154 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
158 // Test asynchronous write.
159 TEST_F(BufferedSocketWriterTest
, WriteAsync
) {
160 socket_data_provider_
.set_async_write(true);
161 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
165 // Make sure we can call Write() from the done callback.
166 TEST_F(BufferedSocketWriterTest
, AppendInCallbackSync
) {
167 TestAppendInCallback();
170 // Make sure we can call Write() from the done callback.
171 TEST_F(BufferedSocketWriterTest
, AppendInCallbackAsync
) {
172 socket_data_provider_
.set_async_write(true);
173 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
174 TestAppendInCallback();
177 // Test that the writer can be destroyed from callback.
178 TEST_F(BufferedSocketWriterTest
, DestroyFromCallback
) {
179 socket_data_provider_
.set_async_write(true);
180 writer_
->Write(test_buffer_
, base::Bind(
181 &BufferedSocketWriterTest::DestroyWriter
,
182 base::Unretained(this)));
183 writer_
->Write(test_buffer_2_
, base::Bind(
184 &BufferedSocketWriterTest::Unexpected
,
185 base::Unretained(this)));
186 socket_data_provider_
.set_async_write(false);
187 base::RunLoop().RunUntilIdle();
188 ASSERT_GE(socket_data_provider_
.written_data().size(),
189 static_cast<size_t>(test_buffer_
->size()));
190 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
191 socket_data_provider_
.written_data().data(),
192 test_buffer_
->size()));
195 // Verify that it stops writing after the first error.
196 TEST_F(BufferedSocketWriterTest
, TestWriteErrorSync
) {
197 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
198 writer_
->Write(test_buffer_
, base::Closure());
199 socket_data_provider_
.set_async_write(true);
200 socket_data_provider_
.set_next_write_error(net::ERR_FAILED
);
201 writer_
->Write(test_buffer_2_
,
202 base::Bind(&BufferedSocketWriterTest::Unexpected
,
203 base::Unretained(this)));
204 socket_data_provider_
.set_async_write(false);
205 base::RunLoop().RunUntilIdle();
206 EXPECT_EQ(net::ERR_FAILED
, write_error_
);
207 EXPECT_EQ(static_cast<size_t>(test_buffer_
->size()),
208 socket_data_provider_
.written_data().size());
211 // Verify that it stops writing after the first error.
212 TEST_F(BufferedSocketWriterTest
, TestWriteErrorAsync
) {
213 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
214 writer_
->Write(test_buffer_
, base::Closure());
215 socket_data_provider_
.set_async_write(true);
216 socket_data_provider_
.set_next_write_error(net::ERR_FAILED
);
217 writer_
->Write(test_buffer_2_
,
218 base::Bind(&BufferedSocketWriterTest::Unexpected
,
219 base::Unretained(this)));
220 base::RunLoop().RunUntilIdle();
221 EXPECT_EQ(net::ERR_FAILED
, write_error_
);
222 EXPECT_EQ(static_cast<size_t>(test_buffer_
->size()),
223 socket_data_provider_
.written_data().size());
226 } // namespace remoting