blob: 926e927e78bac0461fc8e9bbbfd6ae80759e699c [file] [log] [blame]
mmenkecbc2b712014-10-09 20:29:071// 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.
4
5#include "net/base/chunked_upload_data_stream.h"
6
danakj7f767e62016-04-16 23:20:237#include <memory>
mmenkecbc2b712014-10-09 20:29:078#include <string>
9
mmenkecbc2b712014-10-09 20:29:0710#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"
robpercival214763f2016-07-01 23:27:0114#include "net/test/gtest_util.h"
15#include "testing/gmock/include/gmock/gmock.h"
mmenkecbc2b712014-10-09 20:29:0716#include "testing/gtest/include/gtest/gtest.h"
17
robpercival214763f2016-07-01 23:27:0118using net::test::IsError;
19using net::test::IsOk;
20
mmenkecbc2b712014-10-09 20:29:0721namespace net {
22
23namespace {
24
25const char kTestData[] = "0123456789";
26const size_t kTestDataSize = arraysize(kTestData) - 1;
27const size_t kTestBufferSize = 1 << 14; // 16KB.
28
29} // namespace
30
31// Reads data once from the upload data stream, and returns the data as string.
32// Expects the read to succeed synchronously.
33std::string ReadSync(UploadDataStream* stream, int buffer_size) {
34 scoped_refptr<IOBuffer> buf = new IOBuffer(buffer_size);
35 int result = stream->Read(buf.get(),
36 buffer_size,
37 TestCompletionCallback().callback());
38 EXPECT_GE(result, 0);
39 return std::string(buf->data(), result);
40}
41
42// Check the case data is added after the first read attempt.
43TEST(ChunkedUploadDataStreamTest, AppendOnce) {
44 ChunkedUploadDataStream stream(0);
45
robpercival214763f2016-07-01 23:27:0146 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:0747 EXPECT_FALSE(stream.IsInMemory());
48 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
49 EXPECT_EQ(0u, stream.position());
50 EXPECT_FALSE(stream.IsEOF());
51
52 TestCompletionCallback callback;
53 scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize);
54 int result = stream.Read(buf.get(), kTestBufferSize, callback.callback());
robpercival214763f2016-07-01 23:27:0155 ASSERT_THAT(result, IsError(ERR_IO_PENDING));
mmenkecbc2b712014-10-09 20:29:0756
57 stream.AppendData(kTestData, kTestDataSize, true);
58 int read = callback.WaitForResult();
59 ASSERT_GE(read, 0);
60 EXPECT_EQ(kTestData, std::string(buf->data(), read));
61 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
62 EXPECT_EQ(kTestDataSize, stream.position());
63 EXPECT_TRUE(stream.IsEOF());
64}
65
66TEST(ChunkedUploadDataStreamTest, AppendOnceBeforeRead) {
67 ChunkedUploadDataStream stream(0);
68
robpercival214763f2016-07-01 23:27:0169 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:0770 EXPECT_FALSE(stream.IsInMemory());
71 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
72 EXPECT_EQ(0u, stream.position());
73 EXPECT_FALSE(stream.IsEOF());
74
75 stream.AppendData(kTestData, kTestDataSize, true);
76 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
77 EXPECT_EQ(0u, stream.position());
78 EXPECT_FALSE(stream.IsEOF());
79
80 std::string data = ReadSync(&stream, kTestBufferSize);
81 EXPECT_EQ(kTestData, data);
82 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
83 EXPECT_EQ(kTestDataSize, stream.position());
84 EXPECT_TRUE(stream.IsEOF());
85}
86
87TEST(ChunkedUploadDataStreamTest, AppendOnceBeforeInit) {
88 ChunkedUploadDataStream stream(0);
89
90 stream.AppendData(kTestData, kTestDataSize, true);
robpercival214763f2016-07-01 23:27:0191 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:0792 EXPECT_FALSE(stream.IsInMemory());
93 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
94 EXPECT_EQ(0u, stream.position());
95 EXPECT_FALSE(stream.IsEOF());
96
97 std::string data = ReadSync(&stream, kTestBufferSize);
98 EXPECT_EQ(kTestData, data);
99 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
100 EXPECT_EQ(kTestDataSize, stream.position());
101 EXPECT_TRUE(stream.IsEOF());
102}
103
104TEST(ChunkedUploadDataStreamTest, MultipleAppends) {
105 ChunkedUploadDataStream stream(0);
106
robpercival214763f2016-07-01 23:27:01107 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07108 EXPECT_FALSE(stream.IsInMemory());
109 EXPECT_EQ(0u, stream.size());
110 EXPECT_EQ(0u, stream.position());
111 EXPECT_FALSE(stream.IsEOF());
112
113 TestCompletionCallback callback;
114 scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize);
115 for (size_t i = 0; i < kTestDataSize; ++i) {
116 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
117 EXPECT_EQ(i, stream.position());
118 ASSERT_FALSE(stream.IsEOF());
119 int bytes_read = stream.Read(buf.get(),
120 kTestBufferSize,
121 callback.callback());
robpercival214763f2016-07-01 23:27:01122 ASSERT_THAT(bytes_read, IsError(ERR_IO_PENDING));
mmenkecbc2b712014-10-09 20:29:07123 stream.AppendData(&kTestData[i], 1, i == kTestDataSize - 1);
124 ASSERT_EQ(1, callback.WaitForResult());
125 EXPECT_EQ(kTestData[i], buf->data()[0]);
126 }
127
128 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
129 EXPECT_EQ(kTestDataSize, stream.position());
130 ASSERT_TRUE(stream.IsEOF());
131}
132
133TEST(ChunkedUploadDataStreamTest, MultipleAppendsBetweenReads) {
134 ChunkedUploadDataStream stream(0);
135
robpercival214763f2016-07-01 23:27:01136 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07137 EXPECT_FALSE(stream.IsInMemory());
138 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
139 EXPECT_EQ(0u, stream.position());
140 EXPECT_FALSE(stream.IsEOF());
141
142 scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize);
143 for (size_t i = 0; i < kTestDataSize; ++i) {
144 EXPECT_EQ(i, stream.position());
145 ASSERT_FALSE(stream.IsEOF());
146 stream.AppendData(&kTestData[i], 1, i == kTestDataSize - 1);
147 int bytes_read = stream.Read(buf.get(),
148 kTestBufferSize,
149 TestCompletionCallback().callback());
150 ASSERT_EQ(1, bytes_read);
151 EXPECT_EQ(kTestData[i], buf->data()[0]);
152 }
153
154 EXPECT_EQ(kTestDataSize, stream.position());
155 ASSERT_TRUE(stream.IsEOF());
156}
157
158// Checks that multiple reads can be merged.
159TEST(ChunkedUploadDataStreamTest, MultipleAppendsBeforeInit) {
160 ChunkedUploadDataStream stream(0);
161 stream.AppendData(kTestData, 1, false);
162 stream.AppendData(kTestData + 1, 1, false);
163 stream.AppendData(kTestData + 2, kTestDataSize - 2, true);
164
robpercival214763f2016-07-01 23:27:01165 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07166 EXPECT_FALSE(stream.IsInMemory());
167 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
168 EXPECT_EQ(0u, stream.position());
169 EXPECT_FALSE(stream.IsEOF());
170
171 std::string data = ReadSync(&stream, kTestBufferSize);
172 EXPECT_EQ(kTestData, data);
173 EXPECT_EQ(kTestDataSize, stream.position());
174 ASSERT_TRUE(stream.IsEOF());
175}
176
177TEST(ChunkedUploadDataStreamTest, MultipleReads) {
178 // Use a read size different from the write size to test bounds checking.
179 const size_t kReadSize = kTestDataSize + 3;
180
181 ChunkedUploadDataStream stream(0);
182 stream.AppendData(kTestData, kTestDataSize, false);
183 stream.AppendData(kTestData, kTestDataSize, false);
184 stream.AppendData(kTestData, kTestDataSize, false);
185 stream.AppendData(kTestData, kTestDataSize, true);
186
robpercival214763f2016-07-01 23:27:01187 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07188 EXPECT_FALSE(stream.IsInMemory());
189 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
190 EXPECT_EQ(0u, stream.position());
191 EXPECT_FALSE(stream.IsEOF());
192
193 std::string data = ReadSync(&stream, kReadSize);
194 EXPECT_EQ("0123456789012", data);
195 EXPECT_EQ(kReadSize, stream.position());
196 EXPECT_FALSE(stream.IsEOF());
197
198 data = ReadSync(&stream, kReadSize);
199 EXPECT_EQ("3456789012345", data);
200 EXPECT_EQ(2 * kReadSize, stream.position());
201 EXPECT_FALSE(stream.IsEOF());
202
203 data = ReadSync(&stream, kReadSize);
204 EXPECT_EQ("6789012345678", data);
205 EXPECT_EQ(3 * kReadSize, stream.position());
206 EXPECT_FALSE(stream.IsEOF());
207
208 data = ReadSync(&stream, kReadSize);
209 EXPECT_EQ("9", data);
210 EXPECT_EQ(4 * kTestDataSize, stream.position());
211 EXPECT_TRUE(stream.IsEOF());
212}
213
214TEST(ChunkedUploadDataStreamTest, EmptyUpload) {
215 ChunkedUploadDataStream stream(0);
216
robpercival214763f2016-07-01 23:27:01217 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07218 EXPECT_FALSE(stream.IsInMemory());
219 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
220 EXPECT_EQ(0u, stream.position());
221 EXPECT_FALSE(stream.IsEOF());
222
223 TestCompletionCallback callback;
224 scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize);
225 int result = stream.Read(buf.get(), kTestBufferSize, callback.callback());
robpercival214763f2016-07-01 23:27:01226 ASSERT_THAT(result, IsError(ERR_IO_PENDING));
mmenkecbc2b712014-10-09 20:29:07227
228 stream.AppendData(NULL, 0, true);
229 int read = callback.WaitForResult();
230 EXPECT_EQ(0, read);
231 EXPECT_EQ(0u, stream.position());
232 EXPECT_TRUE(stream.IsEOF());
233}
234
235TEST(ChunkedUploadDataStreamTest, EmptyUploadEndedBeforeInit) {
236 ChunkedUploadDataStream stream(0);
237 stream.AppendData(NULL, 0, true);
238
robpercival214763f2016-07-01 23:27:01239 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07240 EXPECT_FALSE(stream.IsInMemory());
241 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
242 EXPECT_EQ(0u, stream.position());
243 EXPECT_FALSE(stream.IsEOF());
244
245 std::string data = ReadSync(&stream, kTestBufferSize);
246 ASSERT_EQ("", data);
247 EXPECT_EQ(0u, stream.position());
248 EXPECT_TRUE(stream.IsEOF());
249}
250
251TEST(ChunkedUploadDataStreamTest, RewindAfterComplete) {
252 ChunkedUploadDataStream stream(0);
253 stream.AppendData(kTestData, 1, false);
254 stream.AppendData(kTestData + 1, kTestDataSize - 1, true);
255
robpercival214763f2016-07-01 23:27:01256 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07257 EXPECT_FALSE(stream.IsInMemory());
258 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
259 EXPECT_EQ(0u, stream.position());
260 EXPECT_FALSE(stream.IsEOF());
261
262 std::string data = ReadSync(&stream, kTestBufferSize);
263 EXPECT_EQ(kTestData, data);
264 EXPECT_EQ(kTestDataSize, stream.position());
265 ASSERT_TRUE(stream.IsEOF());
266
267 // Rewind stream and repeat.
robpercival214763f2016-07-01 23:27:01268 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07269 EXPECT_FALSE(stream.IsInMemory());
270 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
271 EXPECT_EQ(0u, stream.position());
272 EXPECT_FALSE(stream.IsEOF());
273
274 data = ReadSync(&stream, kTestBufferSize);
275 EXPECT_EQ(kTestData, data);
276 EXPECT_EQ(kTestDataSize, stream.position());
277 ASSERT_TRUE(stream.IsEOF());
278}
279
280TEST(ChunkedUploadDataStreamTest, RewindWhileReading) {
281 ChunkedUploadDataStream stream(0);
282
robpercival214763f2016-07-01 23:27:01283 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07284 EXPECT_FALSE(stream.IsInMemory());
285 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
286 EXPECT_EQ(0u, stream.position());
287 EXPECT_FALSE(stream.IsEOF());
288
289 TestCompletionCallback callback;
290 scoped_refptr<IOBuffer> buf = new IOBuffer(kTestBufferSize);
291 int result = stream.Read(buf.get(), kTestBufferSize, callback.callback());
robpercival214763f2016-07-01 23:27:01292 ASSERT_THAT(result, IsError(ERR_IO_PENDING));
mmenkecbc2b712014-10-09 20:29:07293
robpercival214763f2016-07-01 23:27:01294 ASSERT_THAT(stream.Init(TestCompletionCallback().callback()), IsOk());
mmenkecbc2b712014-10-09 20:29:07295 EXPECT_FALSE(stream.IsInMemory());
296 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data.
297 EXPECT_EQ(0u, stream.position());
298 EXPECT_FALSE(stream.IsEOF());
299
300 // Adding data now should not result in calling the original read callback,
301 // since the stream was re-initialized for reuse, which cancels all pending
302 // reads.
303 stream.AppendData(kTestData, kTestDataSize, true);
304 EXPECT_FALSE(callback.have_result());
305
306 std::string data = ReadSync(&stream, kTestBufferSize);
307 EXPECT_EQ(kTestData, data);
308 EXPECT_EQ(kTestDataSize, stream.position());
309 ASSERT_TRUE(stream.IsEOF());
310 EXPECT_FALSE(callback.have_result());
311}
312
mmenke56b0cbb912016-03-28 21:34:53313// Check the behavior of ChunkedUploadDataStream::Writer.
314TEST(ChunkedUploadDataStreamTest, ChunkedUploadDataStreamWriter) {
danakj7f767e62016-04-16 23:20:23315 std::unique_ptr<ChunkedUploadDataStream> stream(
316 new ChunkedUploadDataStream(0));
317 std::unique_ptr<ChunkedUploadDataStream::Writer> writer(
318 stream->CreateWriter());
mmenke56b0cbb912016-03-28 21:34:53319
320 // Write before Init.
321 ASSERT_TRUE(writer->AppendData(kTestData, 1, false));
robpercival214763f2016-07-01 23:27:01322 ASSERT_THAT(stream->Init(TestCompletionCallback().callback()), IsOk());
mmenke56b0cbb912016-03-28 21:34:53323
324 // Write after Init.
325 ASSERT_TRUE(writer->AppendData(kTestData + 1, kTestDataSize - 1, false));
326
327 TestCompletionCallback callback;
328 std::string data = ReadSync(stream.get(), kTestBufferSize);
329 EXPECT_EQ(kTestData, data);
330
331 // Writing data should gracefully fail if the stream is deleted while still
332 // appending data to it.
333 stream.reset();
334 EXPECT_FALSE(writer->AppendData(kTestData, kTestDataSize, true));
335}
336
mmenkecbc2b712014-10-09 20:29:07337} // namespace net