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