OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "net/base/chunked_upload_data_stream.h" | |
6 | |
7 #include <string> | |
8 | |
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" | |
15 | |
16 namespace net { | |
17 | |
18 namespace { | |
19 | |
20 const char kTestData[] = "0123456789"; | |
21 const size_t kTestDataSize = arraysize(kTestData) - 1; | |
22 const size_t kTestBufferSize = 1 << 14; // 16KB. | |
23 | |
24 } // namespace | |
25 | |
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(), | |
31 buffer_size, | |
32 TestCompletionCallback().callback()); | |
33 EXPECT_GE(result, 0); | |
34 return std::string(buf->data(), result); | |
35 } | |
36 | |
37 // Check the case data is added after the first read attempt. | |
38 TEST(ChunkedUploadDataStreamTest, AppendOnce) { | |
39 ChunkedUploadDataStream stream(0); | |
40 | |
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()); | |
46 | |
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); | |
51 | |
52 stream.AppendData(kTestData, kTestDataSize, true); | |
53 int read = callback.WaitForResult(); | |
54 ASSERT_GE(read, 0); | |
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()); | |
59 } | |
60 | |
61 TEST(ChunkedUploadDataStreamTest, AppendOnceBeforeRead) { | |
62 ChunkedUploadDataStream stream(0); | |
63 | |
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()); | |
69 | |
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()); | |
74 | |
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()); | |
80 } | |
81 | |
82 TEST(ChunkedUploadDataStreamTest, AppendOnceBeforeInit) { | |
83 ChunkedUploadDataStream stream(0); | |
84 | |
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()); | |
91 | |
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()); | |
97 } | |
98 | |
99 TEST(ChunkedUploadDataStreamTest, MultipleAppends) { | |
100 ChunkedUploadDataStream stream(0); | |
101 | |
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()); | |
107 | |
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(), | |
115 kTestBufferSize, | |
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]); | |
121 } | |
122 | |
123 EXPECT_EQ(0u, stream.size()); // Content-Length is 0 for chunked data. | |
124 EXPECT_EQ(kTestDataSize, stream.position()); | |
125 ASSERT_TRUE(stream.IsEOF()); | |
126 } | |
127 | |
128 TEST(ChunkedUploadDataStreamTest, MultipleAppendsBetweenReads) { | |
129 ChunkedUploadDataStream stream(0); | |
130 | |
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()); | |
136 | |
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(), | |
143 kTestBufferSize, | |
144 TestCompletionCallback().callback()); | |
145 ASSERT_EQ(1, bytes_read); | |
146 EXPECT_EQ(kTestData[i], buf->data()[0]); | |
147 } | |
148 | |
149 EXPECT_EQ(kTestDataSize, stream.position()); | |
150 ASSERT_TRUE(stream.IsEOF()); | |
151 } | |
152 | |
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); | |
159 | |
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()); | |
165 | |
166 std::string data = ReadSync(&stream, kTestBufferSize); | |
167 EXPECT_EQ(kTestData, data); | |
168 EXPECT_EQ(kTestDataSize, stream.position()); | |
169 ASSERT_TRUE(stream.IsEOF()); | |
170 } | |
171 | |
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; | |
175 | |
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); | |
181 | |
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()); | |
187 | |
188 std::string data = ReadSync(&stream, kReadSize); | |
189 EXPECT_EQ("0123456789012", data); | |
190 EXPECT_EQ(kReadSize, stream.position()); | |
191 EXPECT_FALSE(stream.IsEOF()); | |
192 | |
193 data = ReadSync(&stream, kReadSize); | |
194 EXPECT_EQ("3456789012345", data); | |
195 EXPECT_EQ(2 * kReadSize, stream.position()); | |
196 EXPECT_FALSE(stream.IsEOF()); | |
197 | |
198 data = ReadSync(&stream, kReadSize); | |
199 EXPECT_EQ("6789012345678", data); | |
200 EXPECT_EQ(3 * kReadSize, stream.position()); | |
201 EXPECT_FALSE(stream.IsEOF()); | |
202 | |
203 data = ReadSync(&stream, kReadSize); | |
204 EXPECT_EQ("9", data); | |
205 EXPECT_EQ(4 * kTestDataSize, stream.position()); | |
206 EXPECT_TRUE(stream.IsEOF()); | |
207 } | |
208 | |
209 TEST(ChunkedUploadDataStreamTest, EmptyUpload) { | |
210 ChunkedUploadDataStream stream(0); | |
211 | |
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()); | |
217 | |
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); | |
222 | |
223 stream.AppendData(NULL, 0, true); | |
224 int read = callback.WaitForResult(); | |
225 EXPECT_EQ(0, read); | |
226 EXPECT_EQ(0u, stream.position()); | |
227 EXPECT_TRUE(stream.IsEOF()); | |
228 } | |
229 | |
230 TEST(ChunkedUploadDataStreamTest, EmptyUploadEndedBeforeInit) { | |
231 ChunkedUploadDataStream stream(0); | |
232 stream.AppendData(NULL, 0, true); | |
233 | |
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()); | |
239 | |
240 std::string data = ReadSync(&stream, kTestBufferSize); | |
241 ASSERT_EQ("", data); | |
242 EXPECT_EQ(0u, stream.position()); | |
243 EXPECT_TRUE(stream.IsEOF()); | |
244 } | |
245 | |
246 TEST(ChunkedUploadDataStreamTest, RewindAfterComplete) { | |
247 ChunkedUploadDataStream stream(0); | |
248 stream.AppendData(kTestData, 1, false); | |
249 stream.AppendData(kTestData + 1, kTestDataSize - 1, true); | |
250 | |
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()); | |
256 | |
257 std::string data = ReadSync(&stream, kTestBufferSize); | |
258 EXPECT_EQ(kTestData, data); | |
259 EXPECT_EQ(kTestDataSize, stream.position()); | |
260 ASSERT_TRUE(stream.IsEOF()); | |
261 | |
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()); | |
268 | |
269 data = ReadSync(&stream, kTestBufferSize); | |
270 EXPECT_EQ(kTestData, data); | |
271 EXPECT_EQ(kTestDataSize, stream.position()); | |
272 ASSERT_TRUE(stream.IsEOF()); | |
273 } | |
274 | |
275 TEST(ChunkedUploadDataStreamTest, RewindWhileReading) { | |
276 ChunkedUploadDataStream stream(0); | |
277 | |
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()); | |
283 | |
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); | |
288 | |
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()); | |
294 | |
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 | |
297 // reads. | |
298 stream.AppendData(kTestData, kTestDataSize, true); | |
299 EXPECT_FALSE(callback.have_result()); | |
300 | |
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()); | |
306 } | |
307 | |
308 } // namespace net | |
OLD | NEW |