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