| 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 |