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.
9 #include "base/format_macros.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "media/base/media_log.h"
13 #include "media/base/seekable_buffer.h"
14 #include "media/blink/buffered_resource_loader.h"
15 #include "media/blink/mock_webframeclient.h"
16 #include "media/blink/mock_weburlloader.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"
28 using ::testing::InSequence
;
29 using ::testing::Return
;
30 using ::testing::Truly
;
31 using ::testing::NiceMock
;
33 using blink::WebLocalFrame
;
34 using blink::WebString
;
35 using blink::WebURLError
;
36 using blink::WebURLResponse
;
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";
46 static const int kDataSize
= 1024;
47 static const int kHttpOK
= 200;
48 static const int kHttpPartialContent
= 206;
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
);
64 class BufferedResourceLoaderTest
: public testing::Test
{
66 BufferedResourceLoaderTest()
67 : view_(WebView::create(NULL
)),
68 frame_(WebLocalFrame::create(blink::WebTreeScopeType::Document
,
70 view_
->setMainFrame(frame_
);
72 for (int i
= 0; i
< kDataSize
; ++i
) {
77 virtual ~BufferedResourceLoaderTest() {
82 void Initialize(const char* url
, int first_position
, int last_position
) {
84 first_position_
= first_position
;
85 last_position_
= last_position
;
87 loader_
.reset(new BufferedResourceLoader(
88 gurl_
, BufferedResourceLoader::kUnspecified
,
89 first_position_
, last_position_
,
90 BufferedResourceLoader::kCapacityDefer
, 0, 0,
93 // |test_loader_| will be used when Start() is called.
94 url_loader_
= new NiceMock
<MockWebURLLoader
>();
95 loader_
->test_loader_
= scoped_ptr
<blink::WebURLLoader
>(url_loader_
);
98 void SetLoaderBuffer(int forward_capacity
, int backward_capacity
) {
99 loader_
->buffer_
.set_forward_capacity(forward_capacity
);
100 loader_
->buffer_
.set_backward_capacity(backward_capacity
);
101 loader_
->buffer_
.Clear();
106 EXPECT_CALL(*url_loader_
, loadAsynchronously(Truly(CorrectAcceptEncoding
),
109 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
111 base::Bind(&BufferedResourceLoaderTest::StartCallback
,
112 base::Unretained(this)),
113 base::Bind(&BufferedResourceLoaderTest::LoadingCallback
,
114 base::Unretained(this)),
115 base::Bind(&BufferedResourceLoaderTest::ProgressCallback
,
116 base::Unretained(this)),
120 void FullResponse(int64 instance_size
) {
121 FullResponse(instance_size
, BufferedResourceLoader::kOk
);
124 void FullResponse(int64 instance_size
,
125 BufferedResourceLoader::Status status
) {
126 EXPECT_CALL(*this, StartCallback(status
));
128 WebURLResponse
response(gurl_
);
129 response
.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
130 WebString::fromUTF8(base::StringPrintf("%"
131 PRId64
, instance_size
)));
132 response
.setExpectedContentLength(instance_size
);
133 response
.setHTTPStatusCode(kHttpOK
);
134 loader_
->didReceiveResponse(url_loader_
, response
);
136 if (status
== BufferedResourceLoader::kOk
) {
137 EXPECT_EQ(instance_size
, loader_
->content_length());
138 EXPECT_EQ(instance_size
, loader_
->instance_size());
141 EXPECT_FALSE(loader_
->range_supported());
144 void PartialResponse(int64 first_position
, int64 last_position
,
145 int64 instance_size
) {
146 PartialResponse(first_position
, last_position
, instance_size
, false, true);
149 void PartialResponse(int64 first_position
, int64 last_position
,
150 int64 instance_size
, bool chunked
, bool accept_ranges
) {
151 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kOk
));
153 WebURLResponse
response(gurl_
);
154 response
.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
155 WebString::fromUTF8(base::StringPrintf("bytes "
156 "%" PRId64
"-%" PRId64
"/%" PRId64
,
161 // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked.
162 int64 content_length
= -1;
164 response
.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"),
165 WebString::fromUTF8("chunked"));
167 content_length
= last_position
- first_position
+ 1;
169 response
.setExpectedContentLength(content_length
);
171 // A server isn't required to return Accept-Ranges even though it might.
173 response
.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
174 WebString::fromUTF8("bytes"));
177 response
.setHTTPStatusCode(kHttpPartialContent
);
178 loader_
->didReceiveResponse(url_loader_
, response
);
180 // XXX: what's the difference between these two? For example in the chunked
181 // range request case, Content-Length is unspecified (because it's chunked)
182 // but Content-Range: a-b/c can be returned, where c == Content-Length
184 // Can we eliminate one?
185 EXPECT_EQ(content_length
, loader_
->content_length());
186 EXPECT_EQ(instance_size
, loader_
->instance_size());
188 // A valid partial response should always result in this being true.
189 EXPECT_TRUE(loader_
->range_supported());
192 void Redirect(const char* url
) {
193 GURL
redirectUrl(url
);
194 blink::WebURLRequest
newRequest(redirectUrl
);
195 blink::WebURLResponse
redirectResponse(gurl_
);
197 loader_
->willSendRequest(url_loader_
, newRequest
, redirectResponse
);
199 base::MessageLoop::current()->RunUntilIdle();
202 void StopWhenLoad() {
204 EXPECT_CALL(*url_loader_
, cancel());
209 // Helper method to write to |loader_| from |data_|.
210 void WriteLoader(int position
, int size
) {
211 EXPECT_CALL(*this, ProgressCallback(position
+ size
- 1));
212 loader_
->didReceiveData(url_loader_
,
213 reinterpret_cast<char*>(data_
+ position
),
218 void WriteData(int size
) {
219 EXPECT_CALL(*this, ProgressCallback(_
));
221 scoped_ptr
<char[]> data(new char[size
]);
222 loader_
->didReceiveData(url_loader_
, data
.get(), size
, size
);
225 void WriteUntilThreshold() {
226 int buffered
= loader_
->buffer_
.forward_bytes();
227 int capacity
= loader_
->buffer_
.forward_capacity();
228 CHECK_LT(buffered
, capacity
);
230 EXPECT_CALL(*this, LoadingCallback(
231 BufferedResourceLoader::kLoadingDeferred
));
232 WriteData(capacity
- buffered
);
235 // Helper method to read from |loader_|.
236 void ReadLoader(int64 position
, int size
, uint8
* buffer
) {
237 loader_
->Read(position
, size
, buffer
,
238 base::Bind(&BufferedResourceLoaderTest::ReadCallback
,
239 base::Unretained(this)));
242 // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size].
243 void VerifyBuffer(uint8
* buffer
, int pos
, int size
) {
244 EXPECT_EQ(0, memcmp(buffer
, data_
+ pos
, size
));
247 void ConfirmLoaderOffsets(int64 expected_offset
,
248 int expected_first_offset
,
249 int expected_last_offset
) {
250 EXPECT_EQ(loader_
->offset_
, expected_offset
);
251 EXPECT_EQ(loader_
->first_offset_
, expected_first_offset
);
252 EXPECT_EQ(loader_
->last_offset_
, expected_last_offset
);
255 void ConfirmBufferState(int backward_bytes
,
256 int backward_capacity
,
258 int forward_capacity
) {
259 EXPECT_EQ(backward_bytes
, loader_
->buffer_
.backward_bytes());
260 EXPECT_EQ(backward_capacity
, loader_
->buffer_
.backward_capacity());
261 EXPECT_EQ(forward_bytes
, loader_
->buffer_
.forward_bytes());
262 EXPECT_EQ(forward_capacity
, loader_
->buffer_
.forward_capacity());
265 void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity
) {
266 EXPECT_EQ(loader_
->buffer_
.backward_capacity(),
267 expected_backward_capacity
);
270 void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity
) {
271 EXPECT_EQ(loader_
->buffer_
.forward_capacity(), expected_forward_capacity
);
274 // Makes sure the |loader_| buffer window is in a reasonable range.
275 void CheckBufferWindowBounds() {
276 // Corresponds to value defined in buffered_resource_loader.cc.
277 static const int kMinBufferCapacity
= 2 * 1024 * 1024;
278 EXPECT_GE(loader_
->buffer_
.forward_capacity(), kMinBufferCapacity
);
279 EXPECT_GE(loader_
->buffer_
.backward_capacity(), kMinBufferCapacity
);
281 // Corresponds to value defined in buffered_resource_loader.cc.
282 static const int kMaxBufferCapacity
= 20 * 1024 * 1024;
283 EXPECT_LE(loader_
->buffer_
.forward_capacity(), kMaxBufferCapacity
);
284 EXPECT_LE(loader_
->buffer_
.backward_capacity(), kMaxBufferCapacity
);
287 bool HasActiveLoader() { return loader_
->active_loader_
; }
289 MOCK_METHOD1(StartCallback
, void(BufferedResourceLoader::Status
));
290 MOCK_METHOD2(ReadCallback
, void(BufferedResourceLoader::Status
, int));
291 MOCK_METHOD1(LoadingCallback
, void(BufferedResourceLoader::LoadingState
));
292 MOCK_METHOD1(ProgressCallback
, void(int64
));
296 int64 first_position_
;
297 int64 last_position_
;
299 scoped_ptr
<BufferedResourceLoader
> loader_
;
300 NiceMock
<MockWebURLLoader
>* url_loader_
;
302 MockWebFrameClient client_
;
304 WebLocalFrame
* frame_
;
306 base::MessageLoop message_loop_
;
308 uint8 data_
[kDataSize
];
311 DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest
);
314 TEST_F(BufferedResourceLoaderTest
, StartStop
) {
315 Initialize(kHttpUrl
, -1, -1);
320 // Tests that a bad HTTP response is recived, e.g. file not found.
321 TEST_F(BufferedResourceLoaderTest
, BadHttpResponse
) {
322 Initialize(kHttpUrl
, -1, -1);
325 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed
));
327 WebURLResponse
response(gurl_
);
328 response
.setHTTPStatusCode(404);
329 response
.setHTTPStatusText("Not Found\n");
330 loader_
->didReceiveResponse(url_loader_
, response
);
334 // Tests that partial content is requested but not fulfilled.
335 TEST_F(BufferedResourceLoaderTest
, NotPartialResponse
) {
336 Initialize(kHttpUrl
, 100, -1);
338 FullResponse(1024, BufferedResourceLoader::kFailed
);
342 // Tests that a 200 response is received.
343 TEST_F(BufferedResourceLoaderTest
, FullResponse
) {
344 Initialize(kHttpUrl
, -1, -1);
350 // Tests that a partial content response is received.
351 TEST_F(BufferedResourceLoaderTest
, PartialResponse
) {
352 Initialize(kHttpUrl
, 100, 200);
354 PartialResponse(100, 200, 1024);
358 TEST_F(BufferedResourceLoaderTest
, PartialResponse_Chunked
) {
359 Initialize(kHttpUrl
, 100, 200);
361 PartialResponse(100, 200, 1024, true, true);
365 TEST_F(BufferedResourceLoaderTest
, PartialResponse_NoAcceptRanges
) {
366 Initialize(kHttpUrl
, 100, 200);
368 PartialResponse(100, 200, 1024, false, false);
372 TEST_F(BufferedResourceLoaderTest
, PartialResponse_ChunkedNoAcceptRanges
) {
373 Initialize(kHttpUrl
, 100, 200);
375 PartialResponse(100, 200, 1024, true, false);
379 // Tests that an invalid partial response is received.
380 TEST_F(BufferedResourceLoaderTest
, InvalidPartialResponse
) {
381 Initialize(kHttpUrl
, 0, 10);
384 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed
));
386 WebURLResponse
response(gurl_
);
387 response
.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
388 WebString::fromUTF8(base::StringPrintf("bytes "
389 "%d-%d/%d", 1, 10, 1024)));
390 response
.setExpectedContentLength(10);
391 response
.setHTTPStatusCode(kHttpPartialContent
);
392 loader_
->didReceiveResponse(url_loader_
, response
);
396 // Tests the logic of sliding window for data buffering and reading.
397 TEST_F(BufferedResourceLoaderTest
, BufferAndRead
) {
398 Initialize(kHttpUrl
, 10, 29);
399 loader_
->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer
);
401 PartialResponse(10, 29, 30);
406 // Writes 10 bytes and read them back.
408 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
409 ReadLoader(10, 10, buffer
);
410 VerifyBuffer(buffer
, 10, 10);
412 // Writes 10 bytes and read 2 times.
414 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 5));
415 ReadLoader(20, 5, buffer
);
416 VerifyBuffer(buffer
, 20, 5);
417 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 5));
418 ReadLoader(25, 5, buffer
);
419 VerifyBuffer(buffer
, 25, 5);
421 // Read backward within buffer.
422 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
423 ReadLoader(10, 10, buffer
);
424 VerifyBuffer(buffer
, 10, 10);
426 // Read backward outside buffer.
427 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
428 ReadLoader(9, 10, buffer
);
430 // Response has completed.
431 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished
));
432 loader_
->didFinishLoading(url_loader_
, 0, -1);
434 // Try to read 10 from position 25 will just return with 5 bytes.
435 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 5));
436 ReadLoader(25, 10, buffer
);
437 VerifyBuffer(buffer
, 25, 5);
439 // Try to read outside buffered range after request has completed.
440 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
441 ReadLoader(5, 10, buffer
);
443 // Try to read beyond the instance size.
444 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 0));
445 ReadLoader(30, 10, buffer
);
448 // Tests the logic of expanding the data buffer for large reads.
449 TEST_F(BufferedResourceLoaderTest
, ReadExtendBuffer
) {
450 Initialize(kHttpUrl
, 10, 0x014FFFFFF);
451 SetLoaderBuffer(10, 20);
453 PartialResponse(10, 0x014FFFFFF, 0x015000000);
458 // Write more than forward capacity and read it back. Ensure forward capacity
459 // gets reset after reading.
460 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
463 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 20));
464 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
465 ReadLoader(10, 20, buffer
);
467 VerifyBuffer(buffer
, 10, 20);
468 ConfirmLoaderBufferForwardCapacity(10);
470 // Make and outstanding read request larger than forward capacity. Ensure
471 // forward capacity gets extended.
472 ReadLoader(30, 20, buffer
);
473 ConfirmLoaderBufferForwardCapacity(20);
475 // Fulfill outstanding request. Ensure forward capacity gets reset.
476 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 20));
479 VerifyBuffer(buffer
, 30, 20);
480 ConfirmLoaderBufferForwardCapacity(10);
482 // Try to read further ahead than kForwardWaitThreshold allows. Ensure
483 // forward capacity is not changed.
484 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
485 ReadLoader(0x00300000, 1, buffer
);
487 ConfirmLoaderBufferForwardCapacity(10);
489 // Try to read more than maximum forward capacity. Ensure forward capacity is
491 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed
, 0));
492 ReadLoader(30, 0x01400001, buffer
);
494 ConfirmLoaderBufferForwardCapacity(10);
499 TEST_F(BufferedResourceLoaderTest
, ReadOutsideBuffer
) {
500 Initialize(kHttpUrl
, 10, 0x00FFFFFF);
502 PartialResponse(10, 0x00FFFFFF, 0x01000000);
507 // Read very far ahead will get a cache miss.
508 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
509 ReadLoader(0x00FFFFFF, 1, buffer
);
511 // The following call will not call ReadCallback() because it is waiting for
513 ReadLoader(10, 10, buffer
);
515 // Writing to loader will fulfill the read request.
516 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
518 VerifyBuffer(buffer
, 10, 10);
520 // The following call cannot be fulfilled now.
521 ReadLoader(25, 10, buffer
);
523 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished
));
524 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 5));
525 loader_
->didFinishLoading(url_loader_
, 0, -1);
528 TEST_F(BufferedResourceLoaderTest
, RequestFailedWhenRead
) {
529 Initialize(kHttpUrl
, 10, 29);
531 PartialResponse(10, 29, 30);
536 // We should convert any error we receive to BufferedResourceLoader::kFailed.
537 ReadLoader(10, 10, buffer
);
538 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed
));
539 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed
, 0));
541 error
.reason
= net::ERR_TIMED_OUT
;
542 error
.isCancellation
= false;
543 loader_
->didFail(url_loader_
, error
);
546 TEST_F(BufferedResourceLoaderTest
, RequestFailedWithNoPendingReads
) {
547 Initialize(kHttpUrl
, 10, 29);
549 PartialResponse(10, 29, 30);
554 // Write enough data so that a read would technically complete had the request
558 // Fail without a pending read.
560 error
.reason
= net::ERR_TIMED_OUT
;
561 error
.isCancellation
= false;
562 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed
));
563 loader_
->didFail(url_loader_
, error
);
565 // Now we should immediately fail any read even if we have data buffered.
566 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed
, 0));
567 ReadLoader(10, 10, buffer
);
570 TEST_F(BufferedResourceLoaderTest
, RequestCancelledWhenRead
) {
571 Initialize(kHttpUrl
, 10, 29);
573 PartialResponse(10, 29, 30);
578 // We should convert any error we receive to BufferedResourceLoader::kFailed.
579 ReadLoader(10, 10, buffer
);
580 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed
));
581 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed
, 0));
584 error
.isCancellation
= true;
585 loader_
->didFail(url_loader_
, error
);
588 // Tests the data buffering logic of NeverDefer strategy.
589 TEST_F(BufferedResourceLoaderTest
, NeverDeferStrategy
) {
590 Initialize(kHttpUrl
, 10, 99);
591 SetLoaderBuffer(10, 20);
592 loader_
->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer
);
594 PartialResponse(10, 99, 100);
598 // Read past the buffer size; should not defer regardless.
602 // Should move past window.
603 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
604 ReadLoader(10, 10, buffer
);
609 // Tests the data buffering logic of ReadThenDefer strategy.
610 TEST_F(BufferedResourceLoaderTest
, ReadThenDeferStrategy
) {
611 Initialize(kHttpUrl
, 10, 99);
612 SetLoaderBuffer(10, 20);
613 loader_
->UpdateDeferStrategy(BufferedResourceLoader::kReadThenDefer
);
615 PartialResponse(10, 99, 100);
619 // Make an outstanding read request.
620 ReadLoader(10, 10, buffer
);
622 // Receive almost enough data to cover, shouldn't defer.
625 // As soon as we have received enough data to fulfill the read, defer.
626 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
627 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
630 VerifyBuffer(buffer
, 10, 10);
632 // Read again which should disable deferring since there should be nothing
633 // left in our internal buffer.
634 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
635 ReadLoader(20, 10, buffer
);
637 // Over-fulfill requested bytes, then deferring should be enabled again.
638 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
639 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
642 VerifyBuffer(buffer
, 20, 10);
644 // Read far ahead, which should disable deferring. In this case we still have
645 // bytes in our internal buffer.
646 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
647 ReadLoader(80, 10, buffer
);
649 // Fulfill requested bytes, then deferring should be enabled again.
650 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
651 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
654 VerifyBuffer(buffer
, 80, 10);
659 // Tests the data buffering logic of kCapacityDefer strategy.
660 TEST_F(BufferedResourceLoaderTest
, ThresholdDeferStrategy
) {
661 Initialize(kHttpUrl
, 10, 99);
662 SetLoaderBuffer(10, 20);
664 PartialResponse(10, 99, 100);
669 // Write half of capacity: keep not deferring.
672 // Write rest of space until capacity: start deferring.
673 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
676 // Read a byte from the buffer: stop deferring.
677 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 1));
678 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
679 ReadLoader(10, 1, buffer
);
681 // Write a byte to hit capacity: start deferring.
682 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
688 TEST_F(BufferedResourceLoaderTest
, Tricky_ReadForwardsPastBuffered
) {
689 Initialize(kHttpUrl
, 10, 99);
690 SetLoaderBuffer(10, 10);
692 PartialResponse(10, 99, 100);
698 WriteUntilThreshold();
699 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 1));
700 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
701 ReadLoader(10, 1, buffer
);
702 ConfirmBufferState(1, 10, 9, 10);
703 ConfirmLoaderOffsets(11, 0, 0);
705 // *** TRICKY BUSINESS, PT. I ***
706 // Read past buffered: stop deferring.
708 // In order for the read to complete we must:
709 // 1) Stop deferring to receive more data.
712 // offset=11 [xxxxxxxxx_]
713 // ^ ^^^ requested 4 bytes @ offset 20
715 // offset=24 [__________]
717 ReadLoader(20, 4, buffer
);
719 // Write a little, make sure we didn't start deferring.
722 // Write the rest, read should complete.
723 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 4));
727 ConfirmBufferState(4, 10, 0, 10);
728 ConfirmLoaderOffsets(24, 0, 0);
733 TEST_F(BufferedResourceLoaderTest
, Tricky_ReadBackwardsPastBuffered
) {
734 Initialize(kHttpUrl
, 10, 99);
735 SetLoaderBuffer(10, 10);
737 PartialResponse(10, 99, 100);
743 WriteUntilThreshold();
744 ConfirmBufferState(0, 10, 10, 10);
745 ConfirmLoaderOffsets(10, 0, 0);
747 // *** TRICKY BUSINESS, PT. II ***
748 // Read backwards a little too much: cache miss.
751 // offset=10 [__________|xxxxxxxxxx]
752 // ^ ^^^ requested 10 bytes @ offset 9
754 // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!!
756 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
757 ReadLoader(9, 4, buffer
);
760 ConfirmBufferState(0, 10, 10, 10);
761 ConfirmLoaderOffsets(10, 0, 0);
766 TEST_F(BufferedResourceLoaderTest
, Tricky_SmallReadWithinThreshold
) {
767 Initialize(kHttpUrl
, 10, 99);
768 SetLoaderBuffer(10, 10);
770 PartialResponse(10, 99, 100);
776 WriteUntilThreshold();
777 ConfirmBufferState(0, 10, 10, 10);
778 ConfirmLoaderOffsets(10, 0, 0);
780 // *** TRICKY BUSINESS, PT. III ***
781 // Read past forward capacity but within capacity: stop deferring.
783 // In order for the read to complete we must:
784 // 1) Adjust offset forward to create capacity.
785 // 2) Stop deferring to receive more data.
788 // offset=10 [xxxxxxxxxx]
789 // ^^^^ requested 4 bytes @ offset 24
791 // offset=20 [__________]
792 // ^^^^ requested 4 bytes @ offset 24
794 // offset=28 [__________]
796 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
797 ReadLoader(24, 4, buffer
);
798 ConfirmLoaderOffsets(20, 4, 8);
800 // Write a little, make sure we didn't start deferring.
803 // Write the rest, read should complete.
804 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 4));
808 ConfirmBufferState(8, 10, 0, 10);
809 ConfirmLoaderOffsets(28, 0, 0);
814 TEST_F(BufferedResourceLoaderTest
, Tricky_LargeReadWithinThreshold
) {
815 Initialize(kHttpUrl
, 10, 99);
816 SetLoaderBuffer(10, 10);
818 PartialResponse(10, 99, 100);
824 WriteUntilThreshold();
825 ConfirmBufferState(0, 10, 10, 10);
826 ConfirmLoaderOffsets(10, 0, 0);
828 // *** TRICKY BUSINESS, PT. IV ***
829 // Read a large amount past forward capacity but within
830 // capacity: stop deferring.
832 // In order for the read to complete we must:
833 // 1) Adjust offset forward to create capacity.
834 // 2) Expand capacity to make sure we don't defer as data arrives.
835 // 3) Stop deferring to receive more data.
838 // offset=10 [xxxxxxxxxx]
839 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
841 // offset=20 [__________]
842 // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24
844 // offset=20 [________________]
845 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
847 // offset=36 [__________]
849 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
850 ReadLoader(24, 12, buffer
);
851 ConfirmLoaderOffsets(20, 4, 16);
852 ConfirmBufferState(10, 10, 0, 16);
854 // Write a little, make sure we didn't start deferring.
857 // Write the rest, read should complete and capacity should go back to normal.
858 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 12));
860 ConfirmLoaderBufferForwardCapacity(10);
863 ConfirmBufferState(6, 10, 0, 10);
864 ConfirmLoaderOffsets(36, 0, 0);
869 TEST_F(BufferedResourceLoaderTest
, Tricky_LargeReadBackwards
) {
870 Initialize(kHttpUrl
, 10, 99);
871 SetLoaderBuffer(10, 10);
873 PartialResponse(10, 99, 100);
879 WriteUntilThreshold();
880 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
881 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
882 ReadLoader(10, 10, buffer
);
883 WriteUntilThreshold();
884 ConfirmBufferState(10, 10, 10, 10);
885 ConfirmLoaderOffsets(20, 0, 0);
887 // *** TRICKY BUSINESS, PT. V ***
888 // Read a large amount that involves backwards data: stop deferring.
890 // In order for the read to complete we must:
891 // 1) Adjust offset *backwards* to create capacity.
892 // 2) Expand capacity to make sure we don't defer as data arrives.
893 // 3) Stop deferring to receive more data.
896 // offset=20 [xxxxxxxxxx|xxxxxxxxxx]
897 // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16
899 // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx
900 // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16
902 // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____]
903 // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16
905 // offset=34 [xxxxxxxxxx|__________]
907 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
908 ReadLoader(16, 18, buffer
);
909 ConfirmLoaderOffsets(16, 0, 18);
910 ConfirmBufferState(6, 10, 14, 18);
912 // Write a little, make sure we didn't start deferring.
915 // Write the rest, read should complete and capacity should go back to normal.
916 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 18));
918 ConfirmLoaderBufferForwardCapacity(10);
921 ConfirmBufferState(4, 10, 0, 10);
922 ConfirmLoaderOffsets(34, 0, 0);
927 TEST_F(BufferedResourceLoaderTest
, Tricky_ReadPastThreshold
) {
928 const int kSize
= 5 * 1024 * 1024;
929 const int kThreshold
= 2 * 1024 * 1024;
931 Initialize(kHttpUrl
, 10, kSize
);
932 SetLoaderBuffer(10, 10);
934 PartialResponse(10, kSize
- 1, kSize
);
940 WriteUntilThreshold();
941 ConfirmBufferState(0, 10, 10, 10);
942 ConfirmLoaderOffsets(10, 0, 0);
944 // *** TRICKY BUSINESS, PT. VI ***
945 // Read past the forward wait threshold: cache miss.
948 // offset=10 [xxxxxxxxxx] ...
949 // ^^^^ requested 10 bytes @ threshold
951 // offset=10 [xxxxxxxxxx] !!! cache miss !!!
953 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
954 ReadLoader(kThreshold
+ 20, 10, buffer
);
957 ConfirmBufferState(0, 10, 10, 10);
958 ConfirmLoaderOffsets(10, 0, 0);
963 TEST_F(BufferedResourceLoaderTest
, HasSingleOrigin
) {
964 // Make sure no redirect case works as expected.
965 Initialize(kHttpUrl
, -1, -1);
968 EXPECT_TRUE(loader_
->HasSingleOrigin());
971 // Test redirect to the same domain.
972 Initialize(kHttpUrl
, -1, -1);
974 Redirect(kHttpRedirectToSameDomainUrl1
);
976 EXPECT_TRUE(loader_
->HasSingleOrigin());
979 // Test redirect twice to the same domain.
980 Initialize(kHttpUrl
, -1, -1);
982 Redirect(kHttpRedirectToSameDomainUrl1
);
983 Redirect(kHttpRedirectToSameDomainUrl2
);
985 EXPECT_TRUE(loader_
->HasSingleOrigin());
988 // Test redirect to a different domain.
989 Initialize(kHttpUrl
, -1, -1);
991 Redirect(kHttpRedirectToDifferentDomainUrl1
);
993 EXPECT_FALSE(loader_
->HasSingleOrigin());
996 // Test redirect to the same domain and then to a different domain.
997 Initialize(kHttpUrl
, -1, -1);
999 Redirect(kHttpRedirectToSameDomainUrl1
);
1000 Redirect(kHttpRedirectToDifferentDomainUrl1
);
1002 EXPECT_FALSE(loader_
->HasSingleOrigin());
1006 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Default
) {
1007 Initialize(kHttpUrl
, -1, -1);
1010 // Test ensures that default construction of a BufferedResourceLoader has sane
1013 // Please do not change these values in order to make a test pass! Instead,
1014 // start a conversation on what the default buffer window capacities should
1016 ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024);
1017 ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024);
1022 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Bitrate_Unknown
) {
1023 Initialize(kHttpUrl
, -1, -1);
1025 loader_
->SetBitrate(0);
1026 CheckBufferWindowBounds();
1030 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Bitrate_BelowLowerBound
) {
1031 Initialize(kHttpUrl
, -1, -1);
1033 loader_
->SetBitrate(1024 * 8); // 1 Kbps.
1034 CheckBufferWindowBounds();
1038 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Bitrate_WithinBounds
) {
1039 Initialize(kHttpUrl
, -1, -1);
1041 loader_
->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps.
1042 CheckBufferWindowBounds();
1046 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Bitrate_AboveUpperBound
) {
1047 Initialize(kHttpUrl
, -1, -1);
1049 loader_
->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps.
1050 CheckBufferWindowBounds();
1054 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_Negative
) {
1055 Initialize(kHttpUrl
, -1, -1);
1057 loader_
->SetPlaybackRate(-10);
1058 CheckBufferWindowBounds();
1062 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_Zero
) {
1063 Initialize(kHttpUrl
, -1, -1);
1065 loader_
->SetPlaybackRate(0);
1066 CheckBufferWindowBounds();
1070 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_BelowLowerBound
) {
1071 Initialize(kHttpUrl
, -1, -1);
1073 loader_
->SetPlaybackRate(0.1);
1074 CheckBufferWindowBounds();
1078 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_WithinBounds
) {
1079 Initialize(kHttpUrl
, -1, -1);
1081 loader_
->SetPlaybackRate(10);
1082 CheckBufferWindowBounds();
1086 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_AboveUpperBound
) {
1087 Initialize(kHttpUrl
, -1, -1);
1089 loader_
->SetPlaybackRate(100);
1090 CheckBufferWindowBounds();
1094 static void ExpectContentRange(
1095 const std::string
& str
, bool expect_success
,
1096 int64 expected_first
, int64 expected_last
, int64 expected_size
) {
1097 int64 first
, last
, size
;
1098 ASSERT_EQ(expect_success
, BufferedResourceLoader::ParseContentRange(
1099 str
, &first
, &last
, &size
)) << str
;
1100 if (!expect_success
)
1102 EXPECT_EQ(first
, expected_first
);
1103 EXPECT_EQ(last
, expected_last
);
1104 EXPECT_EQ(size
, expected_size
);
1107 static void ExpectContentRangeFailure(const std::string
& str
) {
1108 ExpectContentRange(str
, false, 0, 0, 0);
1111 static void ExpectContentRangeSuccess(
1112 const std::string
& str
,
1113 int64 expected_first
, int64 expected_last
, int64 expected_size
) {
1114 ExpectContentRange(str
, true, expected_first
, expected_last
, expected_size
);
1117 TEST(BufferedResourceLoaderStandaloneTest
, ParseContentRange
) {
1118 ExpectContentRangeFailure("cytes 0-499/500");
1119 ExpectContentRangeFailure("bytes 0499/500");
1120 ExpectContentRangeFailure("bytes 0-499500");
1121 ExpectContentRangeFailure("bytes 0-499/500-blorg");
1122 ExpectContentRangeFailure("bytes 0-499/500-1");
1123 ExpectContentRangeFailure("bytes 0-499/400");
1124 ExpectContentRangeFailure("bytes 0-/400");
1125 ExpectContentRangeFailure("bytes -300/400");
1126 ExpectContentRangeFailure("bytes 20-10/400");
1128 ExpectContentRangeSuccess("bytes 0-499/500", 0, 499, 500);
1129 ExpectContentRangeSuccess("bytes 0-0/500", 0, 0, 500);
1130 ExpectContentRangeSuccess("bytes 10-11/50", 10, 11, 50);
1131 ExpectContentRangeSuccess("bytes 10-11/*", 10, 11,
1132 kPositionNotSpecified
);
1135 // Tests the data buffering logic of ReadThenDefer strategy.
1136 TEST_F(BufferedResourceLoaderTest
, CancelAfterDeferral
) {
1137 Initialize(kHttpUrl
, 10, 99);
1138 SetLoaderBuffer(10, 20);
1139 loader_
->UpdateDeferStrategy(BufferedResourceLoader::kReadThenDefer
);
1140 loader_
->CancelUponDeferral();
1142 PartialResponse(10, 99, 100);
1146 // Make an outstanding read request.
1147 ReadLoader(10, 10, buffer
);
1149 // Receive almost enough data to cover, shouldn't defer.
1151 EXPECT_TRUE(HasActiveLoader());
1153 // As soon as we have received enough data to fulfill the read, defer.
1154 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
1155 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
1157 VerifyBuffer(buffer
, 10, 10);
1158 EXPECT_FALSE(HasActiveLoader());
1161 } // namespace media