OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 <vector> | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "testing/gtest/include/gtest/gtest.h" | |
9 #include "third_party/WebKit/public/platform/WebString.h" | |
10 #include "third_party/WebKit/public/platform/WebURL.h" | |
11 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" | |
12 #include "third_party/WebKit/public/platform/WebURLResponse.h" | |
13 #include "webkit/child/multipart_response_delegate.h" | |
14 | |
15 using std::string; | |
16 using blink::WebString; | |
17 using blink::WebURL; | |
18 using blink::WebURLError; | |
19 using blink::WebURLLoader; | |
20 using blink::WebURLLoaderClient; | |
21 using blink::WebURLRequest; | |
22 using blink::WebURLResponse; | |
23 using webkit_glue::MultipartResponseDelegate; | |
24 using webkit_glue::MultipartResponseDelegateTester; | |
25 | |
26 namespace webkit_glue { | |
27 | |
28 class MultipartResponseDelegateTester { | |
29 public: | |
30 MultipartResponseDelegateTester(MultipartResponseDelegate* delegate) | |
31 : delegate_(delegate) { | |
32 } | |
33 | |
34 int PushOverLine(const std::string& data, size_t pos) { | |
35 return delegate_->PushOverLine(data, pos); | |
36 } | |
37 | |
38 bool ParseHeaders() { return delegate_->ParseHeaders(); } | |
39 size_t FindBoundary() { return delegate_->FindBoundary(); } | |
40 std::string& boundary() { return delegate_->boundary_; } | |
41 std::string& data() { return delegate_->data_; } | |
42 | |
43 private: | |
44 MultipartResponseDelegate* delegate_; | |
45 }; | |
46 | |
47 } // namespace webkit_glue | |
48 | |
49 namespace { | |
50 | |
51 class MultipartResponseTest : public testing::Test { | |
52 }; | |
53 | |
54 class MockWebURLLoaderClient : public WebURLLoaderClient { | |
55 public: | |
56 MockWebURLLoaderClient() { Reset(); } | |
57 | |
58 virtual void willSendRequest( | |
59 WebURLLoader*, WebURLRequest&, const WebURLResponse&) {} | |
60 virtual void didSendData( | |
61 WebURLLoader*, unsigned long long, unsigned long long) {} | |
62 | |
63 virtual void didReceiveResponse(WebURLLoader* loader, | |
64 const WebURLResponse& response) { | |
65 ++received_response_; | |
66 response_ = response; | |
67 data_.clear(); | |
68 } | |
69 virtual void didReceiveData( | |
70 blink::WebURLLoader* loader, | |
71 const char* data, | |
72 int data_length, | |
73 int encoded_data_length) { | |
74 ++received_data_; | |
75 data_.append(data, data_length); | |
76 total_encoded_data_length_ += encoded_data_length; | |
77 } | |
78 virtual void didFinishLoading( | |
79 WebURLLoader*, double finishTime, int64_t total_encoded_data_length) {} | |
80 virtual void didFail(WebURLLoader*, const WebURLError&) {} | |
81 | |
82 void Reset() { | |
83 received_response_ = received_data_ = total_encoded_data_length_ = 0; | |
84 data_.clear(); | |
85 response_.reset(); | |
86 } | |
87 | |
88 string GetResponseHeader(const char* name) const { | |
89 return string(response_.httpHeaderField(WebString::fromUTF8(name)).utf8()); | |
90 } | |
91 | |
92 int received_response_, received_data_, total_encoded_data_length_; | |
93 string data_; | |
94 WebURLResponse response_; | |
95 }; | |
96 | |
97 // We can't put this in an anonymous function because it's a friend class for | |
98 // access to private members. | |
99 TEST(MultipartResponseTest, Functions) { | |
100 // PushOverLine tests | |
101 | |
102 WebURLResponse response; | |
103 response.initialize(); | |
104 response.setMIMEType("multipart/x-mixed-replace"); | |
105 response.setHTTPHeaderField("Foo", "Bar"); | |
106 response.setHTTPHeaderField("Content-type", "text/plain"); | |
107 MockWebURLLoaderClient client; | |
108 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
109 MultipartResponseDelegateTester delegate_tester(&delegate); | |
110 | |
111 struct { | |
112 const char* input; | |
113 const int position; | |
114 const int expected; | |
115 } line_tests[] = { | |
116 { "Line", 0, 0 }, | |
117 { "Line", 2, 0 }, | |
118 { "Line", 10, 0 }, | |
119 { "\r\nLine", 0, 2 }, | |
120 { "\nLine", 0, 1 }, | |
121 { "\n\nLine", 0, 2 }, | |
122 { "\rLine", 0, 1 }, | |
123 { "Line\r\nLine", 4, 2 }, | |
124 { "Line\nLine", 4, 1 }, | |
125 { "Line\n\nLine", 4, 2 }, | |
126 { "Line\rLine", 4, 1 }, | |
127 { "Line\r\rLine", 4, 1 }, | |
128 }; | |
129 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(line_tests); ++i) { | |
130 EXPECT_EQ(line_tests[i].expected, | |
131 delegate_tester.PushOverLine(line_tests[i].input, | |
132 line_tests[i].position)); | |
133 } | |
134 | |
135 // ParseHeaders tests | |
136 struct { | |
137 const char* data; | |
138 const bool rv; | |
139 const int received_response_calls; | |
140 const char* newdata; | |
141 } header_tests[] = { | |
142 { "This is junk", false, 0, "This is junk" }, | |
143 { "Foo: bar\nBaz:\n\nAfter:\n", true, 1, "After:\n" }, | |
144 { "Foo: bar\nBaz:\n", false, 0, "Foo: bar\nBaz:\n" }, | |
145 { "Foo: bar\r\nBaz:\r\n\r\nAfter:\r\n", true, 1, "After:\r\n" }, | |
146 { "Foo: bar\r\nBaz:\r\n", false, 0, "Foo: bar\r\nBaz:\r\n" }, | |
147 { "Foo: bar\nBaz:\r\n\r\nAfter:\n\n", true, 1, "After:\n\n" }, | |
148 { "Foo: bar\r\nBaz:\n", false, 0, "Foo: bar\r\nBaz:\n" }, | |
149 { "\r\n", true, 1, "" }, | |
150 }; | |
151 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(header_tests); ++i) { | |
152 client.Reset(); | |
153 delegate_tester.data().assign(header_tests[i].data); | |
154 EXPECT_EQ(header_tests[i].rv, | |
155 delegate_tester.ParseHeaders()); | |
156 EXPECT_EQ(header_tests[i].received_response_calls, | |
157 client.received_response_); | |
158 EXPECT_EQ(string(header_tests[i].newdata), | |
159 delegate_tester.data()); | |
160 } | |
161 // Test that the resource response is filled in correctly when parsing | |
162 // headers. | |
163 client.Reset(); | |
164 string test_header("content-type: image/png\ncontent-length: 10\n\n"); | |
165 delegate_tester.data().assign(test_header); | |
166 EXPECT_TRUE(delegate_tester.ParseHeaders()); | |
167 EXPECT_TRUE(delegate_tester.data().length() == 0); | |
168 EXPECT_EQ(string("image/png"), client.GetResponseHeader("Content-Type")); | |
169 EXPECT_EQ(string("10"), client.GetResponseHeader("content-length")); | |
170 // This header is passed from the original request. | |
171 EXPECT_EQ(string("Bar"), client.GetResponseHeader("foo")); | |
172 | |
173 // Make sure we parse the right mime-type if a charset is provided. | |
174 client.Reset(); | |
175 string test_header2("content-type: text/html; charset=utf-8\n\n"); | |
176 delegate_tester.data().assign(test_header2); | |
177 EXPECT_TRUE(delegate_tester.ParseHeaders()); | |
178 EXPECT_TRUE(delegate_tester.data().length() == 0); | |
179 EXPECT_EQ(string("text/html; charset=utf-8"), | |
180 client.GetResponseHeader("Content-Type")); | |
181 EXPECT_EQ(string("utf-8"), | |
182 string(client.response_.textEncodingName().utf8())); | |
183 | |
184 // FindBoundary tests | |
185 struct { | |
186 const char* boundary; | |
187 const char* data; | |
188 const size_t position; | |
189 } boundary_tests[] = { | |
190 { "bound", "bound", 0 }, | |
191 { "bound", "--bound", 0 }, | |
192 { "bound", "junkbound", 4 }, | |
193 { "bound", "junk--bound", 4 }, | |
194 { "foo", "bound", string::npos }, | |
195 { "bound", "--boundbound", 0 }, | |
196 }; | |
197 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(boundary_tests); ++i) { | |
198 delegate_tester.boundary().assign(boundary_tests[i].boundary); | |
199 delegate_tester.data().assign(boundary_tests[i].data); | |
200 EXPECT_EQ(boundary_tests[i].position, | |
201 delegate_tester.FindBoundary()); | |
202 } | |
203 } | |
204 | |
205 TEST(MultipartResponseTest, MissingBoundaries) { | |
206 WebURLResponse response; | |
207 response.initialize(); | |
208 response.setMIMEType("multipart/x-mixed-replace"); | |
209 response.setHTTPHeaderField("Foo", "Bar"); | |
210 response.setHTTPHeaderField("Content-type", "text/plain"); | |
211 MockWebURLLoaderClient client; | |
212 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
213 | |
214 // No start boundary | |
215 string no_start_boundary( | |
216 "Content-type: text/plain\n\n" | |
217 "This is a sample response\n" | |
218 "--bound--" | |
219 "ignore junk after end token --bound\n\nTest2\n"); | |
220 delegate.OnReceivedData(no_start_boundary.c_str(), | |
221 static_cast<int>(no_start_boundary.length()), | |
222 static_cast<int>(no_start_boundary.length())); | |
223 EXPECT_EQ(1, client.received_response_); | |
224 EXPECT_EQ(1, client.received_data_); | |
225 EXPECT_EQ(string("This is a sample response"), client.data_); | |
226 EXPECT_EQ(static_cast<int>(no_start_boundary.length()), | |
227 client.total_encoded_data_length_); | |
228 | |
229 delegate.OnCompletedRequest(); | |
230 EXPECT_EQ(1, client.received_response_); | |
231 EXPECT_EQ(1, client.received_data_); | |
232 | |
233 // No end boundary | |
234 client.Reset(); | |
235 MultipartResponseDelegate delegate2(&client, NULL, response, "bound"); | |
236 string no_end_boundary( | |
237 "bound\nContent-type: text/plain\n\n" | |
238 "This is a sample response\n"); | |
239 delegate2.OnReceivedData(no_end_boundary.c_str(), | |
240 static_cast<int>(no_end_boundary.length()), | |
241 static_cast<int>(no_end_boundary.length())); | |
242 EXPECT_EQ(1, client.received_response_); | |
243 EXPECT_EQ(1, client.received_data_); | |
244 EXPECT_EQ("This is a sample response\n", client.data_); | |
245 EXPECT_EQ(static_cast<int>(no_end_boundary.length()), | |
246 client.total_encoded_data_length_); | |
247 | |
248 delegate2.OnCompletedRequest(); | |
249 EXPECT_EQ(1, client.received_response_); | |
250 EXPECT_EQ(1, client.received_data_); | |
251 EXPECT_EQ(string("This is a sample response\n"), client.data_); | |
252 EXPECT_EQ(static_cast<int>(no_end_boundary.length()), | |
253 client.total_encoded_data_length_); | |
254 | |
255 // Neither boundary | |
256 client.Reset(); | |
257 MultipartResponseDelegate delegate3(&client, NULL, response, "bound"); | |
258 string no_boundaries( | |
259 "Content-type: text/plain\n\n" | |
260 "This is a sample response\n"); | |
261 delegate3.OnReceivedData(no_boundaries.c_str(), | |
262 static_cast<int>(no_boundaries.length()), | |
263 static_cast<int>(no_boundaries.length())); | |
264 EXPECT_EQ(1, client.received_response_); | |
265 EXPECT_EQ(1, client.received_data_); | |
266 EXPECT_EQ("This is a sample response\n", client.data_); | |
267 EXPECT_EQ(static_cast<int>(no_boundaries.length()), | |
268 client.total_encoded_data_length_); | |
269 | |
270 delegate3.OnCompletedRequest(); | |
271 EXPECT_EQ(1, client.received_response_); | |
272 EXPECT_EQ(1, client.received_data_); | |
273 EXPECT_EQ(string("This is a sample response\n"), client.data_); | |
274 EXPECT_EQ(static_cast<int>(no_boundaries.length()), | |
275 client.total_encoded_data_length_); | |
276 } | |
277 | |
278 TEST(MultipartResponseTest, MalformedBoundary) { | |
279 // Some servers send a boundary that is prefixed by "--". See bug 5786. | |
280 | |
281 WebURLResponse response; | |
282 response.initialize(); | |
283 response.setMIMEType("multipart/x-mixed-replace"); | |
284 response.setHTTPHeaderField("Foo", "Bar"); | |
285 response.setHTTPHeaderField("Content-type", "text/plain"); | |
286 MockWebURLLoaderClient client; | |
287 MultipartResponseDelegate delegate(&client, NULL, response, "--bound"); | |
288 | |
289 string data( | |
290 "--bound\n" | |
291 "Content-type: text/plain\n\n" | |
292 "This is a sample response\n" | |
293 "--bound--" | |
294 "ignore junk after end token --bound\n\nTest2\n"); | |
295 delegate.OnReceivedData(data.c_str(), | |
296 static_cast<int>(data.length()), | |
297 static_cast<int>(data.length())); | |
298 EXPECT_EQ(1, client.received_response_); | |
299 EXPECT_EQ(1, client.received_data_); | |
300 EXPECT_EQ(string("This is a sample response"), client.data_); | |
301 EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_); | |
302 | |
303 delegate.OnCompletedRequest(); | |
304 EXPECT_EQ(1, client.received_response_); | |
305 EXPECT_EQ(1, client.received_data_); | |
306 } | |
307 | |
308 | |
309 // Used in for tests that break the data in various places. | |
310 struct TestChunk { | |
311 const int start_pos; // offset in data | |
312 const int end_pos; // end offset in data | |
313 const int expected_responses; | |
314 const int expected_received_data; | |
315 const char* expected_data; | |
316 const int expected_encoded_data_length; | |
317 }; | |
318 | |
319 void VariousChunkSizesTest(const TestChunk chunks[], int chunks_size, | |
320 int responses, int received_data, | |
321 const char* completed_data, | |
322 int completed_encoded_data_length) { | |
323 const string data( | |
324 "--bound\n" // 0-7 | |
325 "Content-type: image/png\n\n" // 8-32 | |
326 "datadatadatadatadata" // 33-52 | |
327 "--bound\n" // 53-60 | |
328 "Content-type: image/jpg\n\n" // 61-85 | |
329 "foofoofoofoofoo" // 86-100 | |
330 "--bound--"); // 101-109 | |
331 | |
332 WebURLResponse response; | |
333 response.initialize(); | |
334 response.setMIMEType("multipart/x-mixed-replace"); | |
335 MockWebURLLoaderClient client; | |
336 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
337 | |
338 for (int i = 0; i < chunks_size; ++i) { | |
339 ASSERT_TRUE(chunks[i].start_pos < chunks[i].end_pos); | |
340 string chunk = data.substr(chunks[i].start_pos, | |
341 chunks[i].end_pos - chunks[i].start_pos); | |
342 delegate.OnReceivedData( | |
343 chunk.c_str(), | |
344 static_cast<int>(chunk.length()), | |
345 static_cast<int>(chunk.length())); | |
346 EXPECT_EQ(chunks[i].expected_responses, client.received_response_); | |
347 EXPECT_EQ(chunks[i].expected_received_data, client.received_data_); | |
348 EXPECT_EQ(string(chunks[i].expected_data), client.data_); | |
349 EXPECT_EQ(chunks[i].expected_encoded_data_length, | |
350 client.total_encoded_data_length_); | |
351 } | |
352 // Check final state | |
353 delegate.OnCompletedRequest(); | |
354 EXPECT_EQ(responses, client.received_response_); | |
355 EXPECT_EQ(received_data, client.received_data_); | |
356 string completed_data_string(completed_data); | |
357 EXPECT_EQ(completed_data_string, client.data_); | |
358 EXPECT_EQ(completed_encoded_data_length, client.total_encoded_data_length_); | |
359 } | |
360 | |
361 TEST(MultipartResponseTest, BreakInBoundary) { | |
362 // Break in the first boundary | |
363 const TestChunk bound1[] = { | |
364 { 0, 4, 0, 0, "", 0 }, | |
365 { 4, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
366 }; | |
367 VariousChunkSizesTest(bound1, arraysize(bound1), | |
368 2, 2, "foofoofoofoofoo", 110); | |
369 | |
370 // Break in first and second | |
371 const TestChunk bound2[] = { | |
372 { 0, 4, 0, 0, "", 0 }, | |
373 { 4, 55, 1, 1, "datadatadatadat", 55 }, | |
374 { 55, 65, 1, 2, "datadatadatadatadata", 65 }, | |
375 { 65, 110, 2, 3, "foofoofoofoofoo", 110 }, | |
376 }; | |
377 VariousChunkSizesTest(bound2, arraysize(bound2), | |
378 2, 3, "foofoofoofoofoo", 110); | |
379 | |
380 // Break in second only | |
381 const TestChunk bound3[] = { | |
382 { 0, 55, 1, 1, "datadatadatadat", 55 }, | |
383 { 55, 110, 2, 3, "foofoofoofoofoo", 110 }, | |
384 }; | |
385 VariousChunkSizesTest(bound3, arraysize(bound3), | |
386 2, 3, "foofoofoofoofoo", 110); | |
387 } | |
388 | |
389 TEST(MultipartResponseTest, BreakInHeaders) { | |
390 // Break in first header | |
391 const TestChunk header1[] = { | |
392 { 0, 10, 0, 0, "", 0 }, | |
393 { 10, 35, 1, 0, "", 0 }, | |
394 { 35, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
395 }; | |
396 VariousChunkSizesTest(header1, arraysize(header1), | |
397 2, 2, "foofoofoofoofoo", 110); | |
398 | |
399 // Break in both headers | |
400 const TestChunk header2[] = { | |
401 { 0, 10, 0, 0, "", 0 }, | |
402 { 10, 65, 1, 1, "datadatadatadatadata", 65 }, | |
403 { 65, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
404 }; | |
405 VariousChunkSizesTest(header2, arraysize(header2), | |
406 2, 2, "foofoofoofoofoo", 110); | |
407 | |
408 // Break at end of a header | |
409 const TestChunk header3[] = { | |
410 { 0, 33, 1, 0, "", 0 }, | |
411 { 33, 65, 1, 1, "datadatadatadatadata", 65 }, | |
412 { 65, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
413 }; | |
414 VariousChunkSizesTest(header3, arraysize(header3), | |
415 2, 2, "foofoofoofoofoo", 110); | |
416 } | |
417 | |
418 TEST(MultipartResponseTest, BreakInData) { | |
419 // All data as one chunk | |
420 const TestChunk data1[] = { | |
421 { 0, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
422 }; | |
423 VariousChunkSizesTest(data1, arraysize(data1), | |
424 2, 2, "foofoofoofoofoo", 110); | |
425 | |
426 // breaks in data segment | |
427 const TestChunk data2[] = { | |
428 { 0, 35, 1, 0, "", 0 }, | |
429 { 35, 65, 1, 1, "datadatadatadatadata", 65 }, | |
430 { 65, 90, 2, 1, "", 65 }, | |
431 { 90, 110, 2, 2, "foofoofoofoofoo", 110 }, | |
432 }; | |
433 VariousChunkSizesTest(data2, arraysize(data2), | |
434 2, 2, "foofoofoofoofoo", 110); | |
435 | |
436 // Incomplete send | |
437 const TestChunk data3[] = { | |
438 { 0, 35, 1, 0, "", 0 }, | |
439 { 35, 90, 2, 1, "", 90 }, | |
440 }; | |
441 VariousChunkSizesTest(data3, arraysize(data3), | |
442 2, 2, "foof", 90); | |
443 } | |
444 | |
445 TEST(MultipartResponseTest, SmallChunk) { | |
446 WebURLResponse response; | |
447 response.initialize(); | |
448 response.setMIMEType("multipart/x-mixed-replace"); | |
449 response.setHTTPHeaderField("Content-type", "text/plain"); | |
450 MockWebURLLoaderClient client; | |
451 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
452 | |
453 // Test chunks of size 1, 2, and 0. | |
454 string data( | |
455 "--boundContent-type: text/plain\n\n" | |
456 "\n--boundContent-type: text/plain\n\n" | |
457 "\n\n--boundContent-type: text/plain\n\n" | |
458 "--boundContent-type: text/plain\n\n" | |
459 "end--bound--"); | |
460 delegate.OnReceivedData(data.c_str(), | |
461 static_cast<int>(data.length()), | |
462 static_cast<int>(data.length())); | |
463 EXPECT_EQ(4, client.received_response_); | |
464 EXPECT_EQ(2, client.received_data_); | |
465 EXPECT_EQ(string("end"), client.data_); | |
466 EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_); | |
467 | |
468 delegate.OnCompletedRequest(); | |
469 EXPECT_EQ(4, client.received_response_); | |
470 EXPECT_EQ(2, client.received_data_); | |
471 } | |
472 | |
473 TEST(MultipartResponseTest, MultipleBoundaries) { | |
474 // Test multiple boundaries back to back | |
475 WebURLResponse response; | |
476 response.initialize(); | |
477 response.setMIMEType("multipart/x-mixed-replace"); | |
478 MockWebURLLoaderClient client; | |
479 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
480 | |
481 string data("--bound\r\n\r\n--bound\r\n\r\nfoofoo--bound--"); | |
482 delegate.OnReceivedData(data.c_str(), | |
483 static_cast<int>(data.length()), | |
484 static_cast<int>(data.length())); | |
485 EXPECT_EQ(2, client.received_response_); | |
486 EXPECT_EQ(1, client.received_data_); | |
487 EXPECT_EQ(string("foofoo"), client.data_); | |
488 EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_); | |
489 } | |
490 | |
491 TEST(MultipartResponseTest, MultipartByteRangeParsingTest) { | |
492 // Test multipart/byteranges based boundary parsing. | |
493 WebURLResponse response1; | |
494 response1.initialize(); | |
495 response1.setMIMEType("multipart/x-mixed-replace"); | |
496 response1.setHTTPHeaderField("Content-Length", "200"); | |
497 response1.setHTTPHeaderField("Content-type", | |
498 "multipart/byteranges; boundary=--bound--"); | |
499 | |
500 std::string multipart_boundary; | |
501 bool result = MultipartResponseDelegate::ReadMultipartBoundary( | |
502 response1, &multipart_boundary); | |
503 EXPECT_EQ(result, true); | |
504 EXPECT_EQ(string("--bound--"), | |
505 multipart_boundary); | |
506 | |
507 WebURLResponse response2; | |
508 response2.initialize(); | |
509 response2.setMIMEType("image/png"); | |
510 | |
511 response2.setHTTPHeaderField("Content-Length", "300"); | |
512 response2.setHTTPHeaderField("Last-Modified", | |
513 "Mon, 04 Apr 2005 20:36:01 GMT"); | |
514 response2.setHTTPHeaderField("Date", "Thu, 11 Sep 2008 18:21:42 GMT"); | |
515 | |
516 multipart_boundary.clear(); | |
517 result = MultipartResponseDelegate::ReadMultipartBoundary( | |
518 response2, &multipart_boundary); | |
519 EXPECT_EQ(result, false); | |
520 | |
521 WebURLResponse response3; | |
522 response3.initialize(); | |
523 response3.setMIMEType("multipart/byteranges"); | |
524 | |
525 response3.setHTTPHeaderField("Content-Length", "300"); | |
526 response3.setHTTPHeaderField("Last-Modified", | |
527 "Mon, 04 Apr 2005 20:36:01 GMT"); | |
528 response3.setHTTPHeaderField("Date", "Thu, 11 Sep 2008 18:21:42 GMT"); | |
529 response3.setHTTPHeaderField("Content-type", "multipart/byteranges"); | |
530 | |
531 multipart_boundary.clear(); | |
532 result = MultipartResponseDelegate::ReadMultipartBoundary( | |
533 response3, &multipart_boundary); | |
534 EXPECT_EQ(result, false); | |
535 EXPECT_EQ(multipart_boundary.length(), 0U); | |
536 | |
537 WebURLResponse response4; | |
538 response4.initialize(); | |
539 response4.setMIMEType("multipart/byteranges"); | |
540 response4.setHTTPHeaderField("Content-Length", "200"); | |
541 response4.setHTTPHeaderField("Content-type", | |
542 "multipart/byteranges; boundary=--bound--; charSet=utf8"); | |
543 | |
544 multipart_boundary.clear(); | |
545 | |
546 result = MultipartResponseDelegate::ReadMultipartBoundary( | |
547 response4, &multipart_boundary); | |
548 EXPECT_EQ(result, true); | |
549 EXPECT_EQ(string("--bound--"), multipart_boundary); | |
550 | |
551 WebURLResponse response5; | |
552 response5.initialize(); | |
553 response5.setMIMEType("multipart/byteranges"); | |
554 response5.setHTTPHeaderField("Content-Length", "200"); | |
555 response5.setHTTPHeaderField("Content-type", | |
556 "multipart/byteranges; boundary=\"--bound--\"; charSet=utf8"); | |
557 | |
558 multipart_boundary.clear(); | |
559 | |
560 result = MultipartResponseDelegate::ReadMultipartBoundary( | |
561 response5, &multipart_boundary); | |
562 EXPECT_EQ(result, true); | |
563 EXPECT_EQ(string("--bound--"), multipart_boundary); | |
564 } | |
565 | |
566 TEST(MultipartResponseTest, MultipartContentRangesTest) { | |
567 WebURLResponse response1; | |
568 response1.initialize(); | |
569 response1.setMIMEType("application/pdf"); | |
570 response1.setHTTPHeaderField("Content-Length", "200"); // Ignored! | |
571 // Use intentionally >32bit values to check they are handled correctly. | |
572 response1.setHTTPHeaderField("Content-Range", | |
573 "bytes 5000000000-5000000050/6000000000"); | |
574 | |
575 int64 content_range_lower_bound = 0; | |
576 int64 content_range_upper_bound = 0; | |
577 int64 content_range_instance_size = 0; | |
578 | |
579 bool result = MultipartResponseDelegate::ReadContentRanges( | |
580 response1, &content_range_lower_bound, | |
581 &content_range_upper_bound, | |
582 &content_range_instance_size); | |
583 | |
584 EXPECT_EQ(result, true); | |
585 EXPECT_EQ(content_range_lower_bound, 5e9); | |
586 EXPECT_EQ(content_range_upper_bound, 5e9+50); | |
587 EXPECT_EQ(content_range_instance_size, 6e9); | |
588 | |
589 WebURLResponse response2; | |
590 response2.initialize(); | |
591 response2.setMIMEType("application/pdf"); | |
592 response2.setHTTPHeaderField("Content-Length", "200"); | |
593 response2.setHTTPHeaderField("Content-Range", "bytes 1000/1050"); | |
594 | |
595 content_range_lower_bound = 0; | |
596 content_range_upper_bound = 0; | |
597 content_range_instance_size = 0; | |
598 | |
599 result = MultipartResponseDelegate::ReadContentRanges( | |
600 response2, &content_range_lower_bound, | |
601 &content_range_upper_bound, | |
602 &content_range_instance_size); | |
603 | |
604 EXPECT_EQ(result, false); | |
605 | |
606 WebURLResponse response3; | |
607 response3.initialize(); | |
608 response3.setMIMEType("application/pdf"); | |
609 response3.setHTTPHeaderField("Content-Length", "200"); | |
610 response3.setHTTPHeaderField("Range", "bytes 1000-1050/5000"); | |
611 | |
612 content_range_lower_bound = 0; | |
613 content_range_upper_bound = 0; | |
614 content_range_instance_size = 0; | |
615 | |
616 result = MultipartResponseDelegate::ReadContentRanges( | |
617 response3, &content_range_lower_bound, | |
618 &content_range_upper_bound, | |
619 &content_range_instance_size); | |
620 | |
621 EXPECT_EQ(result, true); | |
622 EXPECT_EQ(content_range_lower_bound, 1000); | |
623 EXPECT_EQ(content_range_upper_bound, 1050); | |
624 | |
625 WebURLResponse response4; | |
626 response4.initialize(); | |
627 response4.setMIMEType("application/pdf"); | |
628 response4.setHTTPHeaderField("Content-Length", "200"); | |
629 | |
630 content_range_lower_bound = 0; | |
631 content_range_upper_bound = 0; | |
632 content_range_instance_size = 0; | |
633 | |
634 result = MultipartResponseDelegate::ReadContentRanges( | |
635 response4, &content_range_lower_bound, | |
636 &content_range_upper_bound, | |
637 &content_range_instance_size); | |
638 | |
639 EXPECT_EQ(result, false); | |
640 } | |
641 | |
642 TEST(MultipartResponseTest, MultipartPayloadSet) { | |
643 WebURLResponse response; | |
644 response.initialize(); | |
645 response.setMIMEType("multipart/x-mixed-replace"); | |
646 MockWebURLLoaderClient client; | |
647 MultipartResponseDelegate delegate(&client, NULL, response, "bound"); | |
648 | |
649 string data( | |
650 "--bound\n" | |
651 "Content-type: text/plain\n\n" | |
652 "response data\n" | |
653 "--bound\n"); | |
654 delegate.OnReceivedData(data.c_str(), | |
655 static_cast<int>(data.length()), | |
656 static_cast<int>(data.length())); | |
657 EXPECT_EQ(1, client.received_response_); | |
658 EXPECT_EQ(string("response data"), client.data_); | |
659 EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_); | |
660 EXPECT_FALSE(client.response_.isMultipartPayload()); | |
661 | |
662 string data2( | |
663 "Content-type: text/plain\n\n" | |
664 "response data2\n" | |
665 "--bound\n"); | |
666 delegate.OnReceivedData(data2.c_str(), | |
667 static_cast<int>(data2.length()), | |
668 static_cast<int>(data2.length())); | |
669 EXPECT_EQ(2, client.received_response_); | |
670 EXPECT_EQ(string("response data2"), client.data_); | |
671 EXPECT_EQ(static_cast<int>(data.length()) + static_cast<int>(data2.length()), | |
672 client.total_encoded_data_length_); | |
673 EXPECT_TRUE(client.response_.isMultipartPayload()); | |
674 } | |
675 | |
676 } // namespace | |
OLD | NEW |