Update V8 to version 4.5.80.
[chromium-blink-merge.git] / media / blink / buffered_resource_loader_unittest.cc
blob5a15f7197d0ec39837ce0d470c8248ea331587f9
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.
5 #include <algorithm>
6 #include <string>
8 #include "base/bind.h"
9 #include "base/format_macros.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/stringprintf.h"
12 #include "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"
27 using ::testing::_;
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;
37 using blink::WebView;
39 namespace media {
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;
50 enum NetworkState {
51 NONE,
52 LOADED,
53 LOADING
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 {
65 public:
66 BufferedResourceLoaderTest()
67 : view_(WebView::create(NULL)),
68 frame_(WebLocalFrame::create(blink::WebTreeScopeType::Document,
69 &client_)) {
70 view_->setMainFrame(frame_);
72 for (int i = 0; i < kDataSize; ++i) {
73 data_[i] = i;
77 virtual ~BufferedResourceLoaderTest() {
78 view_->close();
79 frame_->close();
82 void Initialize(const char* url, int first_position, int last_position) {
83 gurl_ = GURL(url);
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,
91 new MediaLog()));
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();
104 void Start() {
105 InSequence s;
106 EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding),
107 loader_.get()));
109 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
110 loader_->Start(
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)),
117 view_->mainFrame());
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,
157 first_position,
158 last_position,
159 instance_size)));
161 // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked.
162 int64 content_length = -1;
163 if (chunked) {
164 response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"),
165 WebString::fromUTF8("chunked"));
166 } else {
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.
172 if (accept_ranges) {
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() {
203 InSequence s;
204 EXPECT_CALL(*url_loader_, cancel());
205 loader_->Stop();
206 loader_.reset();
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),
214 size,
215 size);
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,
257 int forward_bytes,
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));
294 protected:
295 GURL gurl_;
296 int64 first_position_;
297 int64 last_position_;
299 scoped_ptr<BufferedResourceLoader> loader_;
300 NiceMock<MockWebURLLoader>* url_loader_;
302 MockWebFrameClient client_;
303 WebView* view_;
304 WebLocalFrame* frame_;
306 base::MessageLoop message_loop_;
308 uint8 data_[kDataSize];
310 private:
311 DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest);
314 TEST_F(BufferedResourceLoaderTest, StartStop) {
315 Initialize(kHttpUrl, -1, -1);
316 Start();
317 StopWhenLoad();
320 // Tests that a bad HTTP response is recived, e.g. file not found.
321 TEST_F(BufferedResourceLoaderTest, BadHttpResponse) {
322 Initialize(kHttpUrl, -1, -1);
323 Start();
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);
331 StopWhenLoad();
334 // Tests that partial content is requested but not fulfilled.
335 TEST_F(BufferedResourceLoaderTest, NotPartialResponse) {
336 Initialize(kHttpUrl, 100, -1);
337 Start();
338 FullResponse(1024, BufferedResourceLoader::kFailed);
339 StopWhenLoad();
342 // Tests that a 200 response is received.
343 TEST_F(BufferedResourceLoaderTest, FullResponse) {
344 Initialize(kHttpUrl, -1, -1);
345 Start();
346 FullResponse(1024);
347 StopWhenLoad();
350 // Tests that a partial content response is received.
351 TEST_F(BufferedResourceLoaderTest, PartialResponse) {
352 Initialize(kHttpUrl, 100, 200);
353 Start();
354 PartialResponse(100, 200, 1024);
355 StopWhenLoad();
358 TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) {
359 Initialize(kHttpUrl, 100, 200);
360 Start();
361 PartialResponse(100, 200, 1024, true, true);
362 StopWhenLoad();
365 TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) {
366 Initialize(kHttpUrl, 100, 200);
367 Start();
368 PartialResponse(100, 200, 1024, false, false);
369 StopWhenLoad();
372 TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) {
373 Initialize(kHttpUrl, 100, 200);
374 Start();
375 PartialResponse(100, 200, 1024, true, false);
376 StopWhenLoad();
379 // Tests that an invalid partial response is received.
380 TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) {
381 Initialize(kHttpUrl, 0, 10);
382 Start();
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);
393 StopWhenLoad();
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);
400 Start();
401 PartialResponse(10, 29, 30);
403 uint8 buffer[10];
404 InSequence s;
406 // Writes 10 bytes and read them back.
407 WriteLoader(10, 10);
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.
413 WriteLoader(20, 10);
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);
452 Start();
453 PartialResponse(10, 0x014FFFFFF, 0x015000000);
455 uint8 buffer[20];
456 InSequence s;
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));
461 WriteLoader(10, 20);
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));
477 WriteLoader(30, 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
490 // not changed.
491 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
492 ReadLoader(30, 0x01400001, buffer);
494 ConfirmLoaderBufferForwardCapacity(10);
496 StopWhenLoad();
499 TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) {
500 Initialize(kHttpUrl, 10, 0x00FFFFFF);
501 Start();
502 PartialResponse(10, 0x00FFFFFF, 0x01000000);
504 uint8 buffer[10];
505 InSequence s;
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
512 // data to arrive.
513 ReadLoader(10, 10, buffer);
515 // Writing to loader will fulfill the read request.
516 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
517 WriteLoader(10, 20);
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);
530 Start();
531 PartialResponse(10, 29, 30);
533 uint8 buffer[10];
534 InSequence s;
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));
540 WebURLError error;
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);
548 Start();
549 PartialResponse(10, 29, 30);
551 uint8 buffer[10];
552 InSequence s;
554 // Write enough data so that a read would technically complete had the request
555 // not failed.
556 WriteLoader(10, 20);
558 // Fail without a pending read.
559 WebURLError error;
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);
572 Start();
573 PartialResponse(10, 29, 30);
575 uint8 buffer[10];
576 InSequence s;
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));
582 WebURLError error;
583 error.reason = 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);
593 Start();
594 PartialResponse(10, 99, 100);
596 uint8 buffer[10];
598 // Read past the buffer size; should not defer regardless.
599 WriteLoader(10, 10);
600 WriteLoader(20, 50);
602 // Should move past window.
603 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
604 ReadLoader(10, 10, buffer);
606 StopWhenLoad();
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);
614 Start();
615 PartialResponse(10, 99, 100);
617 uint8 buffer[10];
619 // Make an outstanding read request.
620 ReadLoader(10, 10, buffer);
622 // Receive almost enough data to cover, shouldn't defer.
623 WriteLoader(10, 9);
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));
628 WriteLoader(19, 1);
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));
640 WriteLoader(20, 40);
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));
652 WriteLoader(60, 40);
654 VerifyBuffer(buffer, 80, 10);
656 StopWhenLoad();
659 // Tests the data buffering logic of kCapacityDefer strategy.
660 TEST_F(BufferedResourceLoaderTest, ThresholdDeferStrategy) {
661 Initialize(kHttpUrl, 10, 99);
662 SetLoaderBuffer(10, 20);
663 Start();
664 PartialResponse(10, 99, 100);
666 uint8 buffer[10];
667 InSequence s;
669 // Write half of capacity: keep not deferring.
670 WriteData(5);
672 // Write rest of space until capacity: start deferring.
673 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
674 WriteData(5);
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));
683 WriteData(6);
685 StopWhenLoad();
688 TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) {
689 Initialize(kHttpUrl, 10, 99);
690 SetLoaderBuffer(10, 10);
691 Start();
692 PartialResponse(10, 99, 100);
694 uint8 buffer[256];
695 InSequence s;
697 // PRECONDITION
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.
711 // BEFORE
712 // offset=11 [xxxxxxxxx_]
713 // ^ ^^^ requested 4 bytes @ offset 20
714 // AFTER
715 // offset=24 [__________]
717 ReadLoader(20, 4, buffer);
719 // Write a little, make sure we didn't start deferring.
720 WriteData(2);
722 // Write the rest, read should complete.
723 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
724 WriteData(2);
726 // POSTCONDITION
727 ConfirmBufferState(4, 10, 0, 10);
728 ConfirmLoaderOffsets(24, 0, 0);
730 StopWhenLoad();
733 TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) {
734 Initialize(kHttpUrl, 10, 99);
735 SetLoaderBuffer(10, 10);
736 Start();
737 PartialResponse(10, 99, 100);
739 uint8 buffer[256];
740 InSequence s;
742 // PRECONDITION
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.
750 // BEFORE
751 // offset=10 [__________|xxxxxxxxxx]
752 // ^ ^^^ requested 10 bytes @ offset 9
753 // AFTER
754 // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!!
756 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
757 ReadLoader(9, 4, buffer);
759 // POSTCONDITION
760 ConfirmBufferState(0, 10, 10, 10);
761 ConfirmLoaderOffsets(10, 0, 0);
763 StopWhenLoad();
766 TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) {
767 Initialize(kHttpUrl, 10, 99);
768 SetLoaderBuffer(10, 10);
769 Start();
770 PartialResponse(10, 99, 100);
772 uint8 buffer[256];
773 InSequence s;
775 // PRECONDITION
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.
787 // BEFORE
788 // offset=10 [xxxxxxxxxx]
789 // ^^^^ requested 4 bytes @ offset 24
790 // ADJUSTED OFFSET
791 // offset=20 [__________]
792 // ^^^^ requested 4 bytes @ offset 24
793 // AFTER
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.
801 WriteData(4);
803 // Write the rest, read should complete.
804 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
805 WriteData(4);
807 // POSTCONDITION
808 ConfirmBufferState(8, 10, 0, 10);
809 ConfirmLoaderOffsets(28, 0, 0);
811 StopWhenLoad();
814 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) {
815 Initialize(kHttpUrl, 10, 99);
816 SetLoaderBuffer(10, 10);
817 Start();
818 PartialResponse(10, 99, 100);
820 uint8 buffer[256];
821 InSequence s;
823 // PRECONDITION
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.
837 // BEFORE
838 // offset=10 [xxxxxxxxxx]
839 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
840 // ADJUSTED OFFSET
841 // offset=20 [__________]
842 // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24
843 // ADJUSTED CAPACITY
844 // offset=20 [________________]
845 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
846 // AFTER
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.
855 WriteData(10);
857 // Write the rest, read should complete and capacity should go back to normal.
858 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 12));
859 WriteData(6);
860 ConfirmLoaderBufferForwardCapacity(10);
862 // POSTCONDITION
863 ConfirmBufferState(6, 10, 0, 10);
864 ConfirmLoaderOffsets(36, 0, 0);
866 StopWhenLoad();
869 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) {
870 Initialize(kHttpUrl, 10, 99);
871 SetLoaderBuffer(10, 10);
872 Start();
873 PartialResponse(10, 99, 100);
875 uint8 buffer[256];
876 InSequence s;
878 // PRECONDITION
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.
895 // BEFORE
896 // offset=20 [xxxxxxxxxx|xxxxxxxxxx]
897 // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16
898 // ADJUSTED OFFSET
899 // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx
900 // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16
901 // ADJUSTED CAPACITY
902 // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____]
903 // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16
904 // AFTER
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.
913 WriteData(2);
915 // Write the rest, read should complete and capacity should go back to normal.
916 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 18));
917 WriteData(2);
918 ConfirmLoaderBufferForwardCapacity(10);
920 // POSTCONDITION
921 ConfirmBufferState(4, 10, 0, 10);
922 ConfirmLoaderOffsets(34, 0, 0);
924 StopWhenLoad();
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);
933 Start();
934 PartialResponse(10, kSize - 1, kSize);
936 uint8 buffer[256];
937 InSequence s;
939 // PRECONDITION
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.
947 // BEFORE
948 // offset=10 [xxxxxxxxxx] ...
949 // ^^^^ requested 10 bytes @ threshold
950 // AFTER
951 // offset=10 [xxxxxxxxxx] !!! cache miss !!!
953 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
954 ReadLoader(kThreshold + 20, 10, buffer);
956 // POSTCONDITION
957 ConfirmBufferState(0, 10, 10, 10);
958 ConfirmLoaderOffsets(10, 0, 0);
960 StopWhenLoad();
963 TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) {
964 // Make sure no redirect case works as expected.
965 Initialize(kHttpUrl, -1, -1);
966 Start();
967 FullResponse(1024);
968 EXPECT_TRUE(loader_->HasSingleOrigin());
969 StopWhenLoad();
971 // Test redirect to the same domain.
972 Initialize(kHttpUrl, -1, -1);
973 Start();
974 Redirect(kHttpRedirectToSameDomainUrl1);
975 FullResponse(1024);
976 EXPECT_TRUE(loader_->HasSingleOrigin());
977 StopWhenLoad();
979 // Test redirect twice to the same domain.
980 Initialize(kHttpUrl, -1, -1);
981 Start();
982 Redirect(kHttpRedirectToSameDomainUrl1);
983 Redirect(kHttpRedirectToSameDomainUrl2);
984 FullResponse(1024);
985 EXPECT_TRUE(loader_->HasSingleOrigin());
986 StopWhenLoad();
988 // Test redirect to a different domain.
989 Initialize(kHttpUrl, -1, -1);
990 Start();
991 Redirect(kHttpRedirectToDifferentDomainUrl1);
992 FullResponse(1024);
993 EXPECT_FALSE(loader_->HasSingleOrigin());
994 StopWhenLoad();
996 // Test redirect to the same domain and then to a different domain.
997 Initialize(kHttpUrl, -1, -1);
998 Start();
999 Redirect(kHttpRedirectToSameDomainUrl1);
1000 Redirect(kHttpRedirectToDifferentDomainUrl1);
1001 FullResponse(1024);
1002 EXPECT_FALSE(loader_->HasSingleOrigin());
1003 StopWhenLoad();
1006 TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) {
1007 Initialize(kHttpUrl, -1, -1);
1008 Start();
1010 // Test ensures that default construction of a BufferedResourceLoader has sane
1011 // values.
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
1015 // be.
1016 ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024);
1017 ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024);
1019 StopWhenLoad();
1022 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) {
1023 Initialize(kHttpUrl, -1, -1);
1024 Start();
1025 loader_->SetBitrate(0);
1026 CheckBufferWindowBounds();
1027 StopWhenLoad();
1030 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_BelowLowerBound) {
1031 Initialize(kHttpUrl, -1, -1);
1032 Start();
1033 loader_->SetBitrate(1024 * 8); // 1 Kbps.
1034 CheckBufferWindowBounds();
1035 StopWhenLoad();
1038 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_WithinBounds) {
1039 Initialize(kHttpUrl, -1, -1);
1040 Start();
1041 loader_->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps.
1042 CheckBufferWindowBounds();
1043 StopWhenLoad();
1046 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_AboveUpperBound) {
1047 Initialize(kHttpUrl, -1, -1);
1048 Start();
1049 loader_->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps.
1050 CheckBufferWindowBounds();
1051 StopWhenLoad();
1054 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) {
1055 Initialize(kHttpUrl, -1, -1);
1056 Start();
1057 loader_->SetPlaybackRate(-10);
1058 CheckBufferWindowBounds();
1059 StopWhenLoad();
1062 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) {
1063 Initialize(kHttpUrl, -1, -1);
1064 Start();
1065 loader_->SetPlaybackRate(0);
1066 CheckBufferWindowBounds();
1067 StopWhenLoad();
1070 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) {
1071 Initialize(kHttpUrl, -1, -1);
1072 Start();
1073 loader_->SetPlaybackRate(0.1);
1074 CheckBufferWindowBounds();
1075 StopWhenLoad();
1078 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) {
1079 Initialize(kHttpUrl, -1, -1);
1080 Start();
1081 loader_->SetPlaybackRate(10);
1082 CheckBufferWindowBounds();
1083 StopWhenLoad();
1086 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) {
1087 Initialize(kHttpUrl, -1, -1);
1088 Start();
1089 loader_->SetPlaybackRate(100);
1090 CheckBufferWindowBounds();
1091 StopWhenLoad();
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)
1101 return;
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();
1141 Start();
1142 PartialResponse(10, 99, 100);
1144 uint8 buffer[10];
1146 // Make an outstanding read request.
1147 ReadLoader(10, 10, buffer);
1149 // Receive almost enough data to cover, shouldn't defer.
1150 WriteLoader(10, 9);
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));
1156 WriteLoader(19, 1);
1157 VerifyBuffer(buffer, 10, 10);
1158 EXPECT_FALSE(HasActiveLoader());
1161 } // namespace media