Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / buffered_resource_loader_unittest.cc
1 // Copyright 2013 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 <algorithm>
6 #include <string>
7
8 #include "base/bind.h"
9 #include "base/format_macros.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "content/renderer/media/buffered_resource_loader.h"
13 #include "content/test/mock_webframeclient.h"
14 #include "content/test/mock_weburlloader.h"
15 #include "media/base/media_log.h"
16 #include "media/base/seekable_buffer.h"
17 #include "net/base/net_errors.h"
18 #include "net/http/http_request_headers.h"
19 #include "net/http/http_util.h"
20 #include "third_party/WebKit/public/platform/WebString.h"
21 #include "third_party/WebKit/public/platform/WebURLError.h"
22 #include "third_party/WebKit/public/platform/WebURLRequest.h"
23 #include "third_party/WebKit/public/platform/WebURLResponse.h"
24 #include "third_party/WebKit/public/web/WebLocalFrame.h"
25 #include "third_party/WebKit/public/web/WebView.h"
26
27 using ::testing::_;
28 using ::testing::InSequence;
29 using ::testing::Return;
30 using ::testing::Truly;
31 using ::testing::NiceMock;
32
33 using blink::WebLocalFrame;
34 using blink::WebString;
35 using blink::WebURLError;
36 using blink::WebURLResponse;
37 using blink::WebView;
38
39 namespace content {
40
41 static const char* kHttpUrl = "http://test";
42 static const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing";
43 static const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2";
44 static const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2";
45
46 static const int kDataSize = 1024;
47 static const int kHttpOK = 200;
48 static const int kHttpPartialContent = 206;
49
50 enum NetworkState {
51   NONE,
52   LOADED,
53   LOADING
54 };
55
56 // Predicate that tests that request disallows compressed data.
57 static bool CorrectAcceptEncoding(const blink::WebURLRequest &request) {
58   std::string value = request.httpHeaderField(
59       WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding)).utf8();
60   return (value.find("identity;q=1") != std::string::npos) &&
61          (value.find("*;q=0") != std::string::npos);
62 }
63
64 class BufferedResourceLoaderTest : public testing::Test {
65  public:
66   BufferedResourceLoaderTest()
67       : view_(WebView::create(NULL)), frame_(WebLocalFrame::create(&client_)) {
68     view_->setMainFrame(frame_);
69
70     for (int i = 0; i < kDataSize; ++i) {
71       data_[i] = i;
72     }
73   }
74
75   virtual ~BufferedResourceLoaderTest() {
76     view_->close();
77     frame_->close();
78   }
79
80   void Initialize(const char* url, int first_position, int last_position) {
81     gurl_ = GURL(url);
82     first_position_ = first_position;
83     last_position_ = last_position;
84
85     loader_.reset(new BufferedResourceLoader(
86         gurl_, BufferedResourceLoader::kUnspecified,
87         first_position_, last_position_,
88         BufferedResourceLoader::kCapacityDefer, 0, 0,
89         new media::MediaLog()));
90
91     // |test_loader_| will be used when Start() is called.
92     url_loader_ = new NiceMock<MockWebURLLoader>();
93     loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_);
94   }
95
96   void SetLoaderBuffer(int forward_capacity, int backward_capacity) {
97     loader_->buffer_.set_forward_capacity(forward_capacity);
98     loader_->buffer_.set_backward_capacity(backward_capacity);
99     loader_->buffer_.Clear();
100   }
101
102   void Start() {
103     InSequence s;
104     EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding),
105                                                  loader_.get()));
106
107     EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
108     loader_->Start(
109         base::Bind(&BufferedResourceLoaderTest::StartCallback,
110                    base::Unretained(this)),
111         base::Bind(&BufferedResourceLoaderTest::LoadingCallback,
112                    base::Unretained(this)),
113         base::Bind(&BufferedResourceLoaderTest::ProgressCallback,
114                    base::Unretained(this)),
115         view_->mainFrame());
116   }
117
118   void FullResponse(int64 instance_size) {
119     FullResponse(instance_size, BufferedResourceLoader::kOk);
120   }
121
122   void FullResponse(int64 instance_size,
123                     BufferedResourceLoader::Status status) {
124     EXPECT_CALL(*this, StartCallback(status));
125
126     WebURLResponse response(gurl_);
127     response.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
128                                 WebString::fromUTF8(base::StringPrintf("%"
129                                     PRId64, instance_size)));
130     response.setExpectedContentLength(instance_size);
131     response.setHTTPStatusCode(kHttpOK);
132     loader_->didReceiveResponse(url_loader_, response);
133
134     if (status == BufferedResourceLoader::kOk) {
135       EXPECT_EQ(instance_size, loader_->content_length());
136       EXPECT_EQ(instance_size, loader_->instance_size());
137     }
138
139     EXPECT_FALSE(loader_->range_supported());
140   }
141
142   void PartialResponse(int64 first_position, int64 last_position,
143                        int64 instance_size) {
144     PartialResponse(first_position, last_position, instance_size, false, true);
145   }
146
147   void PartialResponse(int64 first_position, int64 last_position,
148                        int64 instance_size, bool chunked, bool accept_ranges) {
149     EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kOk));
150
151     WebURLResponse response(gurl_);
152     response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
153                                 WebString::fromUTF8(base::StringPrintf("bytes "
154                                             "%" PRId64 "-%" PRId64 "/%" PRId64,
155                                             first_position,
156                                             last_position,
157                                             instance_size)));
158
159     // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked.
160     int64 content_length = -1;
161     if (chunked) {
162       response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"),
163                                   WebString::fromUTF8("chunked"));
164     } else {
165       content_length = last_position - first_position + 1;
166     }
167     response.setExpectedContentLength(content_length);
168
169     // A server isn't required to return Accept-Ranges even though it might.
170     if (accept_ranges) {
171       response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
172                                   WebString::fromUTF8("bytes"));
173     }
174
175     response.setHTTPStatusCode(kHttpPartialContent);
176     loader_->didReceiveResponse(url_loader_, response);
177
178     // XXX: what's the difference between these two? For example in the chunked
179     // range request case, Content-Length is unspecified (because it's chunked)
180     // but Content-Range: a-b/c can be returned, where c == Content-Length
181     //
182     // Can we eliminate one?
183     EXPECT_EQ(content_length, loader_->content_length());
184     EXPECT_EQ(instance_size, loader_->instance_size());
185
186     // A valid partial response should always result in this being true.
187     EXPECT_TRUE(loader_->range_supported());
188   }
189
190   void Redirect(const char* url) {
191     GURL redirectUrl(url);
192     blink::WebURLRequest newRequest(redirectUrl);
193     blink::WebURLResponse redirectResponse(gurl_);
194
195     loader_->willSendRequest(url_loader_, newRequest, redirectResponse);
196
197     base::MessageLoop::current()->RunUntilIdle();
198   }
199
200   void StopWhenLoad() {
201     InSequence s;
202     EXPECT_CALL(*url_loader_, cancel());
203     loader_->Stop();
204     loader_.reset();
205   }
206
207   // Helper method to write to |loader_| from |data_|.
208   void WriteLoader(int position, int size) {
209     EXPECT_CALL(*this, ProgressCallback(position + size - 1));
210     loader_->didReceiveData(url_loader_,
211                             reinterpret_cast<char*>(data_ + position),
212                             size,
213                             size);
214   }
215
216   void WriteData(int size) {
217     EXPECT_CALL(*this, ProgressCallback(_));
218
219     scoped_ptr<char[]> data(new char[size]);
220     loader_->didReceiveData(url_loader_, data.get(), size, size);
221   }
222
223   void WriteUntilThreshold() {
224     int buffered = loader_->buffer_.forward_bytes();
225     int capacity = loader_->buffer_.forward_capacity();
226     CHECK_LT(buffered, capacity);
227
228     EXPECT_CALL(*this, LoadingCallback(
229         BufferedResourceLoader::kLoadingDeferred));
230     WriteData(capacity - buffered);
231   }
232
233   // Helper method to read from |loader_|.
234   void ReadLoader(int64 position, int size, uint8* buffer) {
235     loader_->Read(position, size, buffer,
236                   base::Bind(&BufferedResourceLoaderTest::ReadCallback,
237                              base::Unretained(this)));
238   }
239
240   // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size].
241   void VerifyBuffer(uint8* buffer, int pos, int size) {
242     EXPECT_EQ(0, memcmp(buffer, data_ + pos, size));
243   }
244
245   void ConfirmLoaderOffsets(int64 expected_offset,
246                             int expected_first_offset,
247                             int expected_last_offset) {
248     EXPECT_EQ(loader_->offset_, expected_offset);
249     EXPECT_EQ(loader_->first_offset_, expected_first_offset);
250     EXPECT_EQ(loader_->last_offset_, expected_last_offset);
251   }
252
253   void ConfirmBufferState(int backward_bytes,
254                           int backward_capacity,
255                           int forward_bytes,
256                           int forward_capacity) {
257     EXPECT_EQ(backward_bytes, loader_->buffer_.backward_bytes());
258     EXPECT_EQ(backward_capacity, loader_->buffer_.backward_capacity());
259     EXPECT_EQ(forward_bytes, loader_->buffer_.forward_bytes());
260     EXPECT_EQ(forward_capacity, loader_->buffer_.forward_capacity());
261   }
262
263   void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity) {
264     EXPECT_EQ(loader_->buffer_.backward_capacity(),
265               expected_backward_capacity);
266   }
267
268   void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity) {
269     EXPECT_EQ(loader_->buffer_.forward_capacity(), expected_forward_capacity);
270   }
271
272   // Makes sure the |loader_| buffer window is in a reasonable range.
273   void CheckBufferWindowBounds() {
274     // Corresponds to value defined in buffered_resource_loader.cc.
275     static const int kMinBufferCapacity = 2 * 1024 * 1024;
276     EXPECT_GE(loader_->buffer_.forward_capacity(), kMinBufferCapacity);
277     EXPECT_GE(loader_->buffer_.backward_capacity(), kMinBufferCapacity);
278
279     // Corresponds to value defined in buffered_resource_loader.cc.
280     static const int kMaxBufferCapacity = 20 * 1024 * 1024;
281     EXPECT_LE(loader_->buffer_.forward_capacity(), kMaxBufferCapacity);
282     EXPECT_LE(loader_->buffer_.backward_capacity(), kMaxBufferCapacity);
283   }
284
285   MOCK_METHOD1(StartCallback, void(BufferedResourceLoader::Status));
286   MOCK_METHOD2(ReadCallback, void(BufferedResourceLoader::Status, int));
287   MOCK_METHOD1(LoadingCallback, void(BufferedResourceLoader::LoadingState));
288   MOCK_METHOD1(ProgressCallback, void(int64));
289
290  protected:
291   GURL gurl_;
292   int64 first_position_;
293   int64 last_position_;
294
295   scoped_ptr<BufferedResourceLoader> loader_;
296   NiceMock<MockWebURLLoader>* url_loader_;
297
298   MockWebFrameClient client_;
299   WebView* view_;
300   WebLocalFrame* frame_;
301
302   base::MessageLoop message_loop_;
303
304   uint8 data_[kDataSize];
305
306  private:
307   DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest);
308 };
309
310 TEST_F(BufferedResourceLoaderTest, StartStop) {
311   Initialize(kHttpUrl, -1, -1);
312   Start();
313   StopWhenLoad();
314 }
315
316 // Tests that a bad HTTP response is recived, e.g. file not found.
317 TEST_F(BufferedResourceLoaderTest, BadHttpResponse) {
318   Initialize(kHttpUrl, -1, -1);
319   Start();
320
321   EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed));
322
323   WebURLResponse response(gurl_);
324   response.setHTTPStatusCode(404);
325   response.setHTTPStatusText("Not Found\n");
326   loader_->didReceiveResponse(url_loader_, response);
327   StopWhenLoad();
328 }
329
330 // Tests that partial content is requested but not fulfilled.
331 TEST_F(BufferedResourceLoaderTest, NotPartialResponse) {
332   Initialize(kHttpUrl, 100, -1);
333   Start();
334   FullResponse(1024, BufferedResourceLoader::kFailed);
335   StopWhenLoad();
336 }
337
338 // Tests that a 200 response is received.
339 TEST_F(BufferedResourceLoaderTest, FullResponse) {
340   Initialize(kHttpUrl, -1, -1);
341   Start();
342   FullResponse(1024);
343   StopWhenLoad();
344 }
345
346 // Tests that a partial content response is received.
347 TEST_F(BufferedResourceLoaderTest, PartialResponse) {
348   Initialize(kHttpUrl, 100, 200);
349   Start();
350   PartialResponse(100, 200, 1024);
351   StopWhenLoad();
352 }
353
354 TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) {
355   Initialize(kHttpUrl, 100, 200);
356   Start();
357   PartialResponse(100, 200, 1024, true, true);
358   StopWhenLoad();
359 }
360
361 TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) {
362   Initialize(kHttpUrl, 100, 200);
363   Start();
364   PartialResponse(100, 200, 1024, false, false);
365   StopWhenLoad();
366 }
367
368 TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) {
369   Initialize(kHttpUrl, 100, 200);
370   Start();
371   PartialResponse(100, 200, 1024, true, false);
372   StopWhenLoad();
373 }
374
375 // Tests that an invalid partial response is received.
376 TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) {
377   Initialize(kHttpUrl, 0, 10);
378   Start();
379
380   EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed));
381
382   WebURLResponse response(gurl_);
383   response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
384                               WebString::fromUTF8(base::StringPrintf("bytes "
385                                   "%d-%d/%d", 1, 10, 1024)));
386   response.setExpectedContentLength(10);
387   response.setHTTPStatusCode(kHttpPartialContent);
388   loader_->didReceiveResponse(url_loader_, response);
389   StopWhenLoad();
390 }
391
392 // Tests the logic of sliding window for data buffering and reading.
393 TEST_F(BufferedResourceLoaderTest, BufferAndRead) {
394   Initialize(kHttpUrl, 10, 29);
395   loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
396   Start();
397   PartialResponse(10, 29, 30);
398
399   uint8 buffer[10];
400   InSequence s;
401
402   // Writes 10 bytes and read them back.
403   WriteLoader(10, 10);
404   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
405   ReadLoader(10, 10, buffer);
406   VerifyBuffer(buffer, 10, 10);
407
408   // Writes 10 bytes and read 2 times.
409   WriteLoader(20, 10);
410   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
411   ReadLoader(20, 5, buffer);
412   VerifyBuffer(buffer, 20, 5);
413   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
414   ReadLoader(25, 5, buffer);
415   VerifyBuffer(buffer, 25, 5);
416
417   // Read backward within buffer.
418   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
419   ReadLoader(10, 10, buffer);
420   VerifyBuffer(buffer, 10, 10);
421
422   // Read backward outside buffer.
423   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
424   ReadLoader(9, 10, buffer);
425
426   // Response has completed.
427   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished));
428   loader_->didFinishLoading(url_loader_, 0, -1);
429
430   // Try to read 10 from position 25 will just return with 5 bytes.
431   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
432   ReadLoader(25, 10, buffer);
433   VerifyBuffer(buffer, 25, 5);
434
435   // Try to read outside buffered range after request has completed.
436   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
437   ReadLoader(5, 10, buffer);
438
439   // Try to read beyond the instance size.
440   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 0));
441   ReadLoader(30, 10, buffer);
442 }
443
444 // Tests the logic of expanding the data buffer for large reads.
445 TEST_F(BufferedResourceLoaderTest, ReadExtendBuffer) {
446   Initialize(kHttpUrl, 10, 0x014FFFFFF);
447   SetLoaderBuffer(10, 20);
448   Start();
449   PartialResponse(10, 0x014FFFFFF, 0x015000000);
450
451   uint8 buffer[20];
452   InSequence s;
453
454   // Write more than forward capacity and read it back. Ensure forward capacity
455   // gets reset after reading.
456   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
457   WriteLoader(10, 20);
458
459   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20));
460   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
461   ReadLoader(10, 20, buffer);
462
463   VerifyBuffer(buffer, 10, 20);
464   ConfirmLoaderBufferForwardCapacity(10);
465
466   // Make and outstanding read request larger than forward capacity. Ensure
467   // forward capacity gets extended.
468   ReadLoader(30, 20, buffer);
469   ConfirmLoaderBufferForwardCapacity(20);
470
471   // Fulfill outstanding request. Ensure forward capacity gets reset.
472   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20));
473   WriteLoader(30, 20);
474
475   VerifyBuffer(buffer, 30, 20);
476   ConfirmLoaderBufferForwardCapacity(10);
477
478   // Try to read further ahead than kForwardWaitThreshold allows. Ensure
479   // forward capacity is not changed.
480   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
481   ReadLoader(0x00300000, 1, buffer);
482
483   ConfirmLoaderBufferForwardCapacity(10);
484
485   // Try to read more than maximum forward capacity. Ensure forward capacity is
486   // not changed.
487   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
488   ReadLoader(30, 0x01400001, buffer);
489
490   ConfirmLoaderBufferForwardCapacity(10);
491
492   StopWhenLoad();
493 }
494
495 TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) {
496   Initialize(kHttpUrl, 10, 0x00FFFFFF);
497   Start();
498   PartialResponse(10, 0x00FFFFFF, 0x01000000);
499
500   uint8 buffer[10];
501   InSequence s;
502
503   // Read very far ahead will get a cache miss.
504   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
505   ReadLoader(0x00FFFFFF, 1, buffer);
506
507   // The following call will not call ReadCallback() because it is waiting for
508   // data to arrive.
509   ReadLoader(10, 10, buffer);
510
511   // Writing to loader will fulfill the read request.
512   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
513   WriteLoader(10, 20);
514   VerifyBuffer(buffer, 10, 10);
515
516   // The following call cannot be fulfilled now.
517   ReadLoader(25, 10, buffer);
518
519   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished));
520   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
521   loader_->didFinishLoading(url_loader_, 0, -1);
522 }
523
524 TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) {
525   Initialize(kHttpUrl, 10, 29);
526   Start();
527   PartialResponse(10, 29, 30);
528
529   uint8 buffer[10];
530   InSequence s;
531
532   // We should convert any error we receive to BufferedResourceLoader::kFailed.
533   ReadLoader(10, 10, buffer);
534   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
535   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
536   WebURLError error;
537   error.reason = net::ERR_TIMED_OUT;
538   error.isCancellation = false;
539   loader_->didFail(url_loader_, error);
540 }
541
542 TEST_F(BufferedResourceLoaderTest, RequestFailedWithNoPendingReads) {
543   Initialize(kHttpUrl, 10, 29);
544   Start();
545   PartialResponse(10, 29, 30);
546
547   uint8 buffer[10];
548   InSequence s;
549
550   // Write enough data so that a read would technically complete had the request
551   // not failed.
552   WriteLoader(10, 20);
553
554   // Fail without a pending read.
555   WebURLError error;
556   error.reason = net::ERR_TIMED_OUT;
557   error.isCancellation = false;
558   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
559   loader_->didFail(url_loader_, error);
560
561   // Now we should immediately fail any read even if we have data buffered.
562   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
563   ReadLoader(10, 10, buffer);
564 }
565
566 TEST_F(BufferedResourceLoaderTest, RequestCancelledWhenRead) {
567   Initialize(kHttpUrl, 10, 29);
568   Start();
569   PartialResponse(10, 29, 30);
570
571   uint8 buffer[10];
572   InSequence s;
573
574   // We should convert any error we receive to BufferedResourceLoader::kFailed.
575   ReadLoader(10, 10, buffer);
576   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
577   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
578   WebURLError error;
579   error.reason = 0;
580   error.isCancellation = true;
581   loader_->didFail(url_loader_, error);
582 }
583
584 // Tests the data buffering logic of NeverDefer strategy.
585 TEST_F(BufferedResourceLoaderTest, NeverDeferStrategy) {
586   Initialize(kHttpUrl, 10, 99);
587   SetLoaderBuffer(10, 20);
588   loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer);
589   Start();
590   PartialResponse(10, 99, 100);
591
592   uint8 buffer[10];
593
594   // Read past the buffer size; should not defer regardless.
595   WriteLoader(10, 10);
596   WriteLoader(20, 50);
597
598   // Should move past window.
599   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
600   ReadLoader(10, 10, buffer);
601
602   StopWhenLoad();
603 }
604
605 // Tests the data buffering logic of ReadThenDefer strategy.
606 TEST_F(BufferedResourceLoaderTest, ReadThenDeferStrategy) {
607   Initialize(kHttpUrl, 10, 99);
608   SetLoaderBuffer(10, 20);
609   loader_->UpdateDeferStrategy(BufferedResourceLoader::kReadThenDefer);
610   Start();
611   PartialResponse(10, 99, 100);
612
613   uint8 buffer[10];
614
615   // Make an outstanding read request.
616   ReadLoader(10, 10, buffer);
617
618   // Receive almost enough data to cover, shouldn't defer.
619   WriteLoader(10, 9);
620
621   // As soon as we have received enough data to fulfill the read, defer.
622   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
623   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
624   WriteLoader(19, 1);
625
626   VerifyBuffer(buffer, 10, 10);
627
628   // Read again which should disable deferring since there should be nothing
629   // left in our internal buffer.
630   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
631   ReadLoader(20, 10, buffer);
632
633   // Over-fulfill requested bytes, then deferring should be enabled again.
634   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
635   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
636   WriteLoader(20, 40);
637
638   VerifyBuffer(buffer, 20, 10);
639
640   // Read far ahead, which should disable deferring. In this case we still have
641   // bytes in our internal buffer.
642   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
643   ReadLoader(80, 10, buffer);
644
645   // Fulfill requested bytes, then deferring should be enabled again.
646   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
647   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
648   WriteLoader(60, 40);
649
650   VerifyBuffer(buffer, 80, 10);
651
652   StopWhenLoad();
653 }
654
655 // Tests the data buffering logic of kCapacityDefer strategy.
656 TEST_F(BufferedResourceLoaderTest, ThresholdDeferStrategy) {
657   Initialize(kHttpUrl, 10, 99);
658   SetLoaderBuffer(10, 20);
659   Start();
660   PartialResponse(10, 99, 100);
661
662   uint8 buffer[10];
663   InSequence s;
664
665   // Write half of capacity: keep not deferring.
666   WriteData(5);
667
668   // Write rest of space until capacity: start deferring.
669   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
670   WriteData(5);
671
672   // Read a byte from the buffer: stop deferring.
673   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1));
674   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
675   ReadLoader(10, 1, buffer);
676
677   // Write a byte to hit capacity: start deferring.
678   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
679   WriteData(6);
680
681   StopWhenLoad();
682 }
683
684 TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) {
685   Initialize(kHttpUrl, 10, 99);
686   SetLoaderBuffer(10, 10);
687   Start();
688   PartialResponse(10, 99, 100);
689
690   uint8 buffer[256];
691   InSequence s;
692
693   // PRECONDITION
694   WriteUntilThreshold();
695   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1));
696   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
697   ReadLoader(10, 1, buffer);
698   ConfirmBufferState(1, 10, 9, 10);
699   ConfirmLoaderOffsets(11, 0, 0);
700
701   // *** TRICKY BUSINESS, PT. I ***
702   // Read past buffered: stop deferring.
703   //
704   // In order for the read to complete we must:
705   //   1) Stop deferring to receive more data.
706   //
707   // BEFORE
708   //   offset=11 [xxxxxxxxx_]
709   //                       ^ ^^^ requested 4 bytes @ offset 20
710   // AFTER
711   //   offset=24 [__________]
712   //
713   ReadLoader(20, 4, buffer);
714
715   // Write a little, make sure we didn't start deferring.
716   WriteData(2);
717
718   // Write the rest, read should complete.
719   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
720   WriteData(2);
721
722   // POSTCONDITION
723   ConfirmBufferState(4, 10, 0, 10);
724   ConfirmLoaderOffsets(24, 0, 0);
725
726   StopWhenLoad();
727 }
728
729 TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) {
730   Initialize(kHttpUrl, 10, 99);
731   SetLoaderBuffer(10, 10);
732   Start();
733   PartialResponse(10, 99, 100);
734
735   uint8 buffer[256];
736   InSequence s;
737
738   // PRECONDITION
739   WriteUntilThreshold();
740   ConfirmBufferState(0, 10, 10, 10);
741   ConfirmLoaderOffsets(10, 0, 0);
742
743   // *** TRICKY BUSINESS, PT. II ***
744   // Read backwards a little too much: cache miss.
745   //
746   // BEFORE
747   //   offset=10 [__________|xxxxxxxxxx]
748   //                       ^ ^^^ requested 10 bytes @ offset 9
749   // AFTER
750   //   offset=10 [__________|xxxxxxxxxx]  !!! cache miss !!!
751   //
752   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
753   ReadLoader(9, 4, buffer);
754
755   // POSTCONDITION
756   ConfirmBufferState(0, 10, 10, 10);
757   ConfirmLoaderOffsets(10, 0, 0);
758
759   StopWhenLoad();
760 }
761
762 TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) {
763   Initialize(kHttpUrl, 10, 99);
764   SetLoaderBuffer(10, 10);
765   Start();
766   PartialResponse(10, 99, 100);
767
768   uint8 buffer[256];
769   InSequence s;
770
771   // PRECONDITION
772   WriteUntilThreshold();
773   ConfirmBufferState(0, 10, 10, 10);
774   ConfirmLoaderOffsets(10, 0, 0);
775
776   // *** TRICKY BUSINESS, PT. III ***
777   // Read past forward capacity but within capacity: stop deferring.
778   //
779   // In order for the read to complete we must:
780   //   1) Adjust offset forward to create capacity.
781   //   2) Stop deferring to receive more data.
782   //
783   // BEFORE
784   //   offset=10 [xxxxxxxxxx]
785   //                             ^^^^ requested 4 bytes @ offset 24
786   // ADJUSTED OFFSET
787   //   offset=20 [__________]
788   //                  ^^^^ requested 4 bytes @ offset 24
789   // AFTER
790   //   offset=28 [__________]
791   //
792   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
793   ReadLoader(24, 4, buffer);
794   ConfirmLoaderOffsets(20, 4, 8);
795
796   // Write a little, make sure we didn't start deferring.
797   WriteData(4);
798
799   // Write the rest, read should complete.
800   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
801   WriteData(4);
802
803   // POSTCONDITION
804   ConfirmBufferState(8, 10, 0, 10);
805   ConfirmLoaderOffsets(28, 0, 0);
806
807   StopWhenLoad();
808 }
809
810 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) {
811   Initialize(kHttpUrl, 10, 99);
812   SetLoaderBuffer(10, 10);
813   Start();
814   PartialResponse(10, 99, 100);
815
816   uint8 buffer[256];
817   InSequence s;
818
819   // PRECONDITION
820   WriteUntilThreshold();
821   ConfirmBufferState(0, 10, 10, 10);
822   ConfirmLoaderOffsets(10, 0, 0);
823
824   // *** TRICKY BUSINESS, PT. IV ***
825   // Read a large amount past forward capacity but within
826   // capacity: stop deferring.
827   //
828   // In order for the read to complete we must:
829   //   1) Adjust offset forward to create capacity.
830   //   2) Expand capacity to make sure we don't defer as data arrives.
831   //   3) Stop deferring to receive more data.
832   //
833   // BEFORE
834   //   offset=10 [xxxxxxxxxx]
835   //                             ^^^^^^^^^^^^ requested 12 bytes @ offset 24
836   // ADJUSTED OFFSET
837   //   offset=20 [__________]
838   //                  ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24
839   // ADJUSTED CAPACITY
840   //   offset=20 [________________]
841   //                  ^^^^^^^^^^^^ requested 12 bytes @ offset 24
842   // AFTER
843   //   offset=36 [__________]
844   //
845   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
846   ReadLoader(24, 12, buffer);
847   ConfirmLoaderOffsets(20, 4, 16);
848   ConfirmBufferState(10, 10, 0, 16);
849
850   // Write a little, make sure we didn't start deferring.
851   WriteData(10);
852
853   // Write the rest, read should complete and capacity should go back to normal.
854   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 12));
855   WriteData(6);
856   ConfirmLoaderBufferForwardCapacity(10);
857
858   // POSTCONDITION
859   ConfirmBufferState(6, 10, 0, 10);
860   ConfirmLoaderOffsets(36, 0, 0);
861
862   StopWhenLoad();
863 }
864
865 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) {
866   Initialize(kHttpUrl, 10, 99);
867   SetLoaderBuffer(10, 10);
868   Start();
869   PartialResponse(10, 99, 100);
870
871   uint8 buffer[256];
872   InSequence s;
873
874   // PRECONDITION
875   WriteUntilThreshold();
876   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
877   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
878   ReadLoader(10, 10, buffer);
879   WriteUntilThreshold();
880   ConfirmBufferState(10, 10, 10, 10);
881   ConfirmLoaderOffsets(20, 0, 0);
882
883   // *** TRICKY BUSINESS, PT. V ***
884   // Read a large amount that involves backwards data: stop deferring.
885   //
886   // In order for the read to complete we must:
887   //   1) Adjust offset *backwards* to create capacity.
888   //   2) Expand capacity to make sure we don't defer as data arrives.
889   //   3) Stop deferring to receive more data.
890   //
891   // BEFORE
892   //   offset=20 [xxxxxxxxxx|xxxxxxxxxx]
893   //                    ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16
894   // ADJUSTED OFFSET
895   //   offset=16 [____xxxxxx|xxxxxxxxxx]xxxx
896   //                         ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16
897   // ADJUSTED CAPACITY
898   //   offset=16 [____xxxxxx|xxxxxxxxxxxxxx____]
899   //                         ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16
900   // AFTER
901   //   offset=34 [xxxxxxxxxx|__________]
902   //
903   EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
904   ReadLoader(16, 18, buffer);
905   ConfirmLoaderOffsets(16, 0, 18);
906   ConfirmBufferState(6, 10, 14, 18);
907
908   // Write a little, make sure we didn't start deferring.
909   WriteData(2);
910
911   // Write the rest, read should complete and capacity should go back to normal.
912   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 18));
913   WriteData(2);
914   ConfirmLoaderBufferForwardCapacity(10);
915
916   // POSTCONDITION
917   ConfirmBufferState(4, 10, 0, 10);
918   ConfirmLoaderOffsets(34, 0, 0);
919
920   StopWhenLoad();
921 }
922
923 TEST_F(BufferedResourceLoaderTest, Tricky_ReadPastThreshold) {
924   const int kSize = 5 * 1024 * 1024;
925   const int kThreshold = 2 * 1024 * 1024;
926
927   Initialize(kHttpUrl, 10, kSize);
928   SetLoaderBuffer(10, 10);
929   Start();
930   PartialResponse(10, kSize - 1, kSize);
931
932   uint8 buffer[256];
933   InSequence s;
934
935   // PRECONDITION
936   WriteUntilThreshold();
937   ConfirmBufferState(0, 10, 10, 10);
938   ConfirmLoaderOffsets(10, 0, 0);
939
940   // *** TRICKY BUSINESS, PT. VI ***
941   // Read past the forward wait threshold: cache miss.
942   //
943   // BEFORE
944   //   offset=10 [xxxxxxxxxx] ...
945   //                              ^^^^ requested 10 bytes @ threshold
946   // AFTER
947   //   offset=10 [xxxxxxxxxx]  !!! cache miss !!!
948   //
949   EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
950   ReadLoader(kThreshold + 20, 10, buffer);
951
952   // POSTCONDITION
953   ConfirmBufferState(0, 10, 10, 10);
954   ConfirmLoaderOffsets(10, 0, 0);
955
956   StopWhenLoad();
957 }
958
959 TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) {
960   // Make sure no redirect case works as expected.
961   Initialize(kHttpUrl, -1, -1);
962   Start();
963   FullResponse(1024);
964   EXPECT_TRUE(loader_->HasSingleOrigin());
965   StopWhenLoad();
966
967   // Test redirect to the same domain.
968   Initialize(kHttpUrl, -1, -1);
969   Start();
970   Redirect(kHttpRedirectToSameDomainUrl1);
971   FullResponse(1024);
972   EXPECT_TRUE(loader_->HasSingleOrigin());
973   StopWhenLoad();
974
975   // Test redirect twice to the same domain.
976   Initialize(kHttpUrl, -1, -1);
977   Start();
978   Redirect(kHttpRedirectToSameDomainUrl1);
979   Redirect(kHttpRedirectToSameDomainUrl2);
980   FullResponse(1024);
981   EXPECT_TRUE(loader_->HasSingleOrigin());
982   StopWhenLoad();
983
984   // Test redirect to a different domain.
985   Initialize(kHttpUrl, -1, -1);
986   Start();
987   Redirect(kHttpRedirectToDifferentDomainUrl1);
988   FullResponse(1024);
989   EXPECT_FALSE(loader_->HasSingleOrigin());
990   StopWhenLoad();
991
992   // Test redirect to the same domain and then to a different domain.
993   Initialize(kHttpUrl, -1, -1);
994   Start();
995   Redirect(kHttpRedirectToSameDomainUrl1);
996   Redirect(kHttpRedirectToDifferentDomainUrl1);
997   FullResponse(1024);
998   EXPECT_FALSE(loader_->HasSingleOrigin());
999   StopWhenLoad();
1000 }
1001
1002 TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) {
1003   Initialize(kHttpUrl, -1, -1);
1004   Start();
1005
1006   // Test ensures that default construction of a BufferedResourceLoader has sane
1007   // values.
1008   //
1009   // Please do not change these values in order to make a test pass! Instead,
1010   // start a conversation on what the default buffer window capacities should
1011   // be.
1012   ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024);
1013   ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024);
1014
1015   StopWhenLoad();
1016 }
1017
1018 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) {
1019   Initialize(kHttpUrl, -1, -1);
1020   Start();
1021   loader_->SetBitrate(0);
1022   CheckBufferWindowBounds();
1023   StopWhenLoad();
1024 }
1025
1026 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_BelowLowerBound) {
1027   Initialize(kHttpUrl, -1, -1);
1028   Start();
1029   loader_->SetBitrate(1024 * 8);  // 1 Kbps.
1030   CheckBufferWindowBounds();
1031   StopWhenLoad();
1032 }
1033
1034 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_WithinBounds) {
1035   Initialize(kHttpUrl, -1, -1);
1036   Start();
1037   loader_->SetBitrate(2 * 1024 * 1024 * 8);  // 2 Mbps.
1038   CheckBufferWindowBounds();
1039   StopWhenLoad();
1040 }
1041
1042 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_AboveUpperBound) {
1043   Initialize(kHttpUrl, -1, -1);
1044   Start();
1045   loader_->SetBitrate(100 * 1024 * 1024 * 8);  // 100 Mbps.
1046   CheckBufferWindowBounds();
1047   StopWhenLoad();
1048 }
1049
1050 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) {
1051   Initialize(kHttpUrl, -1, -1);
1052   Start();
1053   loader_->SetPlaybackRate(-10);
1054   CheckBufferWindowBounds();
1055   StopWhenLoad();
1056 }
1057
1058 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) {
1059   Initialize(kHttpUrl, -1, -1);
1060   Start();
1061   loader_->SetPlaybackRate(0);
1062   CheckBufferWindowBounds();
1063   StopWhenLoad();
1064 }
1065
1066 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) {
1067   Initialize(kHttpUrl, -1, -1);
1068   Start();
1069   loader_->SetPlaybackRate(0.1f);
1070   CheckBufferWindowBounds();
1071   StopWhenLoad();
1072 }
1073
1074 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) {
1075   Initialize(kHttpUrl, -1, -1);
1076   Start();
1077   loader_->SetPlaybackRate(10);
1078   CheckBufferWindowBounds();
1079   StopWhenLoad();
1080 }
1081
1082 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) {
1083   Initialize(kHttpUrl, -1, -1);
1084   Start();
1085   loader_->SetPlaybackRate(100);
1086   CheckBufferWindowBounds();
1087   StopWhenLoad();
1088 }
1089
1090 static void ExpectContentRange(
1091     const std::string& str, bool expect_success,
1092     int64 expected_first, int64 expected_last, int64 expected_size) {
1093   int64 first, last, size;
1094   ASSERT_EQ(expect_success, BufferedResourceLoader::ParseContentRange(
1095       str, &first, &last, &size)) << str;
1096   if (!expect_success)
1097     return;
1098   EXPECT_EQ(first, expected_first);
1099   EXPECT_EQ(last, expected_last);
1100   EXPECT_EQ(size, expected_size);
1101 }
1102
1103 static void ExpectContentRangeFailure(const std::string& str) {
1104   ExpectContentRange(str, false, 0, 0, 0);
1105 }
1106
1107 static void ExpectContentRangeSuccess(
1108     const std::string& str,
1109     int64 expected_first, int64 expected_last, int64 expected_size) {
1110   ExpectContentRange(str, true, expected_first, expected_last, expected_size);
1111 }
1112
1113 TEST(BufferedResourceLoaderStandaloneTest, ParseContentRange) {
1114   ExpectContentRangeFailure("cytes 0-499/500");
1115   ExpectContentRangeFailure("bytes 0499/500");
1116   ExpectContentRangeFailure("bytes 0-499500");
1117   ExpectContentRangeFailure("bytes 0-499/500-blorg");
1118   ExpectContentRangeFailure("bytes 0-499/500-1");
1119   ExpectContentRangeFailure("bytes 0-499/400");
1120   ExpectContentRangeFailure("bytes 0-/400");
1121   ExpectContentRangeFailure("bytes -300/400");
1122   ExpectContentRangeFailure("bytes 20-10/400");
1123
1124   ExpectContentRangeSuccess("bytes 0-499/500", 0, 499, 500);
1125   ExpectContentRangeSuccess("bytes 0-0/500", 0, 0, 500);
1126   ExpectContentRangeSuccess("bytes 10-11/50", 10, 11, 50);
1127   ExpectContentRangeSuccess("bytes 10-11/*", 10, 11,
1128                             kPositionNotSpecified);
1129 }
1130
1131 }  // namespace content