| 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 "content/child/multipart_response_delegate.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <vector> | |
| 11 | |
| 12 #include "base/macros.h" | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | |
| 14 #include "third_party/WebKit/public/platform/WebString.h" | |
| 15 #include "third_party/WebKit/public/platform/WebURL.h" | |
| 16 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" | |
| 17 #include "third_party/WebKit/public/platform/WebURLResponse.h" | |
| 18 | |
| 19 using blink::WebString; | |
| 20 using blink::WebURL; | |
| 21 using blink::WebURLError; | |
| 22 using blink::WebURLLoader; | |
| 23 using blink::WebURLLoaderClient; | |
| 24 using blink::WebURLRequest; | |
| 25 using blink::WebURLResponse; | |
| 26 using std::string; | |
| 27 | |
| 28 namespace content { | |
| 29 | |
| 30 class MultipartResponseDelegateTester { | |
| 31 public: | |
| 32 MultipartResponseDelegateTester(MultipartResponseDelegate* delegate) | |
| 33 : delegate_(delegate) { | |
| 34 } | |
| 35 | |
| 36 int PushOverLine(const std::string& data, size_t pos) { | |
| 37 return delegate_->PushOverLine(data, pos); | |
| 38 } | |
| 39 | |
| 40 bool ParseHeaders() { return delegate_->ParseHeaders(); } | |
| 41 size_t FindBoundary() { return delegate_->FindBoundary(); } | |
| 42 std::string& boundary() { return delegate_->boundary_; } | |
| 43 std::string& data() { return delegate_->data_; } | |
| 44 | |
| 45 private: | |
| 46 MultipartResponseDelegate* delegate_; | |
| 47 }; | |
| 48 | |
| 49 namespace { | |
| 50 | |
| 51 class MultipartResponseTest : public testing::Test { | |
| 52 }; | |
| 53 | |
| 54 class MockWebURLLoaderClient : public WebURLLoaderClient { | |
| 55 public: | |
| 56 MockWebURLLoaderClient() { Reset(); } | |
| 57 | |
| 58 void willFollowRedirect(WebURLLoader*, | |
| 59 WebURLRequest&, | |
| 60 const WebURLResponse&) override {} | |
| 61 void didSendData(WebURLLoader*, | |
| 62 unsigned long long, | |
| 63 unsigned long long) override {} | |
| 64 | |
| 65 void didReceiveResponse(WebURLLoader* loader, | |
| 66 const WebURLResponse& response) override { | |
| 67 ++received_response_; | |
| 68 response_ = response; | |
| 69 data_.clear(); | |
| 70 } | |
| 71 void didReceiveData(blink::WebURLLoader* loader, | |
| 72 const char* data, | |
| 73 int data_length, | |
| 74 int encoded_data_length) override { | |
| 75 ++received_data_; | |
| 76 data_.append(data, data_length); | |
| 77 total_encoded_data_length_ += encoded_data_length; | |
| 78 } | |
| 79 void didFinishLoading(WebURLLoader*, | |
| 80 double finishTime, | |
| 81 int64_t total_encoded_data_length) override {} | |
| 82 void didFail(WebURLLoader*, const WebURLError&) override {} | |
| 83 | |
| 84 void Reset() { | |
| 85 received_response_ = received_data_ = total_encoded_data_length_ = 0; | |
| 86 data_.clear(); | |
| 87 response_.reset(); | |
| 88 } | |
| 89 | |
| 90 string GetResponseHeader(const char* name) const { | |
| 91 return string(response_.httpHeaderField(WebString::fromUTF8(name)).utf8()); | |
| 92 } | |
| 93 | |
| 94 int received_response_, received_data_, total_encoded_data_length_; | |
| 95 string data_; | |
| 96 WebURLResponse response_; | |
| 97 }; | |
| 98 | |
| 99 // We can't put this in an anonymous function because it's a friend class for | |
| 100 // access to private members. | |
| 101 TEST(MultipartResponseTest, Functions) { | |
| 102 // PushOverLine tests | |
| 103 | |
| 104 WebURLResponse response; | |
| 105 response.initialize(); | |
| 106 response.setMIMEType("multipart/x-mixed-replace"); | |
| 107 response.setHTTPHeaderField("Foo", "Bar"); | |
| 108 response.setHTTPHeaderField("Content-type", "text/plain"); | |
| 109 MockWebURLLoaderClient client; | |
| 110 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
| 111 MultipartResponseDelegateTester delegate_tester(&delegate); | |
| 112 | |
| 113 struct { | |
| 114 const char* input; | |
| 115 const int position; | |
| 116 const int expected; | |
| 117 } line_tests[] = { | |
| 118 { "Line", 0, 0 }, | |
| 119 { "Line", 2, 0 }, | |
| 120 { "Line", 10, 0 }, | |
| 121 { "\r\nLine", 0, 2 }, | |
| 122 { "\nLine", 0, 1 }, | |
| 123 { "\n\nLine", 0, 2 }, | |
| 124 { "\rLine", 0, 1 }, | |
| 125 { "Line\r\nLine", 4, 2 }, | |
| 126 { "Line\nLine", 4, 1 }, | |
| 127 { "Line\n\nLine", 4, 2 }, | |
| 128 { "Line\rLine", 4, 1 }, | |
| 129 { "Line\r\rLine", 4, 1 }, | |
| 130 }; | |
| 131 for (size_t i = 0; i < arraysize(line_tests); ++i) { | |
| 132 EXPECT_EQ(line_tests[i].expected, | |
| 133 delegate_tester.PushOverLine(line_tests[i].input, | |
| 134 line_tests[i].position)); | |
| 135 } | |
| 136 | |
| 137 // ParseHeaders tests | |
| 138 struct { | |
| 139 const char* data; | |
| 140 const bool rv; | |
| 141 const int received_response_calls; | |
| 142 const char* newdata; | |
| 143 } header_tests[] = { | |
| 144 { "This is junk", false, 0, "This is junk" }, | |
| 145 { "Foo: bar\nBaz:\n\nAfter:\n", true, 1, "After:\n" }, | |
| 146 { "Foo: bar\nBaz:\n", false, 0, "Foo: bar\nBaz:\n" }, | |
| 147 { "Foo: bar\r\nBaz:\r\n\r\nAfter:\r\n", true, 1, "After:\r\n" }, | |
| 148 { "Foo: bar\r\nBaz:\r\n", false, 0, "Foo: bar\r\nBaz:\r\n" }, | |
| 149 { "Foo: bar\nBaz:\r\n\r\nAfter:\n\n", true, 1, "After:\n\n" }, | |
| 150 { "Foo: bar\r\nBaz:\n", false, 0, "Foo: bar\r\nBaz:\n" }, | |
| 151 { "\r\n", true, 1, "" }, | |
| 152 }; | |
| 153 for (size_t i = 0; i < arraysize(header_tests); ++i) { | |
| 154 client.Reset(); | |
| 155 delegate_tester.data().assign(header_tests[i].data); | |
| 156 EXPECT_EQ(header_tests[i].rv, | |
| 157 delegate_tester.ParseHeaders()); | |
| 158 EXPECT_EQ(header_tests[i].received_response_calls, | |
| 159 client.received_response_); | |
| 160 EXPECT_EQ(string(header_tests[i].newdata), | |
| 161 delegate_tester.data()); | |
| 162 } | |
| 163 // Test that the resource response is filled in correctly when parsing | |
| 164 // headers. | |
| 165 client.Reset(); | |
| 166 string test_header("content-type: image/png\ncontent-length: 10\n\n"); | |
| 167 delegate_tester.data().assign(test_header); | |
| 168 EXPECT_TRUE(delegate_tester.ParseHeaders()); | |
| 169 EXPECT_TRUE(delegate_tester.data().length() == 0); | |
| 170 EXPECT_EQ(string("image/png"), client.GetResponseHeader("Content-Type")); | |
| 171 EXPECT_EQ(string("10"), client.GetResponseHeader("content-length")); | |
| 172 // This header is passed from the original request. | |
| 173 EXPECT_EQ(string("Bar"), client.GetResponseHeader("foo")); | |
| 174 | |
| 175 // Make sure we parse the right mime-type if a charset is provided. | |
| 176 client.Reset(); | |
| 177 string test_header2("content-type: text/html; charset=utf-8\n\n"); | |
| 178 delegate_tester.data().assign(test_header2); | |
| 179 EXPECT_TRUE(delegate_tester.ParseHeaders()); | |
| 180 EXPECT_TRUE(delegate_tester.data().length() == 0); | |
| 181 EXPECT_EQ(string("text/html; charset=utf-8"), | |
| 182 client.GetResponseHeader("Content-Type")); | |
| 183 EXPECT_EQ(string("utf-8"), | |
| 184 string(client.response_.textEncodingName().utf8())); | |
| 185 | |
| 186 // FindBoundary tests | |
| 187 struct { | |
| 188 const char* boundary; | |
| 189 const char* data; | |
| 190 const size_t position; | |
| 191 } boundary_tests[] = { | |
| 192 { "bound", "bound", 0 }, | |
| 193 { "bound", "--bound", 0 }, | |
| 194 { "bound", "junkbound", 4 }, | |
| 195 { "bound", "junk--bound", 4 }, | |
| 196 { "foo", "bound", string::npos }, | |
| 197 { "bound", "--boundbound", 0 }, | |
| 198 }; | |
| 199 for (size_t i = 0; i < arraysize(boundary_tests); ++i) { | |
| 200 delegate_tester.boundary().assign(boundary_tests[i].boundary); | |
| 201 delegate_tester.data().assign(boundary_tests[i].data); | |
| 202 EXPECT_EQ(boundary_tests[i].position, | |
| 203 delegate_tester.FindBoundary()); | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 TEST(MultipartResponseTest, MissingBoundaries) { | |
| 208 WebURLResponse response; | |
| 209 response.initialize(); | |
| 210 response.setMIMEType("multipart/x-mixed-replace"); | |
| 211 response.setHTTPHeaderField("Foo", "Bar"); | |
| 212 response.setHTTPHeaderField("Content-type", "text/plain"); | |
| 213 MockWebURLLoaderClient client; | |
| 214 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
| 215 | |
| 216 // No start boundary | |
| 217 string no_start_boundary( | |
| 218 "Content-type: text/plain\n\n" | |
| 219 "This is a sample response\n" | |
| 220 "--bound--" | |
| 221 "ignore junk after end token --bound\n\nTest2\n"); | |
| 222 delegate.OnReceivedData(no_start_boundary.c_str(), | |
| 223 static_cast<int>(no_start_boundary.length()), | |
| 224 static_cast<int>(no_start_boundary.length())); | |
| 225 EXPECT_EQ(1, client.received_response_); | |
| 226 EXPECT_EQ(1, client.received_data_); | |
| 227 EXPECT_EQ(string("This is a sample response"), client.data_); | |
| 228 EXPECT_EQ(static_cast<int>(no_start_boundary.length()), | |
| 229 client.total_encoded_data_length_); | |
| 230 | |
| 231 delegate.OnCompletedRequest(); | |
| 232 EXPECT_EQ(1, client.received_response_); | |
| 233 EXPECT_EQ(1, client.received_data_); | |
| 234 | |
| 235 // No end boundary | |
| 236 client.Reset(); | |
| 237 MultipartResponseDelegate delegate2(&client, NULL, response, "bound"); | |
| 238 string no_end_boundary( | |
| 239 "bound\nContent-type: text/plain\n\n" | |
| 240 "This is a sample response\n"); | |
| 241 delegate2.OnReceivedData(no_end_boundary.c_str(), | |
| 242 static_cast<int>(no_end_boundary.length()), | |
| 243 static_cast<int>(no_end_boundary.length())); | |
| 244 EXPECT_EQ(1, client.received_response_); | |
| 245 EXPECT_EQ(1, client.received_data_); | |
| 246 EXPECT_EQ("This is a sample response\n", client.data_); | |
| 247 EXPECT_EQ(static_cast<int>(no_end_boundary.length()), | |
| 248 client.total_encoded_data_length_); | |
| 249 | |
| 250 delegate2.OnCompletedRequest(); | |
| 251 EXPECT_EQ(1, client.received_response_); | |
| 252 EXPECT_EQ(1, client.received_data_); | |
| 253 EXPECT_EQ(string("This is a sample response\n"), client.data_); | |
| 254 EXPECT_EQ(static_cast<int>(no_end_boundary.length()), | |
| 255 client.total_encoded_data_length_); | |
| 256 | |
| 257 // Neither boundary | |
| 258 client.Reset(); | |
| 259 MultipartResponseDelegate delegate3(&client, NULL, response, "bound"); | |
| 260 string no_boundaries( | |
| 261 "Content-type: text/plain\n\n" | |
| 262 "This is a sample response\n"); | |
| 263 delegate3.OnReceivedData(no_boundaries.c_str(), | |
| 264 static_cast<int>(no_boundaries.length()), | |
| 265 static_cast<int>(no_boundaries.length())); | |
| 266 EXPECT_EQ(1, client.received_response_); | |
| 267 EXPECT_EQ(1, client.received_data_); | |
| 268 EXPECT_EQ("This is a sample response\n", client.data_); | |
| 269 EXPECT_EQ(static_cast<int>(no_boundaries.length()), | |
| 270 client.total_encoded_data_length_); | |
| 271 | |
| 272 delegate3.OnCompletedRequest(); | |
| 273 EXPECT_EQ(1, client.received_response_); | |
| 274 EXPECT_EQ(1, client.received_data_); | |
| 275 EXPECT_EQ(string("This is a sample response\n"), client.data_); | |
| 276 EXPECT_EQ(static_cast<int>(no_boundaries.length()), | |
| 277 client.total_encoded_data_length_); | |
| 278 } | |
| 279 | |
| 280 TEST(MultipartResponseTest, MalformedBoundary) { | |
| 281 // Some servers send a boundary that is prefixed by "--". See bug 5786. | |
| 282 | |
| 283 WebURLResponse response; | |
| 284 response.initialize(); | |
| 285 response.setMIMEType("multipart/x-mixed-replace"); | |
| 286 response.setHTTPHeaderField("Foo", "Bar"); | |
| 287 response.setHTTPHeaderField("Content-type", "text/plain"); | |
| 288 MockWebURLLoaderClient client; | |
| 289 MultipartResponseDelegate delegate(&client, NULL, response, "--bound"); | |
| 290 | |
| 291 string data( | |
| 292 "--bound\n" | |
| 293 "Content-type: text/plain\n\n" | |
| 294 "This is a sample response\n" | |
| 295 "--bound--" | |
| 296 "ignore junk after end token --bound\n\nTest2\n"); | |
| 297 delegate.OnReceivedData(data.c_str(), | |
| 298 static_cast<int>(data.length()), | |
| 299 static_cast<int>(data.length())); | |
| 300 EXPECT_EQ(1, client.received_response_); | |
| 301 EXPECT_EQ(1, client.received_data_); | |
| 302 EXPECT_EQ(string("This is a sample response"), client.data_); | |
| 303 EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_); | |
| 304 | |
| 305 delegate.OnCompletedRequest(); | |
| 306 EXPECT_EQ(1, client.received_response_); | |
| 307 EXPECT_EQ(1, client.received_data_); | |
| 308 } | |
| 309 | |
| 310 | |
| 311 // Used in for tests that break the data in various places. | |
| 312 struct TestChunk { | |
| 313 const int start_pos; // offset in data | |
| 314 const int end_pos; // end offset in data | |
| 315 const int expected_responses; | |
| 316 const int expected_received_data; | |
| 317 const char* expected_data; | |
| 318 const int expected_encoded_data_length; | |
| 319 }; | |
| 320 | |
| 321 void VariousChunkSizesTest(const TestChunk chunks[], int chunks_size, | |
| 322 int responses, int received_data, | |
| 323 const char* completed_data, | |
| 324 int completed_encoded_data_length) { | |
| 325 const string data( | |
| 326 "--bound\n" // 0-7 | |
| 327 "Content-type: image/png\n\n" // 8-32 | |
| 328 "datadatadatadatadata" // 33-52 | |
| 329 "--bound\n" // 53-60 | |
| 330 "Content-type: image/jpg\n\n" // 61-85 | |
| 331 "foofoofoofoofoo" // 86-100 | |
| 332 "--bound--"); // 101-109 | |
| 333 | |
| 334 WebURLResponse response; | |
| 335 response.initialize(); | |
| 336 response.setMIMEType("multipart/x-mixed-replace"); | |
| 337 MockWebURLLoaderClient client; | |
| 338 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
| 339 | |
| 340 for (int i = 0; i < chunks_size; ++i) { | |
| 341 ASSERT_TRUE(chunks[i].start_pos < chunks[i].end_pos); | |
| 342 string chunk = data.substr(chunks[i].start_pos, | |
| 343 chunks[i].end_pos - chunks[i].start_pos); | |
| 344 delegate.OnReceivedData( | |
| 345 chunk.c_str(), | |
| 346 static_cast<int>(chunk.length()), | |
| 347 static_cast<int>(chunk.length())); | |
| 348 EXPECT_EQ(chunks[i].expected_responses, client.received_response_); | |
| 349 EXPECT_EQ(chunks[i].expected_received_data, client.received_data_); | |
| 350 EXPECT_EQ(string(chunks[i].expected_data), client.data_); | |
| 351 EXPECT_EQ(chunks[i].expected_encoded_data_length, | |
| 352 client.total_encoded_data_length_); | |
| 353 } | |
| 354 // Check final state | |
| 355 delegate.OnCompletedRequest(); | |
| 356 EXPECT_EQ(responses, client.received_response_); | |
| 357 EXPECT_EQ(received_data, client.received_data_); | |
| 358 string completed_data_string(completed_data); | |
| 359 EXPECT_EQ(completed_data_string, client.data_); | |
| 360 EXPECT_EQ(completed_encoded_data_length, client.total_encoded_data_length_); | |
| 361 } | |
| 362 | |
| 363 TEST(MultipartResponseTest, BreakInBoundary) { | |
| 364 // Break in the first boundary | |
| 365 const TestChunk bound1[] = { | |
| 366 { 0, 4, 0, 0, "", 0 }, | |
| 367 { 4, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
| 368 }; | |
| 369 VariousChunkSizesTest(bound1, arraysize(bound1), | |
| 370 2, 2, "foofoofoofoofoo", 110); | |
| 371 | |
| 372 // Break in first and second | |
| 373 const TestChunk bound2[] = { | |
| 374 { 0, 4, 0, 0, "", 0 }, | |
| 375 { 4, 55, 1, 1, "datadatadatadat", 55 }, | |
| 376 { 55, 65, 1, 2, "datadatadatadatadata", 65 }, | |
| 377 { 65, 110, 2, 3, "foofoofoofoofoo", 110 }, | |
| 378 }; | |
| 379 VariousChunkSizesTest(bound2, arraysize(bound2), | |
| 380 2, 3, "foofoofoofoofoo", 110); | |
| 381 | |
| 382 // Break in second only | |
| 383 const TestChunk bound3[] = { | |
| 384 { 0, 55, 1, 1, "datadatadatadat", 55 }, | |
| 385 { 55, 110, 2, 3, "foofoofoofoofoo", 110 }, | |
| 386 }; | |
| 387 VariousChunkSizesTest(bound3, arraysize(bound3), | |
| 388 2, 3, "foofoofoofoofoo", 110); | |
| 389 } | |
| 390 | |
| 391 TEST(MultipartResponseTest, BreakInHeaders) { | |
| 392 // Break in first header | |
| 393 const TestChunk header1[] = { | |
| 394 { 0, 10, 0, 0, "", 0 }, | |
| 395 { 10, 35, 1, 0, "", 0 }, | |
| 396 { 35, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
| 397 }; | |
| 398 VariousChunkSizesTest(header1, arraysize(header1), | |
| 399 2, 2, "foofoofoofoofoo", 110); | |
| 400 | |
| 401 // Break in both headers | |
| 402 const TestChunk header2[] = { | |
| 403 { 0, 10, 0, 0, "", 0 }, | |
| 404 { 10, 65, 1, 1, "datadatadatadatadata", 65 }, | |
| 405 { 65, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
| 406 }; | |
| 407 VariousChunkSizesTest(header2, arraysize(header2), | |
| 408 2, 2, "foofoofoofoofoo", 110); | |
| 409 | |
| 410 // Break at end of a header | |
| 411 const TestChunk header3[] = { | |
| 412 { 0, 33, 1, 0, "", 0 }, | |
| 413 { 33, 65, 1, 1, "datadatadatadatadata", 65 }, | |
| 414 { 65, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
| 415 }; | |
| 416 VariousChunkSizesTest(header3, arraysize(header3), | |
| 417 2, 2, "foofoofoofoofoo", 110); | |
| 418 } | |
| 419 | |
| 420 TEST(MultipartResponseTest, BreakInData) { | |
| 421 // All data as one chunk | |
| 422 const TestChunk data1[] = { | |
| 423 { 0, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
| 424 }; | |
| 425 VariousChunkSizesTest(data1, arraysize(data1), | |
| 426 2, 2, "foofoofoofoofoo", 110); | |
| 427 | |
| 428 // breaks in data segment | |
| 429 const TestChunk data2[] = { | |
| 430 { 0, 35, 1, 0, "", 0 }, | |
| 431 { 35, 65, 1, 1, "datadatadatadatadata", 65 }, | |
| 432 { 65, 90, 2, 1, "", 65 }, | |
| 433 { 90, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
| 434 }; | |
| 435 VariousChunkSizesTest(data2, arraysize(data2), | |
| 436 2, 2, "foofoofoofoofoo", 110); | |
| 437 | |
| 438 // Incomplete send | |
| 439 const TestChunk data3[] = { | |
| 440 { 0, 35, 1, 0, "", 0 }, | |
| 441 { 35, 90, 2, 1, "", 90 }, | |
| 442 }; | |
| 443 VariousChunkSizesTest(data3, arraysize(data3), | |
| 444 2, 2, "foof", 90); | |
| 445 } | |
| 446 | |
| 447 TEST(MultipartResponseTest, SmallChunk) { | |
| 448 WebURLResponse response; | |
| 449 response.initialize(); | |
| 450 response.setMIMEType("multipart/x-mixed-replace"); | |
| 451 response.setHTTPHeaderField("Content-type", "text/plain"); | |
| 452 MockWebURLLoaderClient client; | |
| 453 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
| 454 | |
| 455 // Test chunks of size 1, 2, and 0. | |
| 456 string data( | |
| 457 "--boundContent-type: text/plain\n\n" | |
| 458 "\n--boundContent-type: text/plain\n\n" | |
| 459 "\n\n--boundContent-type: text/plain\n\n" | |
| 460 "--boundContent-type: text/plain\n\n" | |
| 461 "end--bound--"); | |
| 462 delegate.OnReceivedData(data.c_str(), | |
| 463 static_cast<int>(data.length()), | |
| 464 static_cast<int>(data.length())); | |
| 465 EXPECT_EQ(4, client.received_response_); | |
| 466 EXPECT_EQ(2, client.received_data_); | |
| 467 EXPECT_EQ(string("end"), client.data_); | |
| 468 EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_); | |
| 469 | |
| 470 delegate.OnCompletedRequest(); | |
| 471 EXPECT_EQ(4, client.received_response_); | |
| 472 EXPECT_EQ(2, client.received_data_); | |
| 473 } | |
| 474 | |
| 475 TEST(MultipartResponseTest, MultipleBoundaries) { | |
| 476 // Test multiple boundaries back to back | |
| 477 WebURLResponse response; | |
| 478 response.initialize(); | |
| 479 response.setMIMEType("multipart/x-mixed-replace"); | |
| 480 MockWebURLLoaderClient client; | |
| 481 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
| 482 | |
| 483 string data("--bound\r\n\r\n--bound\r\n\r\nfoofoo--bound--"); | |
| 484 delegate.OnReceivedData(data.c_str(), | |
| 485 static_cast<int>(data.length()), | |
| 486 static_cast<int>(data.length())); | |
| 487 EXPECT_EQ(2, client.received_response_); | |
| 488 EXPECT_EQ(1, client.received_data_); | |
| 489 EXPECT_EQ(string("foofoo"), client.data_); | |
| 490 EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_); | |
| 491 } | |
| 492 | |
| 493 TEST(MultipartResponseTest, MultipartPayloadSet) { | |
| 494 WebURLResponse response; | |
| 495 response.initialize(); | |
| 496 response.setMIMEType("multipart/x-mixed-replace"); | |
| 497 MockWebURLLoaderClient client; | |
| 498 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
| 499 | |
| 500 string data( | |
| 501 "--bound\n" | |
| 502 "Content-type: text/plain\n\n" | |
| 503 "response data\n" | |
| 504 "--bound\n"); | |
| 505 delegate.OnReceivedData(data.c_str(), | |
| 506 static_cast<int>(data.length()), | |
| 507 static_cast<int>(data.length())); | |
| 508 EXPECT_EQ(1, client.received_response_); | |
| 509 EXPECT_EQ(string("response data"), client.data_); | |
| 510 EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_); | |
| 511 EXPECT_FALSE(client.response_.isMultipartPayload()); | |
| 512 | |
| 513 string data2( | |
| 514 "Content-type: text/plain\n\n" | |
| 515 "response data2\n" | |
| 516 "--bound\n"); | |
| 517 delegate.OnReceivedData(data2.c_str(), | |
| 518 static_cast<int>(data2.length()), | |
| 519 static_cast<int>(data2.length())); | |
| 520 EXPECT_EQ(2, client.received_response_); | |
| 521 EXPECT_EQ(string("response data2"), client.data_); | |
| 522 EXPECT_EQ(static_cast<int>(data.length()) + static_cast<int>(data2.length()), | |
| 523 client.total_encoded_data_length_); | |
| 524 EXPECT_TRUE(client.response_.isMultipartPayload()); | |
| 525 } | |
| 526 | |
| 527 } // namespace | |
| 528 | |
| 529 } // namespace content | |
| OLD | NEW |