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
OnRead() 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 bool AllReadDataConsumed() const override
{
52 bool AllWriteDataConsumed() const override
{
56 void Reset() override
{}
58 std::string
written_data() { return written_data_
; }
60 void set_write_limit(int limit
) { write_limit_
= limit
; }
61 void set_async_write(bool async_write
) { async_write_
= async_write
; }
62 void set_next_write_error(int error
) { next_write_error_
= error
; }
65 std::string written_data_
;
68 int next_write_error_
;
73 class BufferedSocketWriterTest
: public testing::Test
{
75 BufferedSocketWriterTest()
79 void DestroyWriter() {
89 void SetUp() override
{
90 socket_
.reset(new net::MockTCPClientSocket(net::AddressList(), &net_log_
,
91 &socket_data_provider_
));
92 socket_data_provider_
.set_connect_data(
93 net::MockConnect(net::SYNCHRONOUS
, net::OK
));
94 EXPECT_EQ(net::OK
, socket_
->Connect(net::CompletionCallback()));
96 writer_
.reset(new BufferedSocketWriter());
97 writer_
->Init(socket_
.get(), base::Bind(
98 &BufferedSocketWriterTest::OnWriteFailed
, base::Unretained(this)));
99 test_buffer_
= new net::IOBufferWithSize(kTestBufferSize
);
100 test_buffer_2_
= new net::IOBufferWithSize(kTestBufferSize
);
101 for (int i
= 0; i
< kTestBufferSize
; ++i
) {
102 test_buffer_
->data()[i
] = rand() % 256;
103 test_buffer_2_
->data()[i
] = rand() % 256;
107 void OnWriteFailed(int error
) {
108 write_error_
= error
;
112 writer_
->Write(test_buffer_
, base::Closure());
113 writer_
->Write(test_buffer_2_
, base::Closure());
114 base::RunLoop().RunUntilIdle();
115 ASSERT_EQ(static_cast<size_t>(test_buffer_
->size() +
116 test_buffer_2_
->size()),
117 socket_data_provider_
.written_data().size());
118 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
119 socket_data_provider_
.written_data().data(),
120 test_buffer_
->size()));
121 EXPECT_EQ(0, memcmp(test_buffer_2_
->data(),
122 socket_data_provider_
.written_data().data() +
123 test_buffer_
->size(),
124 test_buffer_2_
->size()));
127 void TestAppendInCallback() {
128 writer_
->Write(test_buffer_
, base::Bind(
129 base::IgnoreResult(&BufferedSocketWriterBase::Write
),
130 base::Unretained(writer_
.get()), test_buffer_2_
,
132 base::RunLoop().RunUntilIdle();
133 ASSERT_EQ(static_cast<size_t>(test_buffer_
->size() +
134 test_buffer_2_
->size()),
135 socket_data_provider_
.written_data().size());
136 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
137 socket_data_provider_
.written_data().data(),
138 test_buffer_
->size()));
139 EXPECT_EQ(0, memcmp(test_buffer_2_
->data(),
140 socket_data_provider_
.written_data().data() +
141 test_buffer_
->size(),
142 test_buffer_2_
->size()));
145 base::MessageLoop message_loop_
;
146 net::NetLog net_log_
;
147 SocketDataProvider socket_data_provider_
;
148 scoped_ptr
<net::StreamSocket
> socket_
;
149 scoped_ptr
<BufferedSocketWriter
> writer_
;
150 scoped_refptr
<net::IOBufferWithSize
> test_buffer_
;
151 scoped_refptr
<net::IOBufferWithSize
> test_buffer_2_
;
155 // Test synchronous write.
156 TEST_F(BufferedSocketWriterTest
, WriteFull
) {
160 // Test synchronous write in 1k chunks.
161 TEST_F(BufferedSocketWriterTest
, WriteChunks
) {
162 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
166 // Test asynchronous write.
167 TEST_F(BufferedSocketWriterTest
, WriteAsync
) {
168 socket_data_provider_
.set_async_write(true);
169 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
173 // Make sure we can call Write() from the done callback.
174 TEST_F(BufferedSocketWriterTest
, AppendInCallbackSync
) {
175 TestAppendInCallback();
178 // Make sure we can call Write() from the done callback.
179 TEST_F(BufferedSocketWriterTest
, AppendInCallbackAsync
) {
180 socket_data_provider_
.set_async_write(true);
181 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
182 TestAppendInCallback();
185 // Test that the writer can be destroyed from callback.
186 TEST_F(BufferedSocketWriterTest
, DestroyFromCallback
) {
187 socket_data_provider_
.set_async_write(true);
188 writer_
->Write(test_buffer_
, base::Bind(
189 &BufferedSocketWriterTest::DestroyWriter
,
190 base::Unretained(this)));
191 writer_
->Write(test_buffer_2_
, base::Bind(
192 &BufferedSocketWriterTest::Unexpected
,
193 base::Unretained(this)));
194 socket_data_provider_
.set_async_write(false);
195 base::RunLoop().RunUntilIdle();
196 ASSERT_GE(socket_data_provider_
.written_data().size(),
197 static_cast<size_t>(test_buffer_
->size()));
198 EXPECT_EQ(0, memcmp(test_buffer_
->data(),
199 socket_data_provider_
.written_data().data(),
200 test_buffer_
->size()));
203 // Verify that it stops writing after the first error.
204 TEST_F(BufferedSocketWriterTest
, TestWriteErrorSync
) {
205 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
206 writer_
->Write(test_buffer_
, base::Closure());
207 socket_data_provider_
.set_async_write(true);
208 socket_data_provider_
.set_next_write_error(net::ERR_FAILED
);
209 writer_
->Write(test_buffer_2_
,
210 base::Bind(&BufferedSocketWriterTest::Unexpected
,
211 base::Unretained(this)));
212 socket_data_provider_
.set_async_write(false);
213 base::RunLoop().RunUntilIdle();
214 EXPECT_EQ(net::ERR_FAILED
, write_error_
);
215 EXPECT_EQ(static_cast<size_t>(test_buffer_
->size()),
216 socket_data_provider_
.written_data().size());
219 // Verify that it stops writing after the first error.
220 TEST_F(BufferedSocketWriterTest
, TestWriteErrorAsync
) {
221 socket_data_provider_
.set_write_limit(kWriteChunkSize
);
222 writer_
->Write(test_buffer_
, base::Closure());
223 socket_data_provider_
.set_async_write(true);
224 socket_data_provider_
.set_next_write_error(net::ERR_FAILED
);
225 writer_
->Write(test_buffer_2_
,
226 base::Bind(&BufferedSocketWriterTest::Unexpected
,
227 base::Unretained(this)));
228 base::RunLoop().RunUntilIdle();
229 EXPECT_EQ(net::ERR_FAILED
, write_error_
);
230 EXPECT_EQ(static_cast<size_t>(test_buffer_
->size()),
231 socket_data_provider_
.written_data().size());
234 } // namespace remoting