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