Hook the WebThreadImplForMessageLoop up to post taks through the blink
[chromium-blink-merge.git] / media / blink / buffered_resource_loader_unittest.cc
blob3e7eaa8a8858d5c0cd3f191397e0be17fba1528e
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)), frame_(WebLocalFrame::create(&client_)) {
68 view_->setMainFrame(frame_);
70 for (int i = 0; i < kDataSize; ++i) {
71 data_[i] = i;
75 virtual ~BufferedResourceLoaderTest() {
76 view_->close();
77 frame_->close();
80 void Initialize(const char* url, int first_position, int last_position) {
81 gurl_ = GURL(url);
82 first_position_ = first_position;
83 last_position_ = last_position;
85 loader_.reset(new BufferedResourceLoader(
86 gurl_, BufferedResourceLoader::kUnspecified,
87 first_position_, last_position_,
88 BufferedResourceLoader::kCapacityDefer, 0, 0,
89 new MediaLog()));
91 // |test_loader_| will be used when Start() is called.
92 url_loader_ = new NiceMock<MockWebURLLoader>();
93 loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_);
96 void SetLoaderBuffer(int forward_capacity, int backward_capacity) {
97 loader_->buffer_.set_forward_capacity(forward_capacity);
98 loader_->buffer_.set_backward_capacity(backward_capacity);
99 loader_->buffer_.Clear();
102 void Start() {
103 InSequence s;
104 EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding),
105 loader_.get()));
107 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
108 loader_->Start(
109 base::Bind(&BufferedResourceLoaderTest::StartCallback,
110 base::Unretained(this)),
111 base::Bind(&BufferedResourceLoaderTest::LoadingCallback,
112 base::Unretained(this)),
113 base::Bind(&BufferedResourceLoaderTest::ProgressCallback,
114 base::Unretained(this)),
115 view_->mainFrame());
118 void FullResponse(int64 instance_size) {
119 FullResponse(instance_size, BufferedResourceLoader::kOk);
122 void FullResponse(int64 instance_size,
123 BufferedResourceLoader::Status status) {
124 EXPECT_CALL(*this, StartCallback(status));
126 WebURLResponse response(gurl_);
127 response.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
128 WebString::fromUTF8(base::StringPrintf("%"
129 PRId64, instance_size)));
130 response.setExpectedContentLength(instance_size);
131 response.setHTTPStatusCode(kHttpOK);
132 loader_->didReceiveResponse(url_loader_, response);
134 if (status == BufferedResourceLoader::kOk) {
135 EXPECT_EQ(instance_size, loader_->content_length());
136 EXPECT_EQ(instance_size, loader_->instance_size());
139 EXPECT_FALSE(loader_->range_supported());
142 void PartialResponse(int64 first_position, int64 last_position,
143 int64 instance_size) {
144 PartialResponse(first_position, last_position, instance_size, false, true);
147 void PartialResponse(int64 first_position, int64 last_position,
148 int64 instance_size, bool chunked, bool accept_ranges) {
149 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kOk));
151 WebURLResponse response(gurl_);
152 response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
153 WebString::fromUTF8(base::StringPrintf("bytes "
154 "%" PRId64 "-%" PRId64 "/%" PRId64,
155 first_position,
156 last_position,
157 instance_size)));
159 // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked.
160 int64 content_length = -1;
161 if (chunked) {
162 response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"),
163 WebString::fromUTF8("chunked"));
164 } else {
165 content_length = last_position - first_position + 1;
167 response.setExpectedContentLength(content_length);
169 // A server isn't required to return Accept-Ranges even though it might.
170 if (accept_ranges) {
171 response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
172 WebString::fromUTF8("bytes"));
175 response.setHTTPStatusCode(kHttpPartialContent);
176 loader_->didReceiveResponse(url_loader_, response);
178 // XXX: what's the difference between these two? For example in the chunked
179 // range request case, Content-Length is unspecified (because it's chunked)
180 // but Content-Range: a-b/c can be returned, where c == Content-Length
182 // Can we eliminate one?
183 EXPECT_EQ(content_length, loader_->content_length());
184 EXPECT_EQ(instance_size, loader_->instance_size());
186 // A valid partial response should always result in this being true.
187 EXPECT_TRUE(loader_->range_supported());
190 void Redirect(const char* url) {
191 GURL redirectUrl(url);
192 blink::WebURLRequest newRequest(redirectUrl);
193 blink::WebURLResponse redirectResponse(gurl_);
195 loader_->willSendRequest(url_loader_, newRequest, redirectResponse);
197 base::MessageLoop::current()->RunUntilIdle();
200 void StopWhenLoad() {
201 InSequence s;
202 EXPECT_CALL(*url_loader_, cancel());
203 loader_->Stop();
204 loader_.reset();
207 // Helper method to write to |loader_| from |data_|.
208 void WriteLoader(int position, int size) {
209 EXPECT_CALL(*this, ProgressCallback(position + size - 1));
210 loader_->didReceiveData(url_loader_,
211 reinterpret_cast<char*>(data_ + position),
212 size,
213 size);
216 void WriteData(int size) {
217 EXPECT_CALL(*this, ProgressCallback(_));
219 scoped_ptr<char[]> data(new char[size]);
220 loader_->didReceiveData(url_loader_, data.get(), size, size);
223 void WriteUntilThreshold() {
224 int buffered = loader_->buffer_.forward_bytes();
225 int capacity = loader_->buffer_.forward_capacity();
226 CHECK_LT(buffered, capacity);
228 EXPECT_CALL(*this, LoadingCallback(
229 BufferedResourceLoader::kLoadingDeferred));
230 WriteData(capacity - buffered);
233 // Helper method to read from |loader_|.
234 void ReadLoader(int64 position, int size, uint8* buffer) {
235 loader_->Read(position, size, buffer,
236 base::Bind(&BufferedResourceLoaderTest::ReadCallback,
237 base::Unretained(this)));
240 // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size].
241 void VerifyBuffer(uint8* buffer, int pos, int size) {
242 EXPECT_EQ(0, memcmp(buffer, data_ + pos, size));
245 void ConfirmLoaderOffsets(int64 expected_offset,
246 int expected_first_offset,
247 int expected_last_offset) {
248 EXPECT_EQ(loader_->offset_, expected_offset);
249 EXPECT_EQ(loader_->first_offset_, expected_first_offset);
250 EXPECT_EQ(loader_->last_offset_, expected_last_offset);
253 void ConfirmBufferState(int backward_bytes,
254 int backward_capacity,
255 int forward_bytes,
256 int forward_capacity) {
257 EXPECT_EQ(backward_bytes, loader_->buffer_.backward_bytes());
258 EXPECT_EQ(backward_capacity, loader_->buffer_.backward_capacity());
259 EXPECT_EQ(forward_bytes, loader_->buffer_.forward_bytes());
260 EXPECT_EQ(forward_capacity, loader_->buffer_.forward_capacity());
263 void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity) {
264 EXPECT_EQ(loader_->buffer_.backward_capacity(),
265 expected_backward_capacity);
268 void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity) {
269 EXPECT_EQ(loader_->buffer_.forward_capacity(), expected_forward_capacity);
272 // Makes sure the |loader_| buffer window is in a reasonable range.
273 void CheckBufferWindowBounds() {
274 // Corresponds to value defined in buffered_resource_loader.cc.
275 static const int kMinBufferCapacity = 2 * 1024 * 1024;
276 EXPECT_GE(loader_->buffer_.forward_capacity(), kMinBufferCapacity);
277 EXPECT_GE(loader_->buffer_.backward_capacity(), kMinBufferCapacity);
279 // Corresponds to value defined in buffered_resource_loader.cc.
280 static const int kMaxBufferCapacity = 20 * 1024 * 1024;
281 EXPECT_LE(loader_->buffer_.forward_capacity(), kMaxBufferCapacity);
282 EXPECT_LE(loader_->buffer_.backward_capacity(), kMaxBufferCapacity);
285 MOCK_METHOD1(StartCallback, void(BufferedResourceLoader::Status));
286 MOCK_METHOD2(ReadCallback, void(BufferedResourceLoader::Status, int));
287 MOCK_METHOD1(LoadingCallback, void(BufferedResourceLoader::LoadingState));
288 MOCK_METHOD1(ProgressCallback, void(int64));
290 protected:
291 GURL gurl_;
292 int64 first_position_;
293 int64 last_position_;
295 scoped_ptr<BufferedResourceLoader> loader_;
296 NiceMock<MockWebURLLoader>* url_loader_;
298 MockWebFrameClient client_;
299 WebView* view_;
300 WebLocalFrame* frame_;
302 base::MessageLoop message_loop_;
304 uint8 data_[kDataSize];
306 private:
307 DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest);
310 TEST_F(BufferedResourceLoaderTest, StartStop) {
311 Initialize(kHttpUrl, -1, -1);
312 Start();
313 StopWhenLoad();
316 // Tests that a bad HTTP response is recived, e.g. file not found.
317 TEST_F(BufferedResourceLoaderTest, BadHttpResponse) {
318 Initialize(kHttpUrl, -1, -1);
319 Start();
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);
327 StopWhenLoad();
330 // Tests that partial content is requested but not fulfilled.
331 TEST_F(BufferedResourceLoaderTest, NotPartialResponse) {
332 Initialize(kHttpUrl, 100, -1);
333 Start();
334 FullResponse(1024, BufferedResourceLoader::kFailed);
335 StopWhenLoad();
338 // Tests that a 200 response is received.
339 TEST_F(BufferedResourceLoaderTest, FullResponse) {
340 Initialize(kHttpUrl, -1, -1);
341 Start();
342 FullResponse(1024);
343 StopWhenLoad();
346 // Tests that a partial content response is received.
347 TEST_F(BufferedResourceLoaderTest, PartialResponse) {
348 Initialize(kHttpUrl, 100, 200);
349 Start();
350 PartialResponse(100, 200, 1024);
351 StopWhenLoad();
354 TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) {
355 Initialize(kHttpUrl, 100, 200);
356 Start();
357 PartialResponse(100, 200, 1024, true, true);
358 StopWhenLoad();
361 TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) {
362 Initialize(kHttpUrl, 100, 200);
363 Start();
364 PartialResponse(100, 200, 1024, false, false);
365 StopWhenLoad();
368 TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) {
369 Initialize(kHttpUrl, 100, 200);
370 Start();
371 PartialResponse(100, 200, 1024, true, false);
372 StopWhenLoad();
375 // Tests that an invalid partial response is received.
376 TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) {
377 Initialize(kHttpUrl, 0, 10);
378 Start();
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);
389 StopWhenLoad();
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);
396 Start();
397 PartialResponse(10, 29, 30);
399 uint8 buffer[10];
400 InSequence s;
402 // Writes 10 bytes and read them back.
403 WriteLoader(10, 10);
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.
409 WriteLoader(20, 10);
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, -1);
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);
448 Start();
449 PartialResponse(10, 0x014FFFFFF, 0x015000000);
451 uint8 buffer[20];
452 InSequence s;
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));
457 WriteLoader(10, 20);
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));
473 WriteLoader(30, 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
486 // not changed.
487 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
488 ReadLoader(30, 0x01400001, buffer);
490 ConfirmLoaderBufferForwardCapacity(10);
492 StopWhenLoad();
495 TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) {
496 Initialize(kHttpUrl, 10, 0x00FFFFFF);
497 Start();
498 PartialResponse(10, 0x00FFFFFF, 0x01000000);
500 uint8 buffer[10];
501 InSequence s;
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
508 // data to arrive.
509 ReadLoader(10, 10, buffer);
511 // Writing to loader will fulfill the read request.
512 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
513 WriteLoader(10, 20);
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, -1);
524 TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) {
525 Initialize(kHttpUrl, 10, 29);
526 Start();
527 PartialResponse(10, 29, 30);
529 uint8 buffer[10];
530 InSequence s;
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));
536 WebURLError error;
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);
544 Start();
545 PartialResponse(10, 29, 30);
547 uint8 buffer[10];
548 InSequence s;
550 // Write enough data so that a read would technically complete had the request
551 // not failed.
552 WriteLoader(10, 20);
554 // Fail without a pending read.
555 WebURLError error;
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);
568 Start();
569 PartialResponse(10, 29, 30);
571 uint8 buffer[10];
572 InSequence s;
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));
578 WebURLError error;
579 error.reason = 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);
589 Start();
590 PartialResponse(10, 99, 100);
592 uint8 buffer[10];
594 // Read past the buffer size; should not defer regardless.
595 WriteLoader(10, 10);
596 WriteLoader(20, 50);
598 // Should move past window.
599 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
600 ReadLoader(10, 10, buffer);
602 StopWhenLoad();
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);
610 Start();
611 PartialResponse(10, 99, 100);
613 uint8 buffer[10];
615 // Make an outstanding read request.
616 ReadLoader(10, 10, buffer);
618 // Receive almost enough data to cover, shouldn't defer.
619 WriteLoader(10, 9);
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));
624 WriteLoader(19, 1);
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));
636 WriteLoader(20, 40);
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));
648 WriteLoader(60, 40);
650 VerifyBuffer(buffer, 80, 10);
652 StopWhenLoad();
655 // Tests the data buffering logic of kCapacityDefer strategy.
656 TEST_F(BufferedResourceLoaderTest, ThresholdDeferStrategy) {
657 Initialize(kHttpUrl, 10, 99);
658 SetLoaderBuffer(10, 20);
659 Start();
660 PartialResponse(10, 99, 100);
662 uint8 buffer[10];
663 InSequence s;
665 // Write half of capacity: keep not deferring.
666 WriteData(5);
668 // Write rest of space until capacity: start deferring.
669 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
670 WriteData(5);
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));
679 WriteData(6);
681 StopWhenLoad();
684 TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) {
685 Initialize(kHttpUrl, 10, 99);
686 SetLoaderBuffer(10, 10);
687 Start();
688 PartialResponse(10, 99, 100);
690 uint8 buffer[256];
691 InSequence s;
693 // PRECONDITION
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.
707 // BEFORE
708 // offset=11 [xxxxxxxxx_]
709 // ^ ^^^ requested 4 bytes @ offset 20
710 // AFTER
711 // offset=24 [__________]
713 ReadLoader(20, 4, buffer);
715 // Write a little, make sure we didn't start deferring.
716 WriteData(2);
718 // Write the rest, read should complete.
719 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
720 WriteData(2);
722 // POSTCONDITION
723 ConfirmBufferState(4, 10, 0, 10);
724 ConfirmLoaderOffsets(24, 0, 0);
726 StopWhenLoad();
729 TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) {
730 Initialize(kHttpUrl, 10, 99);
731 SetLoaderBuffer(10, 10);
732 Start();
733 PartialResponse(10, 99, 100);
735 uint8 buffer[256];
736 InSequence s;
738 // PRECONDITION
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.
746 // BEFORE
747 // offset=10 [__________|xxxxxxxxxx]
748 // ^ ^^^ requested 10 bytes @ offset 9
749 // AFTER
750 // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!!
752 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
753 ReadLoader(9, 4, buffer);
755 // POSTCONDITION
756 ConfirmBufferState(0, 10, 10, 10);
757 ConfirmLoaderOffsets(10, 0, 0);
759 StopWhenLoad();
762 TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) {
763 Initialize(kHttpUrl, 10, 99);
764 SetLoaderBuffer(10, 10);
765 Start();
766 PartialResponse(10, 99, 100);
768 uint8 buffer[256];
769 InSequence s;
771 // PRECONDITION
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.
783 // BEFORE
784 // offset=10 [xxxxxxxxxx]
785 // ^^^^ requested 4 bytes @ offset 24
786 // ADJUSTED OFFSET
787 // offset=20 [__________]
788 // ^^^^ requested 4 bytes @ offset 24
789 // AFTER
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.
797 WriteData(4);
799 // Write the rest, read should complete.
800 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
801 WriteData(4);
803 // POSTCONDITION
804 ConfirmBufferState(8, 10, 0, 10);
805 ConfirmLoaderOffsets(28, 0, 0);
807 StopWhenLoad();
810 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) {
811 Initialize(kHttpUrl, 10, 99);
812 SetLoaderBuffer(10, 10);
813 Start();
814 PartialResponse(10, 99, 100);
816 uint8 buffer[256];
817 InSequence s;
819 // PRECONDITION
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.
833 // BEFORE
834 // offset=10 [xxxxxxxxxx]
835 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
836 // ADJUSTED OFFSET
837 // offset=20 [__________]
838 // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24
839 // ADJUSTED CAPACITY
840 // offset=20 [________________]
841 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
842 // AFTER
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.
851 WriteData(10);
853 // Write the rest, read should complete and capacity should go back to normal.
854 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 12));
855 WriteData(6);
856 ConfirmLoaderBufferForwardCapacity(10);
858 // POSTCONDITION
859 ConfirmBufferState(6, 10, 0, 10);
860 ConfirmLoaderOffsets(36, 0, 0);
862 StopWhenLoad();
865 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) {
866 Initialize(kHttpUrl, 10, 99);
867 SetLoaderBuffer(10, 10);
868 Start();
869 PartialResponse(10, 99, 100);
871 uint8 buffer[256];
872 InSequence s;
874 // PRECONDITION
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.
891 // BEFORE
892 // offset=20 [xxxxxxxxxx|xxxxxxxxxx]
893 // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16
894 // ADJUSTED OFFSET
895 // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx
896 // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16
897 // ADJUSTED CAPACITY
898 // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____]
899 // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16
900 // AFTER
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.
909 WriteData(2);
911 // Write the rest, read should complete and capacity should go back to normal.
912 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 18));
913 WriteData(2);
914 ConfirmLoaderBufferForwardCapacity(10);
916 // POSTCONDITION
917 ConfirmBufferState(4, 10, 0, 10);
918 ConfirmLoaderOffsets(34, 0, 0);
920 StopWhenLoad();
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);
929 Start();
930 PartialResponse(10, kSize - 1, kSize);
932 uint8 buffer[256];
933 InSequence s;
935 // PRECONDITION
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.
943 // BEFORE
944 // offset=10 [xxxxxxxxxx] ...
945 // ^^^^ requested 10 bytes @ threshold
946 // AFTER
947 // offset=10 [xxxxxxxxxx] !!! cache miss !!!
949 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
950 ReadLoader(kThreshold + 20, 10, buffer);
952 // POSTCONDITION
953 ConfirmBufferState(0, 10, 10, 10);
954 ConfirmLoaderOffsets(10, 0, 0);
956 StopWhenLoad();
959 TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) {
960 // Make sure no redirect case works as expected.
961 Initialize(kHttpUrl, -1, -1);
962 Start();
963 FullResponse(1024);
964 EXPECT_TRUE(loader_->HasSingleOrigin());
965 StopWhenLoad();
967 // Test redirect to the same domain.
968 Initialize(kHttpUrl, -1, -1);
969 Start();
970 Redirect(kHttpRedirectToSameDomainUrl1);
971 FullResponse(1024);
972 EXPECT_TRUE(loader_->HasSingleOrigin());
973 StopWhenLoad();
975 // Test redirect twice to the same domain.
976 Initialize(kHttpUrl, -1, -1);
977 Start();
978 Redirect(kHttpRedirectToSameDomainUrl1);
979 Redirect(kHttpRedirectToSameDomainUrl2);
980 FullResponse(1024);
981 EXPECT_TRUE(loader_->HasSingleOrigin());
982 StopWhenLoad();
984 // Test redirect to a different domain.
985 Initialize(kHttpUrl, -1, -1);
986 Start();
987 Redirect(kHttpRedirectToDifferentDomainUrl1);
988 FullResponse(1024);
989 EXPECT_FALSE(loader_->HasSingleOrigin());
990 StopWhenLoad();
992 // Test redirect to the same domain and then to a different domain.
993 Initialize(kHttpUrl, -1, -1);
994 Start();
995 Redirect(kHttpRedirectToSameDomainUrl1);
996 Redirect(kHttpRedirectToDifferentDomainUrl1);
997 FullResponse(1024);
998 EXPECT_FALSE(loader_->HasSingleOrigin());
999 StopWhenLoad();
1002 TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) {
1003 Initialize(kHttpUrl, -1, -1);
1004 Start();
1006 // Test ensures that default construction of a BufferedResourceLoader has sane
1007 // values.
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
1011 // be.
1012 ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024);
1013 ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024);
1015 StopWhenLoad();
1018 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) {
1019 Initialize(kHttpUrl, -1, -1);
1020 Start();
1021 loader_->SetBitrate(0);
1022 CheckBufferWindowBounds();
1023 StopWhenLoad();
1026 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_BelowLowerBound) {
1027 Initialize(kHttpUrl, -1, -1);
1028 Start();
1029 loader_->SetBitrate(1024 * 8); // 1 Kbps.
1030 CheckBufferWindowBounds();
1031 StopWhenLoad();
1034 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_WithinBounds) {
1035 Initialize(kHttpUrl, -1, -1);
1036 Start();
1037 loader_->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps.
1038 CheckBufferWindowBounds();
1039 StopWhenLoad();
1042 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_AboveUpperBound) {
1043 Initialize(kHttpUrl, -1, -1);
1044 Start();
1045 loader_->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps.
1046 CheckBufferWindowBounds();
1047 StopWhenLoad();
1050 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) {
1051 Initialize(kHttpUrl, -1, -1);
1052 Start();
1053 loader_->SetPlaybackRate(-10);
1054 CheckBufferWindowBounds();
1055 StopWhenLoad();
1058 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) {
1059 Initialize(kHttpUrl, -1, -1);
1060 Start();
1061 loader_->SetPlaybackRate(0);
1062 CheckBufferWindowBounds();
1063 StopWhenLoad();
1066 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) {
1067 Initialize(kHttpUrl, -1, -1);
1068 Start();
1069 loader_->SetPlaybackRate(0.1f);
1070 CheckBufferWindowBounds();
1071 StopWhenLoad();
1074 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) {
1075 Initialize(kHttpUrl, -1, -1);
1076 Start();
1077 loader_->SetPlaybackRate(10);
1078 CheckBufferWindowBounds();
1079 StopWhenLoad();
1082 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) {
1083 Initialize(kHttpUrl, -1, -1);
1084 Start();
1085 loader_->SetPlaybackRate(100);
1086 CheckBufferWindowBounds();
1087 StopWhenLoad();
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)
1097 return;
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 media