1 // Copyright (c) 2012 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.h"
11 #include "base/stringprintf.h"
12 #include "media/base/media_log.h"
13 #include "media/base/seekable_buffer.h"
14 #include "net/base/net_errors.h"
15 #include "net/http/http_request_headers.h"
16 #include "net/http/http_util.h"
17 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
18 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLError.h"
19 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
20 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLResponse.h"
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
23 #include "webkit/media/buffered_resource_loader.h"
24 #include "webkit/mocks/mock_webframeclient.h"
25 #include "webkit/mocks/mock_weburlloader.h"
28 using ::testing::InSequence
;
29 using ::testing::Return
;
30 using ::testing::Truly
;
31 using ::testing::NiceMock
;
33 using WebKit::WebString
;
34 using WebKit::WebURLError
;
35 using WebKit::WebURLResponse
;
36 using WebKit::WebView
;
38 using webkit_glue::MockWebFrameClient
;
39 using webkit_glue::MockWebURLLoader
;
41 namespace webkit_media
{
43 static const char* kHttpUrl
= "http://test";
44 static const char kHttpRedirectToSameDomainUrl1
[] = "http://test/ing";
45 static const char kHttpRedirectToSameDomainUrl2
[] = "http://test/ing2";
46 static const char kHttpRedirectToDifferentDomainUrl1
[] = "http://test2";
48 static const int kDataSize
= 1024;
49 static const int kHttpOK
= 200;
50 static const int kHttpPartialContent
= 206;
58 // Predicate that tests that request disallows compressed data.
59 static bool CorrectAcceptEncoding(const WebKit::WebURLRequest
&request
) {
60 std::string value
= request
.httpHeaderField(
61 WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding
)).utf8();
62 return (value
.find("identity;q=1") != std::string::npos
) &&
63 (value
.find("*;q=0") != std::string::npos
);
66 class BufferedResourceLoaderTest
: public testing::Test
{
68 BufferedResourceLoaderTest()
69 : view_(WebView::create(NULL
)) {
70 view_
->initializeMainFrame(&client_
);
72 for (int i
= 0; i
< kDataSize
; ++i
) {
77 virtual ~BufferedResourceLoaderTest() {
81 void Initialize(const char* url
, int first_position
, int last_position
) {
83 first_position_
= first_position
;
84 last_position_
= last_position
;
86 loader_
.reset(new BufferedResourceLoader(
87 gurl_
, BufferedResourceLoader::kUnspecified
,
88 first_position_
, last_position_
,
89 BufferedResourceLoader::kCapacityDefer
, 0, 0,
90 new media::MediaLog()));
92 // |test_loader_| will be used when Start() is called.
93 url_loader_
= new NiceMock
<MockWebURLLoader
>();
94 loader_
->test_loader_
= scoped_ptr
<WebKit::WebURLLoader
>(url_loader_
);
97 void SetLoaderBuffer(int forward_capacity
, int backward_capacity
) {
98 loader_
->buffer_
.set_forward_capacity(forward_capacity
);
99 loader_
->buffer_
.set_backward_capacity(backward_capacity
);
100 loader_
->buffer_
.Clear();
105 EXPECT_CALL(*url_loader_
, loadAsynchronously(Truly(CorrectAcceptEncoding
),
108 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
110 base::Bind(&BufferedResourceLoaderTest::StartCallback
,
111 base::Unretained(this)),
112 base::Bind(&BufferedResourceLoaderTest::LoadingCallback
,
113 base::Unretained(this)),
114 base::Bind(&BufferedResourceLoaderTest::ProgressCallback
,
115 base::Unretained(this)),
119 void FullResponse(int64 instance_size
) {
120 FullResponse(instance_size
, BufferedResourceLoader::kOk
);
123 void FullResponse(int64 instance_size
,
124 BufferedResourceLoader::Status status
) {
125 EXPECT_CALL(*this, StartCallback(status
));
127 WebURLResponse
response(gurl_
);
128 response
.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
129 WebString::fromUTF8(base::StringPrintf("%"
130 PRId64
, instance_size
)));
131 response
.setExpectedContentLength(instance_size
);
132 response
.setHTTPStatusCode(kHttpOK
);
133 loader_
->didReceiveResponse(url_loader_
, response
);
135 if (status
== BufferedResourceLoader::kOk
) {
136 EXPECT_EQ(instance_size
, loader_
->content_length());
137 EXPECT_EQ(instance_size
, loader_
->instance_size());
140 EXPECT_FALSE(loader_
->range_supported());
143 void PartialResponse(int64 first_position
, int64 last_position
,
144 int64 instance_size
) {
145 PartialResponse(first_position
, last_position
, instance_size
, false, true);
148 void PartialResponse(int64 first_position
, int64 last_position
,
149 int64 instance_size
, bool chunked
, bool accept_ranges
) {
150 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kOk
));
152 WebURLResponse
response(gurl_
);
153 response
.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
154 WebString::fromUTF8(base::StringPrintf("bytes "
155 "%" PRId64
"-%" PRId64
"/%" PRId64
,
160 // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked.
161 int64 content_length
= -1;
163 response
.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"),
164 WebString::fromUTF8("chunked"));
166 content_length
= last_position
- first_position
+ 1;
168 response
.setExpectedContentLength(content_length
);
170 // A server isn't required to return Accept-Ranges even though it might.
172 response
.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
173 WebString::fromUTF8("bytes"));
176 response
.setHTTPStatusCode(kHttpPartialContent
);
177 loader_
->didReceiveResponse(url_loader_
, response
);
179 // XXX: what's the difference between these two? For example in the chunked
180 // range request case, Content-Length is unspecified (because it's chunked)
181 // but Content-Range: a-b/c can be returned, where c == Content-Length
183 // Can we eliminate one?
184 EXPECT_EQ(content_length
, loader_
->content_length());
185 EXPECT_EQ(instance_size
, loader_
->instance_size());
187 // A valid partial response should always result in this being true.
188 EXPECT_TRUE(loader_
->range_supported());
191 void Redirect(const char* url
) {
192 GURL
redirectUrl(url
);
193 WebKit::WebURLRequest
newRequest(redirectUrl
);
194 WebKit::WebURLResponse
redirectResponse(gurl_
);
196 loader_
->willSendRequest(url_loader_
, newRequest
, redirectResponse
);
198 MessageLoop::current()->RunUntilIdle();
201 void StopWhenLoad() {
203 EXPECT_CALL(*url_loader_
, cancel());
208 // Helper method to write to |loader_| from |data_|.
209 void WriteLoader(int position
, int size
) {
210 EXPECT_CALL(*this, ProgressCallback(position
+ size
- 1));
211 loader_
->didReceiveData(url_loader_
,
212 reinterpret_cast<char*>(data_
+ position
),
217 void WriteData(int size
) {
218 EXPECT_CALL(*this, ProgressCallback(_
));
220 scoped_array
<char> data(new char[size
]);
221 loader_
->didReceiveData(url_loader_
, data
.get(), size
, size
);
224 void WriteUntilThreshold() {
225 int buffered
= loader_
->buffer_
.forward_bytes();
226 int capacity
= loader_
->buffer_
.forward_capacity();
227 CHECK_LT(buffered
, capacity
);
229 EXPECT_CALL(*this, LoadingCallback(
230 BufferedResourceLoader::kLoadingDeferred
));
231 WriteData(capacity
- buffered
);
234 // Helper method to read from |loader_|.
235 void ReadLoader(int64 position
, int size
, uint8
* buffer
) {
236 loader_
->Read(position
, size
, buffer
,
237 base::Bind(&BufferedResourceLoaderTest::ReadCallback
,
238 base::Unretained(this)));
241 // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size].
242 void VerifyBuffer(uint8
* buffer
, int pos
, int size
) {
243 EXPECT_EQ(0, memcmp(buffer
, data_
+ pos
, size
));
246 void ConfirmLoaderOffsets(int64 expected_offset
,
247 int expected_first_offset
,
248 int expected_last_offset
) {
249 EXPECT_EQ(loader_
->offset_
, expected_offset
);
250 EXPECT_EQ(loader_
->first_offset_
, expected_first_offset
);
251 EXPECT_EQ(loader_
->last_offset_
, expected_last_offset
);
254 void ConfirmBufferState(int backward_bytes
,
255 int backward_capacity
,
257 int forward_capacity
) {
258 EXPECT_EQ(backward_bytes
, loader_
->buffer_
.backward_bytes());
259 EXPECT_EQ(backward_capacity
, loader_
->buffer_
.backward_capacity());
260 EXPECT_EQ(forward_bytes
, loader_
->buffer_
.forward_bytes());
261 EXPECT_EQ(forward_capacity
, loader_
->buffer_
.forward_capacity());
264 void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity
) {
265 EXPECT_EQ(loader_
->buffer_
.backward_capacity(),
266 expected_backward_capacity
);
269 void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity
) {
270 EXPECT_EQ(loader_
->buffer_
.forward_capacity(), expected_forward_capacity
);
273 // Makes sure the |loader_| buffer window is in a reasonable range.
274 void CheckBufferWindowBounds() {
275 // Corresponds to value defined in buffered_resource_loader.cc.
276 static const int kMinBufferCapacity
= 2 * 1024 * 1024;
277 EXPECT_GE(loader_
->buffer_
.forward_capacity(), kMinBufferCapacity
);
278 EXPECT_GE(loader_
->buffer_
.backward_capacity(), kMinBufferCapacity
);
280 // Corresponds to value defined in buffered_resource_loader.cc.
281 static const int kMaxBufferCapacity
= 20 * 1024 * 1024;
282 EXPECT_LE(loader_
->buffer_
.forward_capacity(), kMaxBufferCapacity
);
283 EXPECT_LE(loader_
->buffer_
.backward_capacity(), kMaxBufferCapacity
);
286 MOCK_METHOD1(StartCallback
, void(BufferedResourceLoader::Status
));
287 MOCK_METHOD2(ReadCallback
, void(BufferedResourceLoader::Status
, int));
288 MOCK_METHOD1(LoadingCallback
, void(BufferedResourceLoader::LoadingState
));
289 MOCK_METHOD1(ProgressCallback
, void(int64
));
293 int64 first_position_
;
294 int64 last_position_
;
296 scoped_ptr
<BufferedResourceLoader
> loader_
;
297 NiceMock
<MockWebURLLoader
>* url_loader_
;
299 MockWebFrameClient client_
;
302 MessageLoop message_loop_
;
304 uint8 data_
[kDataSize
];
307 DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest
);
310 TEST_F(BufferedResourceLoaderTest
, StartStop
) {
311 Initialize(kHttpUrl
, -1, -1);
316 // Tests that a bad HTTP response is recived, e.g. file not found.
317 TEST_F(BufferedResourceLoaderTest
, BadHttpResponse
) {
318 Initialize(kHttpUrl
, -1, -1);
321 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed
));
323 WebURLResponse
response(gurl_
);
324 response
.setHTTPStatusCode(404);
325 response
.setHTTPStatusText("Not Found\n");
326 loader_
->didReceiveResponse(url_loader_
, response
);
330 // Tests that partial content is requested but not fulfilled.
331 TEST_F(BufferedResourceLoaderTest
, NotPartialResponse
) {
332 Initialize(kHttpUrl
, 100, -1);
334 FullResponse(1024, BufferedResourceLoader::kFailed
);
338 // Tests that a 200 response is received.
339 TEST_F(BufferedResourceLoaderTest
, FullResponse
) {
340 Initialize(kHttpUrl
, -1, -1);
346 // Tests that a partial content response is received.
347 TEST_F(BufferedResourceLoaderTest
, PartialResponse
) {
348 Initialize(kHttpUrl
, 100, 200);
350 PartialResponse(100, 200, 1024);
354 TEST_F(BufferedResourceLoaderTest
, PartialResponse_Chunked
) {
355 Initialize(kHttpUrl
, 100, 200);
357 PartialResponse(100, 200, 1024, true, true);
361 TEST_F(BufferedResourceLoaderTest
, PartialResponse_NoAcceptRanges
) {
362 Initialize(kHttpUrl
, 100, 200);
364 PartialResponse(100, 200, 1024, false, false);
368 TEST_F(BufferedResourceLoaderTest
, PartialResponse_ChunkedNoAcceptRanges
) {
369 Initialize(kHttpUrl
, 100, 200);
371 PartialResponse(100, 200, 1024, true, false);
375 // Tests that an invalid partial response is received.
376 TEST_F(BufferedResourceLoaderTest
, InvalidPartialResponse
) {
377 Initialize(kHttpUrl
, 0, 10);
380 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed
));
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
);
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
);
397 PartialResponse(10, 29, 30);
402 // Writes 10 bytes and read them back.
404 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
405 ReadLoader(10, 10, buffer
);
406 VerifyBuffer(buffer
, 10, 10);
408 // Writes 10 bytes and read 2 times.
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);
417 // Read backward within buffer.
418 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
419 ReadLoader(10, 10, buffer
);
420 VerifyBuffer(buffer
, 10, 10);
422 // Read backward outside buffer.
423 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
424 ReadLoader(9, 10, buffer
);
426 // Response has completed.
427 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished
));
428 loader_
->didFinishLoading(url_loader_
, 0);
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);
435 // Try to read outside buffered range after request has completed.
436 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
437 ReadLoader(5, 10, buffer
);
439 // Try to read beyond the instance size.
440 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 0));
441 ReadLoader(30, 10, buffer
);
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);
449 PartialResponse(10, 0x014FFFFFF, 0x015000000);
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
));
459 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 20));
460 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
461 ReadLoader(10, 20, buffer
);
463 VerifyBuffer(buffer
, 10, 20);
464 ConfirmLoaderBufferForwardCapacity(10);
466 // Make and outstanding read request larger than forward capacity. Ensure
467 // forward capacity gets extended.
468 ReadLoader(30, 20, buffer
);
469 ConfirmLoaderBufferForwardCapacity(20);
471 // Fulfill outstanding request. Ensure forward capacity gets reset.
472 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 20));
475 VerifyBuffer(buffer
, 30, 20);
476 ConfirmLoaderBufferForwardCapacity(10);
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
);
483 ConfirmLoaderBufferForwardCapacity(10);
485 // Try to read more than maximum forward capacity. Ensure forward capacity is
487 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed
, 0));
488 ReadLoader(30, 0x01400001, buffer
);
490 ConfirmLoaderBufferForwardCapacity(10);
495 TEST_F(BufferedResourceLoaderTest
, ReadOutsideBuffer
) {
496 Initialize(kHttpUrl
, 10, 0x00FFFFFF);
498 PartialResponse(10, 0x00FFFFFF, 0x01000000);
503 // Read very far ahead will get a cache miss.
504 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
505 ReadLoader(0x00FFFFFF, 1, buffer
);
507 // The following call will not call ReadCallback() because it is waiting for
509 ReadLoader(10, 10, buffer
);
511 // Writing to loader will fulfill the read request.
512 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 10));
514 VerifyBuffer(buffer
, 10, 10);
516 // The following call cannot be fulfilled now.
517 ReadLoader(25, 10, buffer
);
519 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished
));
520 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 5));
521 loader_
->didFinishLoading(url_loader_
, 0);
524 TEST_F(BufferedResourceLoaderTest
, RequestFailedWhenRead
) {
525 Initialize(kHttpUrl
, 10, 29);
527 PartialResponse(10, 29, 30);
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));
537 error
.reason
= net::ERR_TIMED_OUT
;
538 error
.isCancellation
= false;
539 loader_
->didFail(url_loader_
, error
);
542 TEST_F(BufferedResourceLoaderTest
, RequestFailedWithNoPendingReads
) {
543 Initialize(kHttpUrl
, 10, 29);
545 PartialResponse(10, 29, 30);
550 // Write enough data so that a read would technically complete had the request
554 // Fail without a pending read.
556 error
.reason
= net::ERR_TIMED_OUT
;
557 error
.isCancellation
= false;
558 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed
));
559 loader_
->didFail(url_loader_
, error
);
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
);
566 TEST_F(BufferedResourceLoaderTest
, RequestCancelledWhenRead
) {
567 Initialize(kHttpUrl
, 10, 29);
569 PartialResponse(10, 29, 30);
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));
580 error
.isCancellation
= true;
581 loader_
->didFail(url_loader_
, error
);
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
);
590 PartialResponse(10, 99, 100);
594 // Read past the buffer size; should not defer regardless.
598 // Should move past window.
599 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
600 ReadLoader(10, 10, buffer
);
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
);
611 PartialResponse(10, 99, 100);
615 // Make an outstanding read request.
616 ReadLoader(10, 10, buffer
);
618 // Receive almost enough data to cover, shouldn't defer.
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));
626 VerifyBuffer(buffer
, 10, 10);
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
);
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));
638 VerifyBuffer(buffer
, 20, 10);
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
);
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));
650 VerifyBuffer(buffer
, 80, 10);
655 // Tests the data buffering logic of kCapacityDefer strategy.
656 TEST_F(BufferedResourceLoaderTest
, ThresholdDeferStrategy
) {
657 Initialize(kHttpUrl
, 10, 99);
658 SetLoaderBuffer(10, 20);
660 PartialResponse(10, 99, 100);
665 // Write half of capacity: keep not deferring.
668 // Write rest of space until capacity: start deferring.
669 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
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
);
677 // Write a byte to hit capacity: start deferring.
678 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred
));
684 TEST_F(BufferedResourceLoaderTest
, Tricky_ReadForwardsPastBuffered
) {
685 Initialize(kHttpUrl
, 10, 99);
686 SetLoaderBuffer(10, 10);
688 PartialResponse(10, 99, 100);
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);
701 // *** TRICKY BUSINESS, PT. I ***
702 // Read past buffered: stop deferring.
704 // In order for the read to complete we must:
705 // 1) Stop deferring to receive more data.
708 // offset=11 [xxxxxxxxx_]
709 // ^ ^^^ requested 4 bytes @ offset 20
711 // offset=24 [__________]
713 ReadLoader(20, 4, buffer
);
715 // Write a little, make sure we didn't start deferring.
718 // Write the rest, read should complete.
719 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 4));
723 ConfirmBufferState(4, 10, 0, 10);
724 ConfirmLoaderOffsets(24, 0, 0);
729 TEST_F(BufferedResourceLoaderTest
, Tricky_ReadBackwardsPastBuffered
) {
730 Initialize(kHttpUrl
, 10, 99);
731 SetLoaderBuffer(10, 10);
733 PartialResponse(10, 99, 100);
739 WriteUntilThreshold();
740 ConfirmBufferState(0, 10, 10, 10);
741 ConfirmLoaderOffsets(10, 0, 0);
743 // *** TRICKY BUSINESS, PT. II ***
744 // Read backwards a little too much: cache miss.
747 // offset=10 [__________|xxxxxxxxxx]
748 // ^ ^^^ requested 10 bytes @ offset 9
750 // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!!
752 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
753 ReadLoader(9, 4, buffer
);
756 ConfirmBufferState(0, 10, 10, 10);
757 ConfirmLoaderOffsets(10, 0, 0);
762 TEST_F(BufferedResourceLoaderTest
, Tricky_SmallReadWithinThreshold
) {
763 Initialize(kHttpUrl
, 10, 99);
764 SetLoaderBuffer(10, 10);
766 PartialResponse(10, 99, 100);
772 WriteUntilThreshold();
773 ConfirmBufferState(0, 10, 10, 10);
774 ConfirmLoaderOffsets(10, 0, 0);
776 // *** TRICKY BUSINESS, PT. III ***
777 // Read past forward capacity but within capacity: stop deferring.
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.
784 // offset=10 [xxxxxxxxxx]
785 // ^^^^ requested 4 bytes @ offset 24
787 // offset=20 [__________]
788 // ^^^^ requested 4 bytes @ offset 24
790 // offset=28 [__________]
792 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
793 ReadLoader(24, 4, buffer
);
794 ConfirmLoaderOffsets(20, 4, 8);
796 // Write a little, make sure we didn't start deferring.
799 // Write the rest, read should complete.
800 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 4));
804 ConfirmBufferState(8, 10, 0, 10);
805 ConfirmLoaderOffsets(28, 0, 0);
810 TEST_F(BufferedResourceLoaderTest
, Tricky_LargeReadWithinThreshold
) {
811 Initialize(kHttpUrl
, 10, 99);
812 SetLoaderBuffer(10, 10);
814 PartialResponse(10, 99, 100);
820 WriteUntilThreshold();
821 ConfirmBufferState(0, 10, 10, 10);
822 ConfirmLoaderOffsets(10, 0, 0);
824 // *** TRICKY BUSINESS, PT. IV ***
825 // Read a large amount past forward capacity but within
826 // capacity: stop deferring.
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.
834 // offset=10 [xxxxxxxxxx]
835 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
837 // offset=20 [__________]
838 // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24
840 // offset=20 [________________]
841 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
843 // offset=36 [__________]
845 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
846 ReadLoader(24, 12, buffer
);
847 ConfirmLoaderOffsets(20, 4, 16);
848 ConfirmBufferState(10, 10, 0, 16);
850 // Write a little, make sure we didn't start deferring.
853 // Write the rest, read should complete and capacity should go back to normal.
854 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 12));
856 ConfirmLoaderBufferForwardCapacity(10);
859 ConfirmBufferState(6, 10, 0, 10);
860 ConfirmLoaderOffsets(36, 0, 0);
865 TEST_F(BufferedResourceLoaderTest
, Tricky_LargeReadBackwards
) {
866 Initialize(kHttpUrl
, 10, 99);
867 SetLoaderBuffer(10, 10);
869 PartialResponse(10, 99, 100);
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);
883 // *** TRICKY BUSINESS, PT. V ***
884 // Read a large amount that involves backwards data: stop deferring.
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.
892 // offset=20 [xxxxxxxxxx|xxxxxxxxxx]
893 // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16
895 // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx
896 // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16
898 // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____]
899 // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16
901 // offset=34 [xxxxxxxxxx|__________]
903 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading
));
904 ReadLoader(16, 18, buffer
);
905 ConfirmLoaderOffsets(16, 0, 18);
906 ConfirmBufferState(6, 10, 14, 18);
908 // Write a little, make sure we didn't start deferring.
911 // Write the rest, read should complete and capacity should go back to normal.
912 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk
, 18));
914 ConfirmLoaderBufferForwardCapacity(10);
917 ConfirmBufferState(4, 10, 0, 10);
918 ConfirmLoaderOffsets(34, 0, 0);
923 TEST_F(BufferedResourceLoaderTest
, Tricky_ReadPastThreshold
) {
924 const int kSize
= 5 * 1024 * 1024;
925 const int kThreshold
= 2 * 1024 * 1024;
927 Initialize(kHttpUrl
, 10, kSize
);
928 SetLoaderBuffer(10, 10);
930 PartialResponse(10, kSize
- 1, kSize
);
936 WriteUntilThreshold();
937 ConfirmBufferState(0, 10, 10, 10);
938 ConfirmLoaderOffsets(10, 0, 0);
940 // *** TRICKY BUSINESS, PT. VI ***
941 // Read past the forward wait threshold: cache miss.
944 // offset=10 [xxxxxxxxxx] ...
945 // ^^^^ requested 10 bytes @ threshold
947 // offset=10 [xxxxxxxxxx] !!! cache miss !!!
949 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss
, 0));
950 ReadLoader(kThreshold
+ 20, 10, buffer
);
953 ConfirmBufferState(0, 10, 10, 10);
954 ConfirmLoaderOffsets(10, 0, 0);
959 TEST_F(BufferedResourceLoaderTest
, HasSingleOrigin
) {
960 // Make sure no redirect case works as expected.
961 Initialize(kHttpUrl
, -1, -1);
964 EXPECT_TRUE(loader_
->HasSingleOrigin());
967 // Test redirect to the same domain.
968 Initialize(kHttpUrl
, -1, -1);
970 Redirect(kHttpRedirectToSameDomainUrl1
);
972 EXPECT_TRUE(loader_
->HasSingleOrigin());
975 // Test redirect twice to the same domain.
976 Initialize(kHttpUrl
, -1, -1);
978 Redirect(kHttpRedirectToSameDomainUrl1
);
979 Redirect(kHttpRedirectToSameDomainUrl2
);
981 EXPECT_TRUE(loader_
->HasSingleOrigin());
984 // Test redirect to a different domain.
985 Initialize(kHttpUrl
, -1, -1);
987 Redirect(kHttpRedirectToDifferentDomainUrl1
);
989 EXPECT_FALSE(loader_
->HasSingleOrigin());
992 // Test redirect to the same domain and then to a different domain.
993 Initialize(kHttpUrl
, -1, -1);
995 Redirect(kHttpRedirectToSameDomainUrl1
);
996 Redirect(kHttpRedirectToDifferentDomainUrl1
);
998 EXPECT_FALSE(loader_
->HasSingleOrigin());
1002 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Default
) {
1003 Initialize(kHttpUrl
, -1, -1);
1006 // Test ensures that default construction of a BufferedResourceLoader has sane
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
1012 ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024);
1013 ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024);
1018 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Bitrate_Unknown
) {
1019 Initialize(kHttpUrl
, -1, -1);
1021 loader_
->SetBitrate(0);
1022 CheckBufferWindowBounds();
1026 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Bitrate_BelowLowerBound
) {
1027 Initialize(kHttpUrl
, -1, -1);
1029 loader_
->SetBitrate(1024 * 8); // 1 Kbps.
1030 CheckBufferWindowBounds();
1034 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Bitrate_WithinBounds
) {
1035 Initialize(kHttpUrl
, -1, -1);
1037 loader_
->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps.
1038 CheckBufferWindowBounds();
1042 TEST_F(BufferedResourceLoaderTest
, BufferWindow_Bitrate_AboveUpperBound
) {
1043 Initialize(kHttpUrl
, -1, -1);
1045 loader_
->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps.
1046 CheckBufferWindowBounds();
1050 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_Negative
) {
1051 Initialize(kHttpUrl
, -1, -1);
1053 loader_
->SetPlaybackRate(-10);
1054 CheckBufferWindowBounds();
1058 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_Zero
) {
1059 Initialize(kHttpUrl
, -1, -1);
1061 loader_
->SetPlaybackRate(0);
1062 CheckBufferWindowBounds();
1066 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_BelowLowerBound
) {
1067 Initialize(kHttpUrl
, -1, -1);
1069 loader_
->SetPlaybackRate(0.1f
);
1070 CheckBufferWindowBounds();
1074 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_WithinBounds
) {
1075 Initialize(kHttpUrl
, -1, -1);
1077 loader_
->SetPlaybackRate(10);
1078 CheckBufferWindowBounds();
1082 TEST_F(BufferedResourceLoaderTest
, BufferWindow_PlaybackRate_AboveUpperBound
) {
1083 Initialize(kHttpUrl
, -1, -1);
1085 loader_
->SetPlaybackRate(100);
1086 CheckBufferWindowBounds();
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
)
1098 EXPECT_EQ(first
, expected_first
);
1099 EXPECT_EQ(last
, expected_last
);
1100 EXPECT_EQ(size
, expected_size
);
1103 static void ExpectContentRangeFailure(const std::string
& str
) {
1104 ExpectContentRange(str
, false, 0, 0, 0);
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
);
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");
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
);
1131 } // namespace webkit_media