Upstream version 5.34.104.0
[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 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