1 // Copyright 2014 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 "net/base/chunked_upload_data_stream.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/test_completion_callback.h"
13 #include "net/base/upload_data_stream.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 const char kTestData
[] = "0123456789";
21 const size_t kTestDataSize
= arraysize(kTestData
) - 1;
22 const size_t kTestBufferSize
= 1 << 14; // 16KB.
26 // Reads data once from the upload data stream, and returns the data as string.
27 // Expects the read to succeed synchronously.
28 std::string
ReadSync(UploadDataStream
* stream
, int buffer_size
) {
29 scoped_refptr
<IOBuffer
> buf
= new IOBuffer(buffer_size
);
30 int result
= stream
->Read(buf
.get(),
32 TestCompletionCallback().callback());
34 return std::string(buf
->data(), result
);
37 // Check the case data is added after the first read attempt.
38 TEST(ChunkedUploadDataStreamTest
, AppendOnce
) {
39 ChunkedUploadDataStream
stream(0);
41 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
42 EXPECT_FALSE(stream
.IsInMemory());
43 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
44 EXPECT_EQ(0u, stream
.position());
45 EXPECT_FALSE(stream
.IsEOF());
47 TestCompletionCallback callback
;
48 scoped_refptr
<IOBuffer
> buf
= new IOBuffer(kTestBufferSize
);
49 int result
= stream
.Read(buf
.get(), kTestBufferSize
, callback
.callback());
50 ASSERT_EQ(ERR_IO_PENDING
, result
);
52 stream
.AppendData(kTestData
, kTestDataSize
, true);
53 int read
= callback
.WaitForResult();
55 EXPECT_EQ(kTestData
, std::string(buf
->data(), read
));
56 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
57 EXPECT_EQ(kTestDataSize
, stream
.position());
58 EXPECT_TRUE(stream
.IsEOF());
61 TEST(ChunkedUploadDataStreamTest
, AppendOnceBeforeRead
) {
62 ChunkedUploadDataStream
stream(0);
64 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
65 EXPECT_FALSE(stream
.IsInMemory());
66 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
67 EXPECT_EQ(0u, stream
.position());
68 EXPECT_FALSE(stream
.IsEOF());
70 stream
.AppendData(kTestData
, kTestDataSize
, true);
71 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
72 EXPECT_EQ(0u, stream
.position());
73 EXPECT_FALSE(stream
.IsEOF());
75 std::string data
= ReadSync(&stream
, kTestBufferSize
);
76 EXPECT_EQ(kTestData
, data
);
77 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
78 EXPECT_EQ(kTestDataSize
, stream
.position());
79 EXPECT_TRUE(stream
.IsEOF());
82 TEST(ChunkedUploadDataStreamTest
, AppendOnceBeforeInit
) {
83 ChunkedUploadDataStream
stream(0);
85 stream
.AppendData(kTestData
, kTestDataSize
, true);
86 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
87 EXPECT_FALSE(stream
.IsInMemory());
88 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
89 EXPECT_EQ(0u, stream
.position());
90 EXPECT_FALSE(stream
.IsEOF());
92 std::string data
= ReadSync(&stream
, kTestBufferSize
);
93 EXPECT_EQ(kTestData
, data
);
94 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
95 EXPECT_EQ(kTestDataSize
, stream
.position());
96 EXPECT_TRUE(stream
.IsEOF());
99 TEST(ChunkedUploadDataStreamTest
, MultipleAppends
) {
100 ChunkedUploadDataStream
stream(0);
102 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
103 EXPECT_FALSE(stream
.IsInMemory());
104 EXPECT_EQ(0u, stream
.size());
105 EXPECT_EQ(0u, stream
.position());
106 EXPECT_FALSE(stream
.IsEOF());
108 TestCompletionCallback callback
;
109 scoped_refptr
<IOBuffer
> buf
= new IOBuffer(kTestBufferSize
);
110 for (size_t i
= 0; i
< kTestDataSize
; ++i
) {
111 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
112 EXPECT_EQ(i
, stream
.position());
113 ASSERT_FALSE(stream
.IsEOF());
114 int bytes_read
= stream
.Read(buf
.get(),
116 callback
.callback());
117 ASSERT_EQ(ERR_IO_PENDING
, bytes_read
);
118 stream
.AppendData(&kTestData
[i
], 1, i
== kTestDataSize
- 1);
119 ASSERT_EQ(1, callback
.WaitForResult());
120 EXPECT_EQ(kTestData
[i
], buf
->data()[0]);
123 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
124 EXPECT_EQ(kTestDataSize
, stream
.position());
125 ASSERT_TRUE(stream
.IsEOF());
128 TEST(ChunkedUploadDataStreamTest
, MultipleAppendsBetweenReads
) {
129 ChunkedUploadDataStream
stream(0);
131 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
132 EXPECT_FALSE(stream
.IsInMemory());
133 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
134 EXPECT_EQ(0u, stream
.position());
135 EXPECT_FALSE(stream
.IsEOF());
137 scoped_refptr
<IOBuffer
> buf
= new IOBuffer(kTestBufferSize
);
138 for (size_t i
= 0; i
< kTestDataSize
; ++i
) {
139 EXPECT_EQ(i
, stream
.position());
140 ASSERT_FALSE(stream
.IsEOF());
141 stream
.AppendData(&kTestData
[i
], 1, i
== kTestDataSize
- 1);
142 int bytes_read
= stream
.Read(buf
.get(),
144 TestCompletionCallback().callback());
145 ASSERT_EQ(1, bytes_read
);
146 EXPECT_EQ(kTestData
[i
], buf
->data()[0]);
149 EXPECT_EQ(kTestDataSize
, stream
.position());
150 ASSERT_TRUE(stream
.IsEOF());
153 // Checks that multiple reads can be merged.
154 TEST(ChunkedUploadDataStreamTest
, MultipleAppendsBeforeInit
) {
155 ChunkedUploadDataStream
stream(0);
156 stream
.AppendData(kTestData
, 1, false);
157 stream
.AppendData(kTestData
+ 1, 1, false);
158 stream
.AppendData(kTestData
+ 2, kTestDataSize
- 2, true);
160 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
161 EXPECT_FALSE(stream
.IsInMemory());
162 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
163 EXPECT_EQ(0u, stream
.position());
164 EXPECT_FALSE(stream
.IsEOF());
166 std::string data
= ReadSync(&stream
, kTestBufferSize
);
167 EXPECT_EQ(kTestData
, data
);
168 EXPECT_EQ(kTestDataSize
, stream
.position());
169 ASSERT_TRUE(stream
.IsEOF());
172 TEST(ChunkedUploadDataStreamTest
, MultipleReads
) {
173 // Use a read size different from the write size to test bounds checking.
174 const size_t kReadSize
= kTestDataSize
+ 3;
176 ChunkedUploadDataStream
stream(0);
177 stream
.AppendData(kTestData
, kTestDataSize
, false);
178 stream
.AppendData(kTestData
, kTestDataSize
, false);
179 stream
.AppendData(kTestData
, kTestDataSize
, false);
180 stream
.AppendData(kTestData
, kTestDataSize
, true);
182 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
183 EXPECT_FALSE(stream
.IsInMemory());
184 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
185 EXPECT_EQ(0u, stream
.position());
186 EXPECT_FALSE(stream
.IsEOF());
188 std::string data
= ReadSync(&stream
, kReadSize
);
189 EXPECT_EQ("0123456789012", data
);
190 EXPECT_EQ(kReadSize
, stream
.position());
191 EXPECT_FALSE(stream
.IsEOF());
193 data
= ReadSync(&stream
, kReadSize
);
194 EXPECT_EQ("3456789012345", data
);
195 EXPECT_EQ(2 * kReadSize
, stream
.position());
196 EXPECT_FALSE(stream
.IsEOF());
198 data
= ReadSync(&stream
, kReadSize
);
199 EXPECT_EQ("6789012345678", data
);
200 EXPECT_EQ(3 * kReadSize
, stream
.position());
201 EXPECT_FALSE(stream
.IsEOF());
203 data
= ReadSync(&stream
, kReadSize
);
204 EXPECT_EQ("9", data
);
205 EXPECT_EQ(4 * kTestDataSize
, stream
.position());
206 EXPECT_TRUE(stream
.IsEOF());
209 TEST(ChunkedUploadDataStreamTest
, EmptyUpload
) {
210 ChunkedUploadDataStream
stream(0);
212 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
213 EXPECT_FALSE(stream
.IsInMemory());
214 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
215 EXPECT_EQ(0u, stream
.position());
216 EXPECT_FALSE(stream
.IsEOF());
218 TestCompletionCallback callback
;
219 scoped_refptr
<IOBuffer
> buf
= new IOBuffer(kTestBufferSize
);
220 int result
= stream
.Read(buf
.get(), kTestBufferSize
, callback
.callback());
221 ASSERT_EQ(ERR_IO_PENDING
, result
);
223 stream
.AppendData(NULL
, 0, true);
224 int read
= callback
.WaitForResult();
226 EXPECT_EQ(0u, stream
.position());
227 EXPECT_TRUE(stream
.IsEOF());
230 TEST(ChunkedUploadDataStreamTest
, EmptyUploadEndedBeforeInit
) {
231 ChunkedUploadDataStream
stream(0);
232 stream
.AppendData(NULL
, 0, true);
234 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
235 EXPECT_FALSE(stream
.IsInMemory());
236 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
237 EXPECT_EQ(0u, stream
.position());
238 EXPECT_FALSE(stream
.IsEOF());
240 std::string data
= ReadSync(&stream
, kTestBufferSize
);
242 EXPECT_EQ(0u, stream
.position());
243 EXPECT_TRUE(stream
.IsEOF());
246 TEST(ChunkedUploadDataStreamTest
, RewindAfterComplete
) {
247 ChunkedUploadDataStream
stream(0);
248 stream
.AppendData(kTestData
, 1, false);
249 stream
.AppendData(kTestData
+ 1, kTestDataSize
- 1, true);
251 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
252 EXPECT_FALSE(stream
.IsInMemory());
253 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
254 EXPECT_EQ(0u, stream
.position());
255 EXPECT_FALSE(stream
.IsEOF());
257 std::string data
= ReadSync(&stream
, kTestBufferSize
);
258 EXPECT_EQ(kTestData
, data
);
259 EXPECT_EQ(kTestDataSize
, stream
.position());
260 ASSERT_TRUE(stream
.IsEOF());
262 // Rewind stream and repeat.
263 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
264 EXPECT_FALSE(stream
.IsInMemory());
265 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
266 EXPECT_EQ(0u, stream
.position());
267 EXPECT_FALSE(stream
.IsEOF());
269 data
= ReadSync(&stream
, kTestBufferSize
);
270 EXPECT_EQ(kTestData
, data
);
271 EXPECT_EQ(kTestDataSize
, stream
.position());
272 ASSERT_TRUE(stream
.IsEOF());
275 TEST(ChunkedUploadDataStreamTest
, RewindWhileReading
) {
276 ChunkedUploadDataStream
stream(0);
278 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
279 EXPECT_FALSE(stream
.IsInMemory());
280 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
281 EXPECT_EQ(0u, stream
.position());
282 EXPECT_FALSE(stream
.IsEOF());
284 TestCompletionCallback callback
;
285 scoped_refptr
<IOBuffer
> buf
= new IOBuffer(kTestBufferSize
);
286 int result
= stream
.Read(buf
.get(), kTestBufferSize
, callback
.callback());
287 ASSERT_EQ(ERR_IO_PENDING
, result
);
289 ASSERT_EQ(OK
, stream
.Init(TestCompletionCallback().callback()));
290 EXPECT_FALSE(stream
.IsInMemory());
291 EXPECT_EQ(0u, stream
.size()); // Content-Length is 0 for chunked data.
292 EXPECT_EQ(0u, stream
.position());
293 EXPECT_FALSE(stream
.IsEOF());
295 // Adding data now should not result in calling the original read callback,
296 // since the stream was re-initialized for reuse, which cancels all pending
298 stream
.AppendData(kTestData
, kTestDataSize
, true);
299 EXPECT_FALSE(callback
.have_result());
301 std::string data
= ReadSync(&stream
, kTestBufferSize
);
302 EXPECT_EQ(kTestData
, data
);
303 EXPECT_EQ(kTestDataSize
, stream
.position());
304 ASSERT_TRUE(stream
.IsEOF());
305 EXPECT_FALSE(callback
.have_result());