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 "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"
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;
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";
45 static const int kDataSize = 1024;
46 static const int kHttpOK = 200;
47 static const int kHttpPartialContent = 206;
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);
63 class BufferedResourceLoaderTest : public testing::Test {
65 BufferedResourceLoaderTest()
66 : view_(WebView::create(NULL)) {
67 view_->initializeMainFrame(&client_);
69 for (int i = 0; i < kDataSize; ++i) {
74 virtual ~BufferedResourceLoaderTest() {
78 void Initialize(const char* url, int first_position, int last_position) {
80 first_position_ = first_position;
81 last_position_ = last_position;
83 loader_.reset(new BufferedResourceLoader(
84 gurl_, BufferedResourceLoader::kUnspecified,
85 first_position_, last_position_,
86 BufferedResourceLoader::kCapacityDefer, 0, 0,
87 new media::MediaLog()));
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_);
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();
102 EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding),
105 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
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)),
116 void FullResponse(int64 instance_size) {
117 FullResponse(instance_size, BufferedResourceLoader::kOk);
120 void FullResponse(int64 instance_size,
121 BufferedResourceLoader::Status status) {
122 EXPECT_CALL(*this, StartCallback(status));
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);
132 if (status == BufferedResourceLoader::kOk) {
133 EXPECT_EQ(instance_size, loader_->content_length());
134 EXPECT_EQ(instance_size, loader_->instance_size());
137 EXPECT_FALSE(loader_->range_supported());
140 void PartialResponse(int64 first_position, int64 last_position,
141 int64 instance_size) {
142 PartialResponse(first_position, last_position, instance_size, false, true);
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));
149 WebURLResponse response(gurl_);
150 response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
151 WebString::fromUTF8(base::StringPrintf("bytes "
152 "%" PRId64 "-%" PRId64 "/%" PRId64,
157 // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked.
158 int64 content_length = -1;
160 response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"),
161 WebString::fromUTF8("chunked"));
163 content_length = last_position - first_position + 1;
165 response.setExpectedContentLength(content_length);
167 // A server isn't required to return Accept-Ranges even though it might.
169 response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
170 WebString::fromUTF8("bytes"));
173 response.setHTTPStatusCode(kHttpPartialContent);
174 loader_->didReceiveResponse(url_loader_, response);
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
180 // Can we eliminate one?
181 EXPECT_EQ(content_length, loader_->content_length());
182 EXPECT_EQ(instance_size, loader_->instance_size());
184 // A valid partial response should always result in this being true.
185 EXPECT_TRUE(loader_->range_supported());
188 void Redirect(const char* url) {
189 GURL redirectUrl(url);
190 WebKit::WebURLRequest newRequest(redirectUrl);
191 WebKit::WebURLResponse redirectResponse(gurl_);
193 loader_->willSendRequest(url_loader_, newRequest, redirectResponse);
195 base::MessageLoop::current()->RunUntilIdle();
198 void StopWhenLoad() {
200 EXPECT_CALL(*url_loader_, cancel());
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),
214 void WriteData(int size) {
215 EXPECT_CALL(*this, ProgressCallback(_));
217 scoped_ptr<char[]> data(new char[size]);
218 loader_->didReceiveData(url_loader_, data.get(), size, size);
221 void WriteUntilThreshold() {
222 int buffered = loader_->buffer_.forward_bytes();
223 int capacity = loader_->buffer_.forward_capacity();
224 CHECK_LT(buffered, capacity);
226 EXPECT_CALL(*this, LoadingCallback(
227 BufferedResourceLoader::kLoadingDeferred));
228 WriteData(capacity - buffered);
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)));
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));
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);
251 void ConfirmBufferState(int backward_bytes,
252 int backward_capacity,
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());
261 void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity) {
262 EXPECT_EQ(loader_->buffer_.backward_capacity(),
263 expected_backward_capacity);
266 void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity) {
267 EXPECT_EQ(loader_->buffer_.forward_capacity(), expected_forward_capacity);
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);
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);
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));
290 int64 first_position_;
291 int64 last_position_;
293 scoped_ptr<BufferedResourceLoader> loader_;
294 NiceMock<MockWebURLLoader>* url_loader_;
296 MockWebFrameClient client_;
299 base::MessageLoop message_loop_;
301 uint8 data_[kDataSize];
304 DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest);
307 TEST_F(BufferedResourceLoaderTest, StartStop) {
308 Initialize(kHttpUrl, -1, -1);
313 // Tests that a bad HTTP response is recived, e.g. file not found.
314 TEST_F(BufferedResourceLoaderTest, BadHttpResponse) {
315 Initialize(kHttpUrl, -1, -1);
318 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed));
320 WebURLResponse response(gurl_);
321 response.setHTTPStatusCode(404);
322 response.setHTTPStatusText("Not Found\n");
323 loader_->didReceiveResponse(url_loader_, response);
327 // Tests that partial content is requested but not fulfilled.
328 TEST_F(BufferedResourceLoaderTest, NotPartialResponse) {
329 Initialize(kHttpUrl, 100, -1);
331 FullResponse(1024, BufferedResourceLoader::kFailed);
335 // Tests that a 200 response is received.
336 TEST_F(BufferedResourceLoaderTest, FullResponse) {
337 Initialize(kHttpUrl, -1, -1);
343 // Tests that a partial content response is received.
344 TEST_F(BufferedResourceLoaderTest, PartialResponse) {
345 Initialize(kHttpUrl, 100, 200);
347 PartialResponse(100, 200, 1024);
351 TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) {
352 Initialize(kHttpUrl, 100, 200);
354 PartialResponse(100, 200, 1024, true, true);
358 TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) {
359 Initialize(kHttpUrl, 100, 200);
361 PartialResponse(100, 200, 1024, false, false);
365 TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) {
366 Initialize(kHttpUrl, 100, 200);
368 PartialResponse(100, 200, 1024, true, false);
372 // Tests that an invalid partial response is received.
373 TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) {
374 Initialize(kHttpUrl, 0, 10);
377 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed));
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);
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);
394 PartialResponse(10, 29, 30);
399 // Writes 10 bytes and read them back.
401 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
402 ReadLoader(10, 10, buffer);
403 VerifyBuffer(buffer, 10, 10);
405 // Writes 10 bytes and read 2 times.
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);
414 // Read backward within buffer.
415 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
416 ReadLoader(10, 10, buffer);
417 VerifyBuffer(buffer, 10, 10);
419 // Read backward outside buffer.
420 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
421 ReadLoader(9, 10, buffer);
423 // Response has completed.
424 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished));
425 loader_->didFinishLoading(url_loader_, 0);
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);
432 // Try to read outside buffered range after request has completed.
433 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
434 ReadLoader(5, 10, buffer);
436 // Try to read beyond the instance size.
437 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 0));
438 ReadLoader(30, 10, buffer);
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);
446 PartialResponse(10, 0x014FFFFFF, 0x015000000);
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));
456 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20));
457 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
458 ReadLoader(10, 20, buffer);
460 VerifyBuffer(buffer, 10, 20);
461 ConfirmLoaderBufferForwardCapacity(10);
463 // Make and outstanding read request larger than forward capacity. Ensure
464 // forward capacity gets extended.
465 ReadLoader(30, 20, buffer);
466 ConfirmLoaderBufferForwardCapacity(20);
468 // Fulfill outstanding request. Ensure forward capacity gets reset.
469 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20));
472 VerifyBuffer(buffer, 30, 20);
473 ConfirmLoaderBufferForwardCapacity(10);
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);
480 ConfirmLoaderBufferForwardCapacity(10);
482 // Try to read more than maximum forward capacity. Ensure forward capacity is
484 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
485 ReadLoader(30, 0x01400001, buffer);
487 ConfirmLoaderBufferForwardCapacity(10);
492 TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) {
493 Initialize(kHttpUrl, 10, 0x00FFFFFF);
495 PartialResponse(10, 0x00FFFFFF, 0x01000000);
500 // Read very far ahead will get a cache miss.
501 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
502 ReadLoader(0x00FFFFFF, 1, buffer);
504 // The following call will not call ReadCallback() because it is waiting for
506 ReadLoader(10, 10, buffer);
508 // Writing to loader will fulfill the read request.
509 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
511 VerifyBuffer(buffer, 10, 10);
513 // The following call cannot be fulfilled now.
514 ReadLoader(25, 10, buffer);
516 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished));
517 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
518 loader_->didFinishLoading(url_loader_, 0);
521 TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) {
522 Initialize(kHttpUrl, 10, 29);
524 PartialResponse(10, 29, 30);
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));
534 error.reason = net::ERR_TIMED_OUT;
535 error.isCancellation = false;
536 loader_->didFail(url_loader_, error);
539 TEST_F(BufferedResourceLoaderTest, RequestFailedWithNoPendingReads) {
540 Initialize(kHttpUrl, 10, 29);
542 PartialResponse(10, 29, 30);
547 // Write enough data so that a read would technically complete had the request
551 // Fail without a pending read.
553 error.reason = net::ERR_TIMED_OUT;
554 error.isCancellation = false;
555 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
556 loader_->didFail(url_loader_, error);
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);
563 TEST_F(BufferedResourceLoaderTest, RequestCancelledWhenRead) {
564 Initialize(kHttpUrl, 10, 29);
566 PartialResponse(10, 29, 30);
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));
577 error.isCancellation = true;
578 loader_->didFail(url_loader_, error);
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);
587 PartialResponse(10, 99, 100);
591 // Read past the buffer size; should not defer regardless.
595 // Should move past window.
596 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
597 ReadLoader(10, 10, buffer);
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);
608 PartialResponse(10, 99, 100);
612 // Make an outstanding read request.
613 ReadLoader(10, 10, buffer);
615 // Receive almost enough data to cover, shouldn't defer.
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));
623 VerifyBuffer(buffer, 10, 10);
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);
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));
635 VerifyBuffer(buffer, 20, 10);
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);
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));
647 VerifyBuffer(buffer, 80, 10);
652 // Tests the data buffering logic of kCapacityDefer strategy.
653 TEST_F(BufferedResourceLoaderTest, ThresholdDeferStrategy) {
654 Initialize(kHttpUrl, 10, 99);
655 SetLoaderBuffer(10, 20);
657 PartialResponse(10, 99, 100);
662 // Write half of capacity: keep not deferring.
665 // Write rest of space until capacity: start deferring.
666 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
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);
674 // Write a byte to hit capacity: start deferring.
675 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
681 TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) {
682 Initialize(kHttpUrl, 10, 99);
683 SetLoaderBuffer(10, 10);
685 PartialResponse(10, 99, 100);
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);
698 // *** TRICKY BUSINESS, PT. I ***
699 // Read past buffered: stop deferring.
701 // In order for the read to complete we must:
702 // 1) Stop deferring to receive more data.
705 // offset=11 [xxxxxxxxx_]
706 // ^ ^^^ requested 4 bytes @ offset 20
708 // offset=24 [__________]
710 ReadLoader(20, 4, buffer);
712 // Write a little, make sure we didn't start deferring.
715 // Write the rest, read should complete.
716 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
720 ConfirmBufferState(4, 10, 0, 10);
721 ConfirmLoaderOffsets(24, 0, 0);
726 TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) {
727 Initialize(kHttpUrl, 10, 99);
728 SetLoaderBuffer(10, 10);
730 PartialResponse(10, 99, 100);
736 WriteUntilThreshold();
737 ConfirmBufferState(0, 10, 10, 10);
738 ConfirmLoaderOffsets(10, 0, 0);
740 // *** TRICKY BUSINESS, PT. II ***
741 // Read backwards a little too much: cache miss.
744 // offset=10 [__________|xxxxxxxxxx]
745 // ^ ^^^ requested 10 bytes @ offset 9
747 // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!!
749 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
750 ReadLoader(9, 4, buffer);
753 ConfirmBufferState(0, 10, 10, 10);
754 ConfirmLoaderOffsets(10, 0, 0);
759 TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) {
760 Initialize(kHttpUrl, 10, 99);
761 SetLoaderBuffer(10, 10);
763 PartialResponse(10, 99, 100);
769 WriteUntilThreshold();
770 ConfirmBufferState(0, 10, 10, 10);
771 ConfirmLoaderOffsets(10, 0, 0);
773 // *** TRICKY BUSINESS, PT. III ***
774 // Read past forward capacity but within capacity: stop deferring.
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.
781 // offset=10 [xxxxxxxxxx]
782 // ^^^^ requested 4 bytes @ offset 24
784 // offset=20 [__________]
785 // ^^^^ requested 4 bytes @ offset 24
787 // offset=28 [__________]
789 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
790 ReadLoader(24, 4, buffer);
791 ConfirmLoaderOffsets(20, 4, 8);
793 // Write a little, make sure we didn't start deferring.
796 // Write the rest, read should complete.
797 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
801 ConfirmBufferState(8, 10, 0, 10);
802 ConfirmLoaderOffsets(28, 0, 0);
807 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) {
808 Initialize(kHttpUrl, 10, 99);
809 SetLoaderBuffer(10, 10);
811 PartialResponse(10, 99, 100);
817 WriteUntilThreshold();
818 ConfirmBufferState(0, 10, 10, 10);
819 ConfirmLoaderOffsets(10, 0, 0);
821 // *** TRICKY BUSINESS, PT. IV ***
822 // Read a large amount past forward capacity but within
823 // capacity: stop deferring.
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.
831 // offset=10 [xxxxxxxxxx]
832 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
834 // offset=20 [__________]
835 // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24
837 // offset=20 [________________]
838 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
840 // offset=36 [__________]
842 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
843 ReadLoader(24, 12, buffer);
844 ConfirmLoaderOffsets(20, 4, 16);
845 ConfirmBufferState(10, 10, 0, 16);
847 // Write a little, make sure we didn't start deferring.
850 // Write the rest, read should complete and capacity should go back to normal.
851 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 12));
853 ConfirmLoaderBufferForwardCapacity(10);
856 ConfirmBufferState(6, 10, 0, 10);
857 ConfirmLoaderOffsets(36, 0, 0);
862 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) {
863 Initialize(kHttpUrl, 10, 99);
864 SetLoaderBuffer(10, 10);
866 PartialResponse(10, 99, 100);
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);
880 // *** TRICKY BUSINESS, PT. V ***
881 // Read a large amount that involves backwards data: stop deferring.
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.
889 // offset=20 [xxxxxxxxxx|xxxxxxxxxx]
890 // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16
892 // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx
893 // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16
895 // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____]
896 // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16
898 // offset=34 [xxxxxxxxxx|__________]
900 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
901 ReadLoader(16, 18, buffer);
902 ConfirmLoaderOffsets(16, 0, 18);
903 ConfirmBufferState(6, 10, 14, 18);
905 // Write a little, make sure we didn't start deferring.
908 // Write the rest, read should complete and capacity should go back to normal.
909 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 18));
911 ConfirmLoaderBufferForwardCapacity(10);
914 ConfirmBufferState(4, 10, 0, 10);
915 ConfirmLoaderOffsets(34, 0, 0);
920 TEST_F(BufferedResourceLoaderTest, Tricky_ReadPastThreshold) {
921 const int kSize = 5 * 1024 * 1024;
922 const int kThreshold = 2 * 1024 * 1024;
924 Initialize(kHttpUrl, 10, kSize);
925 SetLoaderBuffer(10, 10);
927 PartialResponse(10, kSize - 1, kSize);
933 WriteUntilThreshold();
934 ConfirmBufferState(0, 10, 10, 10);
935 ConfirmLoaderOffsets(10, 0, 0);
937 // *** TRICKY BUSINESS, PT. VI ***
938 // Read past the forward wait threshold: cache miss.
941 // offset=10 [xxxxxxxxxx] ...
942 // ^^^^ requested 10 bytes @ threshold
944 // offset=10 [xxxxxxxxxx] !!! cache miss !!!
946 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
947 ReadLoader(kThreshold + 20, 10, buffer);
950 ConfirmBufferState(0, 10, 10, 10);
951 ConfirmLoaderOffsets(10, 0, 0);
956 TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) {
957 // Make sure no redirect case works as expected.
958 Initialize(kHttpUrl, -1, -1);
961 EXPECT_TRUE(loader_->HasSingleOrigin());
964 // Test redirect to the same domain.
965 Initialize(kHttpUrl, -1, -1);
967 Redirect(kHttpRedirectToSameDomainUrl1);
969 EXPECT_TRUE(loader_->HasSingleOrigin());
972 // Test redirect twice to the same domain.
973 Initialize(kHttpUrl, -1, -1);
975 Redirect(kHttpRedirectToSameDomainUrl1);
976 Redirect(kHttpRedirectToSameDomainUrl2);
978 EXPECT_TRUE(loader_->HasSingleOrigin());
981 // Test redirect to a different domain.
982 Initialize(kHttpUrl, -1, -1);
984 Redirect(kHttpRedirectToDifferentDomainUrl1);
986 EXPECT_FALSE(loader_->HasSingleOrigin());
989 // Test redirect to the same domain and then to a different domain.
990 Initialize(kHttpUrl, -1, -1);
992 Redirect(kHttpRedirectToSameDomainUrl1);
993 Redirect(kHttpRedirectToDifferentDomainUrl1);
995 EXPECT_FALSE(loader_->HasSingleOrigin());
999 TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) {
1000 Initialize(kHttpUrl, -1, -1);
1003 // Test ensures that default construction of a BufferedResourceLoader has sane
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
1009 ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024);
1010 ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024);
1015 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) {
1016 Initialize(kHttpUrl, -1, -1);
1018 loader_->SetBitrate(0);
1019 CheckBufferWindowBounds();
1023 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_BelowLowerBound) {
1024 Initialize(kHttpUrl, -1, -1);
1026 loader_->SetBitrate(1024 * 8); // 1 Kbps.
1027 CheckBufferWindowBounds();
1031 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_WithinBounds) {
1032 Initialize(kHttpUrl, -1, -1);
1034 loader_->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps.
1035 CheckBufferWindowBounds();
1039 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_AboveUpperBound) {
1040 Initialize(kHttpUrl, -1, -1);
1042 loader_->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps.
1043 CheckBufferWindowBounds();
1047 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) {
1048 Initialize(kHttpUrl, -1, -1);
1050 loader_->SetPlaybackRate(-10);
1051 CheckBufferWindowBounds();
1055 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) {
1056 Initialize(kHttpUrl, -1, -1);
1058 loader_->SetPlaybackRate(0);
1059 CheckBufferWindowBounds();
1063 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) {
1064 Initialize(kHttpUrl, -1, -1);
1066 loader_->SetPlaybackRate(0.1f);
1067 CheckBufferWindowBounds();
1071 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) {
1072 Initialize(kHttpUrl, -1, -1);
1074 loader_->SetPlaybackRate(10);
1075 CheckBufferWindowBounds();
1079 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) {
1080 Initialize(kHttpUrl, -1, -1);
1082 loader_->SetPlaybackRate(100);
1083 CheckBufferWindowBounds();
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)
1095 EXPECT_EQ(first, expected_first);
1096 EXPECT_EQ(last, expected_last);
1097 EXPECT_EQ(size, expected_size);
1100 static void ExpectContentRangeFailure(const std::string& str) {
1101 ExpectContentRange(str, false, 0, 0, 0);
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);
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");
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);
1128 } // namespace content