Revert of Roll src/third_party/WebKit e0eac24:489c548 (svn 193311:193320) (patchset...
[chromium-blink-merge.git] / media / blink / buffered_resource_loader_unittest.cc
blobf046d607c161757a871b12bede270dd2e5db20fc
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 bool HasActiveLoader() { return loader_->active_loader_; }
287 MOCK_METHOD1(StartCallback, void(BufferedResourceLoader::Status));
288 MOCK_METHOD2(ReadCallback, void(BufferedResourceLoader::Status, int));
289 MOCK_METHOD1(LoadingCallback, void(BufferedResourceLoader::LoadingState));
290 MOCK_METHOD1(ProgressCallback, void(int64));
292 protected:
293 GURL gurl_;
294 int64 first_position_;
295 int64 last_position_;
297 scoped_ptr<BufferedResourceLoader> loader_;
298 NiceMock<MockWebURLLoader>* url_loader_;
300 MockWebFrameClient client_;
301 WebView* view_;
302 WebLocalFrame* frame_;
304 base::MessageLoop message_loop_;
306 uint8 data_[kDataSize];
308 private:
309 DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest);
312 TEST_F(BufferedResourceLoaderTest, StartStop) {
313 Initialize(kHttpUrl, -1, -1);
314 Start();
315 StopWhenLoad();
318 // Tests that a bad HTTP response is recived, e.g. file not found.
319 TEST_F(BufferedResourceLoaderTest, BadHttpResponse) {
320 Initialize(kHttpUrl, -1, -1);
321 Start();
323 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed));
325 WebURLResponse response(gurl_);
326 response.setHTTPStatusCode(404);
327 response.setHTTPStatusText("Not Found\n");
328 loader_->didReceiveResponse(url_loader_, response);
329 StopWhenLoad();
332 // Tests that partial content is requested but not fulfilled.
333 TEST_F(BufferedResourceLoaderTest, NotPartialResponse) {
334 Initialize(kHttpUrl, 100, -1);
335 Start();
336 FullResponse(1024, BufferedResourceLoader::kFailed);
337 StopWhenLoad();
340 // Tests that a 200 response is received.
341 TEST_F(BufferedResourceLoaderTest, FullResponse) {
342 Initialize(kHttpUrl, -1, -1);
343 Start();
344 FullResponse(1024);
345 StopWhenLoad();
348 // Tests that a partial content response is received.
349 TEST_F(BufferedResourceLoaderTest, PartialResponse) {
350 Initialize(kHttpUrl, 100, 200);
351 Start();
352 PartialResponse(100, 200, 1024);
353 StopWhenLoad();
356 TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) {
357 Initialize(kHttpUrl, 100, 200);
358 Start();
359 PartialResponse(100, 200, 1024, true, true);
360 StopWhenLoad();
363 TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) {
364 Initialize(kHttpUrl, 100, 200);
365 Start();
366 PartialResponse(100, 200, 1024, false, false);
367 StopWhenLoad();
370 TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) {
371 Initialize(kHttpUrl, 100, 200);
372 Start();
373 PartialResponse(100, 200, 1024, true, false);
374 StopWhenLoad();
377 // Tests that an invalid partial response is received.
378 TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) {
379 Initialize(kHttpUrl, 0, 10);
380 Start();
382 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed));
384 WebURLResponse response(gurl_);
385 response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
386 WebString::fromUTF8(base::StringPrintf("bytes "
387 "%d-%d/%d", 1, 10, 1024)));
388 response.setExpectedContentLength(10);
389 response.setHTTPStatusCode(kHttpPartialContent);
390 loader_->didReceiveResponse(url_loader_, response);
391 StopWhenLoad();
394 // Tests the logic of sliding window for data buffering and reading.
395 TEST_F(BufferedResourceLoaderTest, BufferAndRead) {
396 Initialize(kHttpUrl, 10, 29);
397 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
398 Start();
399 PartialResponse(10, 29, 30);
401 uint8 buffer[10];
402 InSequence s;
404 // Writes 10 bytes and read them back.
405 WriteLoader(10, 10);
406 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
407 ReadLoader(10, 10, buffer);
408 VerifyBuffer(buffer, 10, 10);
410 // Writes 10 bytes and read 2 times.
411 WriteLoader(20, 10);
412 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
413 ReadLoader(20, 5, buffer);
414 VerifyBuffer(buffer, 20, 5);
415 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
416 ReadLoader(25, 5, buffer);
417 VerifyBuffer(buffer, 25, 5);
419 // Read backward within buffer.
420 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
421 ReadLoader(10, 10, buffer);
422 VerifyBuffer(buffer, 10, 10);
424 // Read backward outside buffer.
425 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
426 ReadLoader(9, 10, buffer);
428 // Response has completed.
429 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished));
430 loader_->didFinishLoading(url_loader_, 0, -1);
432 // Try to read 10 from position 25 will just return with 5 bytes.
433 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
434 ReadLoader(25, 10, buffer);
435 VerifyBuffer(buffer, 25, 5);
437 // Try to read outside buffered range after request has completed.
438 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
439 ReadLoader(5, 10, buffer);
441 // Try to read beyond the instance size.
442 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 0));
443 ReadLoader(30, 10, buffer);
446 // Tests the logic of expanding the data buffer for large reads.
447 TEST_F(BufferedResourceLoaderTest, ReadExtendBuffer) {
448 Initialize(kHttpUrl, 10, 0x014FFFFFF);
449 SetLoaderBuffer(10, 20);
450 Start();
451 PartialResponse(10, 0x014FFFFFF, 0x015000000);
453 uint8 buffer[20];
454 InSequence s;
456 // Write more than forward capacity and read it back. Ensure forward capacity
457 // gets reset after reading.
458 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
459 WriteLoader(10, 20);
461 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20));
462 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
463 ReadLoader(10, 20, buffer);
465 VerifyBuffer(buffer, 10, 20);
466 ConfirmLoaderBufferForwardCapacity(10);
468 // Make and outstanding read request larger than forward capacity. Ensure
469 // forward capacity gets extended.
470 ReadLoader(30, 20, buffer);
471 ConfirmLoaderBufferForwardCapacity(20);
473 // Fulfill outstanding request. Ensure forward capacity gets reset.
474 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20));
475 WriteLoader(30, 20);
477 VerifyBuffer(buffer, 30, 20);
478 ConfirmLoaderBufferForwardCapacity(10);
480 // Try to read further ahead than kForwardWaitThreshold allows. Ensure
481 // forward capacity is not changed.
482 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
483 ReadLoader(0x00300000, 1, buffer);
485 ConfirmLoaderBufferForwardCapacity(10);
487 // Try to read more than maximum forward capacity. Ensure forward capacity is
488 // not changed.
489 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
490 ReadLoader(30, 0x01400001, buffer);
492 ConfirmLoaderBufferForwardCapacity(10);
494 StopWhenLoad();
497 TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) {
498 Initialize(kHttpUrl, 10, 0x00FFFFFF);
499 Start();
500 PartialResponse(10, 0x00FFFFFF, 0x01000000);
502 uint8 buffer[10];
503 InSequence s;
505 // Read very far ahead will get a cache miss.
506 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
507 ReadLoader(0x00FFFFFF, 1, buffer);
509 // The following call will not call ReadCallback() because it is waiting for
510 // data to arrive.
511 ReadLoader(10, 10, buffer);
513 // Writing to loader will fulfill the read request.
514 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
515 WriteLoader(10, 20);
516 VerifyBuffer(buffer, 10, 10);
518 // The following call cannot be fulfilled now.
519 ReadLoader(25, 10, buffer);
521 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished));
522 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
523 loader_->didFinishLoading(url_loader_, 0, -1);
526 TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) {
527 Initialize(kHttpUrl, 10, 29);
528 Start();
529 PartialResponse(10, 29, 30);
531 uint8 buffer[10];
532 InSequence s;
534 // We should convert any error we receive to BufferedResourceLoader::kFailed.
535 ReadLoader(10, 10, buffer);
536 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
537 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
538 WebURLError error;
539 error.reason = net::ERR_TIMED_OUT;
540 error.isCancellation = false;
541 loader_->didFail(url_loader_, error);
544 TEST_F(BufferedResourceLoaderTest, RequestFailedWithNoPendingReads) {
545 Initialize(kHttpUrl, 10, 29);
546 Start();
547 PartialResponse(10, 29, 30);
549 uint8 buffer[10];
550 InSequence s;
552 // Write enough data so that a read would technically complete had the request
553 // not failed.
554 WriteLoader(10, 20);
556 // Fail without a pending read.
557 WebURLError error;
558 error.reason = net::ERR_TIMED_OUT;
559 error.isCancellation = false;
560 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
561 loader_->didFail(url_loader_, error);
563 // Now we should immediately fail any read even if we have data buffered.
564 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
565 ReadLoader(10, 10, buffer);
568 TEST_F(BufferedResourceLoaderTest, RequestCancelledWhenRead) {
569 Initialize(kHttpUrl, 10, 29);
570 Start();
571 PartialResponse(10, 29, 30);
573 uint8 buffer[10];
574 InSequence s;
576 // We should convert any error we receive to BufferedResourceLoader::kFailed.
577 ReadLoader(10, 10, buffer);
578 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
579 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
580 WebURLError error;
581 error.reason = 0;
582 error.isCancellation = true;
583 loader_->didFail(url_loader_, error);
586 // Tests the data buffering logic of NeverDefer strategy.
587 TEST_F(BufferedResourceLoaderTest, NeverDeferStrategy) {
588 Initialize(kHttpUrl, 10, 99);
589 SetLoaderBuffer(10, 20);
590 loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer);
591 Start();
592 PartialResponse(10, 99, 100);
594 uint8 buffer[10];
596 // Read past the buffer size; should not defer regardless.
597 WriteLoader(10, 10);
598 WriteLoader(20, 50);
600 // Should move past window.
601 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
602 ReadLoader(10, 10, buffer);
604 StopWhenLoad();
607 // Tests the data buffering logic of ReadThenDefer strategy.
608 TEST_F(BufferedResourceLoaderTest, ReadThenDeferStrategy) {
609 Initialize(kHttpUrl, 10, 99);
610 SetLoaderBuffer(10, 20);
611 loader_->UpdateDeferStrategy(BufferedResourceLoader::kReadThenDefer);
612 Start();
613 PartialResponse(10, 99, 100);
615 uint8 buffer[10];
617 // Make an outstanding read request.
618 ReadLoader(10, 10, buffer);
620 // Receive almost enough data to cover, shouldn't defer.
621 WriteLoader(10, 9);
623 // As soon as we have received enough data to fulfill the read, defer.
624 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
625 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
626 WriteLoader(19, 1);
628 VerifyBuffer(buffer, 10, 10);
630 // Read again which should disable deferring since there should be nothing
631 // left in our internal buffer.
632 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
633 ReadLoader(20, 10, buffer);
635 // Over-fulfill requested bytes, then deferring should be enabled again.
636 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
637 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
638 WriteLoader(20, 40);
640 VerifyBuffer(buffer, 20, 10);
642 // Read far ahead, which should disable deferring. In this case we still have
643 // bytes in our internal buffer.
644 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
645 ReadLoader(80, 10, buffer);
647 // Fulfill requested bytes, then deferring should be enabled again.
648 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
649 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
650 WriteLoader(60, 40);
652 VerifyBuffer(buffer, 80, 10);
654 StopWhenLoad();
657 // Tests the data buffering logic of kCapacityDefer strategy.
658 TEST_F(BufferedResourceLoaderTest, ThresholdDeferStrategy) {
659 Initialize(kHttpUrl, 10, 99);
660 SetLoaderBuffer(10, 20);
661 Start();
662 PartialResponse(10, 99, 100);
664 uint8 buffer[10];
665 InSequence s;
667 // Write half of capacity: keep not deferring.
668 WriteData(5);
670 // Write rest of space until capacity: start deferring.
671 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
672 WriteData(5);
674 // Read a byte from the buffer: stop deferring.
675 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1));
676 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
677 ReadLoader(10, 1, buffer);
679 // Write a byte to hit capacity: start deferring.
680 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
681 WriteData(6);
683 StopWhenLoad();
686 TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) {
687 Initialize(kHttpUrl, 10, 99);
688 SetLoaderBuffer(10, 10);
689 Start();
690 PartialResponse(10, 99, 100);
692 uint8 buffer[256];
693 InSequence s;
695 // PRECONDITION
696 WriteUntilThreshold();
697 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1));
698 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
699 ReadLoader(10, 1, buffer);
700 ConfirmBufferState(1, 10, 9, 10);
701 ConfirmLoaderOffsets(11, 0, 0);
703 // *** TRICKY BUSINESS, PT. I ***
704 // Read past buffered: stop deferring.
706 // In order for the read to complete we must:
707 // 1) Stop deferring to receive more data.
709 // BEFORE
710 // offset=11 [xxxxxxxxx_]
711 // ^ ^^^ requested 4 bytes @ offset 20
712 // AFTER
713 // offset=24 [__________]
715 ReadLoader(20, 4, buffer);
717 // Write a little, make sure we didn't start deferring.
718 WriteData(2);
720 // Write the rest, read should complete.
721 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
722 WriteData(2);
724 // POSTCONDITION
725 ConfirmBufferState(4, 10, 0, 10);
726 ConfirmLoaderOffsets(24, 0, 0);
728 StopWhenLoad();
731 TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) {
732 Initialize(kHttpUrl, 10, 99);
733 SetLoaderBuffer(10, 10);
734 Start();
735 PartialResponse(10, 99, 100);
737 uint8 buffer[256];
738 InSequence s;
740 // PRECONDITION
741 WriteUntilThreshold();
742 ConfirmBufferState(0, 10, 10, 10);
743 ConfirmLoaderOffsets(10, 0, 0);
745 // *** TRICKY BUSINESS, PT. II ***
746 // Read backwards a little too much: cache miss.
748 // BEFORE
749 // offset=10 [__________|xxxxxxxxxx]
750 // ^ ^^^ requested 10 bytes @ offset 9
751 // AFTER
752 // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!!
754 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
755 ReadLoader(9, 4, buffer);
757 // POSTCONDITION
758 ConfirmBufferState(0, 10, 10, 10);
759 ConfirmLoaderOffsets(10, 0, 0);
761 StopWhenLoad();
764 TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) {
765 Initialize(kHttpUrl, 10, 99);
766 SetLoaderBuffer(10, 10);
767 Start();
768 PartialResponse(10, 99, 100);
770 uint8 buffer[256];
771 InSequence s;
773 // PRECONDITION
774 WriteUntilThreshold();
775 ConfirmBufferState(0, 10, 10, 10);
776 ConfirmLoaderOffsets(10, 0, 0);
778 // *** TRICKY BUSINESS, PT. III ***
779 // Read past forward capacity but within capacity: stop deferring.
781 // In order for the read to complete we must:
782 // 1) Adjust offset forward to create capacity.
783 // 2) Stop deferring to receive more data.
785 // BEFORE
786 // offset=10 [xxxxxxxxxx]
787 // ^^^^ requested 4 bytes @ offset 24
788 // ADJUSTED OFFSET
789 // offset=20 [__________]
790 // ^^^^ requested 4 bytes @ offset 24
791 // AFTER
792 // offset=28 [__________]
794 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
795 ReadLoader(24, 4, buffer);
796 ConfirmLoaderOffsets(20, 4, 8);
798 // Write a little, make sure we didn't start deferring.
799 WriteData(4);
801 // Write the rest, read should complete.
802 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
803 WriteData(4);
805 // POSTCONDITION
806 ConfirmBufferState(8, 10, 0, 10);
807 ConfirmLoaderOffsets(28, 0, 0);
809 StopWhenLoad();
812 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) {
813 Initialize(kHttpUrl, 10, 99);
814 SetLoaderBuffer(10, 10);
815 Start();
816 PartialResponse(10, 99, 100);
818 uint8 buffer[256];
819 InSequence s;
821 // PRECONDITION
822 WriteUntilThreshold();
823 ConfirmBufferState(0, 10, 10, 10);
824 ConfirmLoaderOffsets(10, 0, 0);
826 // *** TRICKY BUSINESS, PT. IV ***
827 // Read a large amount past forward capacity but within
828 // capacity: stop deferring.
830 // In order for the read to complete we must:
831 // 1) Adjust offset forward to create capacity.
832 // 2) Expand capacity to make sure we don't defer as data arrives.
833 // 3) Stop deferring to receive more data.
835 // BEFORE
836 // offset=10 [xxxxxxxxxx]
837 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
838 // ADJUSTED OFFSET
839 // offset=20 [__________]
840 // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24
841 // ADJUSTED CAPACITY
842 // offset=20 [________________]
843 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
844 // AFTER
845 // offset=36 [__________]
847 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
848 ReadLoader(24, 12, buffer);
849 ConfirmLoaderOffsets(20, 4, 16);
850 ConfirmBufferState(10, 10, 0, 16);
852 // Write a little, make sure we didn't start deferring.
853 WriteData(10);
855 // Write the rest, read should complete and capacity should go back to normal.
856 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 12));
857 WriteData(6);
858 ConfirmLoaderBufferForwardCapacity(10);
860 // POSTCONDITION
861 ConfirmBufferState(6, 10, 0, 10);
862 ConfirmLoaderOffsets(36, 0, 0);
864 StopWhenLoad();
867 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) {
868 Initialize(kHttpUrl, 10, 99);
869 SetLoaderBuffer(10, 10);
870 Start();
871 PartialResponse(10, 99, 100);
873 uint8 buffer[256];
874 InSequence s;
876 // PRECONDITION
877 WriteUntilThreshold();
878 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
879 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
880 ReadLoader(10, 10, buffer);
881 WriteUntilThreshold();
882 ConfirmBufferState(10, 10, 10, 10);
883 ConfirmLoaderOffsets(20, 0, 0);
885 // *** TRICKY BUSINESS, PT. V ***
886 // Read a large amount that involves backwards data: stop deferring.
888 // In order for the read to complete we must:
889 // 1) Adjust offset *backwards* to create capacity.
890 // 2) Expand capacity to make sure we don't defer as data arrives.
891 // 3) Stop deferring to receive more data.
893 // BEFORE
894 // offset=20 [xxxxxxxxxx|xxxxxxxxxx]
895 // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16
896 // ADJUSTED OFFSET
897 // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx
898 // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16
899 // ADJUSTED CAPACITY
900 // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____]
901 // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16
902 // AFTER
903 // offset=34 [xxxxxxxxxx|__________]
905 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
906 ReadLoader(16, 18, buffer);
907 ConfirmLoaderOffsets(16, 0, 18);
908 ConfirmBufferState(6, 10, 14, 18);
910 // Write a little, make sure we didn't start deferring.
911 WriteData(2);
913 // Write the rest, read should complete and capacity should go back to normal.
914 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 18));
915 WriteData(2);
916 ConfirmLoaderBufferForwardCapacity(10);
918 // POSTCONDITION
919 ConfirmBufferState(4, 10, 0, 10);
920 ConfirmLoaderOffsets(34, 0, 0);
922 StopWhenLoad();
925 TEST_F(BufferedResourceLoaderTest, Tricky_ReadPastThreshold) {
926 const int kSize = 5 * 1024 * 1024;
927 const int kThreshold = 2 * 1024 * 1024;
929 Initialize(kHttpUrl, 10, kSize);
930 SetLoaderBuffer(10, 10);
931 Start();
932 PartialResponse(10, kSize - 1, kSize);
934 uint8 buffer[256];
935 InSequence s;
937 // PRECONDITION
938 WriteUntilThreshold();
939 ConfirmBufferState(0, 10, 10, 10);
940 ConfirmLoaderOffsets(10, 0, 0);
942 // *** TRICKY BUSINESS, PT. VI ***
943 // Read past the forward wait threshold: cache miss.
945 // BEFORE
946 // offset=10 [xxxxxxxxxx] ...
947 // ^^^^ requested 10 bytes @ threshold
948 // AFTER
949 // offset=10 [xxxxxxxxxx] !!! cache miss !!!
951 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
952 ReadLoader(kThreshold + 20, 10, buffer);
954 // POSTCONDITION
955 ConfirmBufferState(0, 10, 10, 10);
956 ConfirmLoaderOffsets(10, 0, 0);
958 StopWhenLoad();
961 TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) {
962 // Make sure no redirect case works as expected.
963 Initialize(kHttpUrl, -1, -1);
964 Start();
965 FullResponse(1024);
966 EXPECT_TRUE(loader_->HasSingleOrigin());
967 StopWhenLoad();
969 // Test redirect to the same domain.
970 Initialize(kHttpUrl, -1, -1);
971 Start();
972 Redirect(kHttpRedirectToSameDomainUrl1);
973 FullResponse(1024);
974 EXPECT_TRUE(loader_->HasSingleOrigin());
975 StopWhenLoad();
977 // Test redirect twice to the same domain.
978 Initialize(kHttpUrl, -1, -1);
979 Start();
980 Redirect(kHttpRedirectToSameDomainUrl1);
981 Redirect(kHttpRedirectToSameDomainUrl2);
982 FullResponse(1024);
983 EXPECT_TRUE(loader_->HasSingleOrigin());
984 StopWhenLoad();
986 // Test redirect to a different domain.
987 Initialize(kHttpUrl, -1, -1);
988 Start();
989 Redirect(kHttpRedirectToDifferentDomainUrl1);
990 FullResponse(1024);
991 EXPECT_FALSE(loader_->HasSingleOrigin());
992 StopWhenLoad();
994 // Test redirect to the same domain and then to a different domain.
995 Initialize(kHttpUrl, -1, -1);
996 Start();
997 Redirect(kHttpRedirectToSameDomainUrl1);
998 Redirect(kHttpRedirectToDifferentDomainUrl1);
999 FullResponse(1024);
1000 EXPECT_FALSE(loader_->HasSingleOrigin());
1001 StopWhenLoad();
1004 TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) {
1005 Initialize(kHttpUrl, -1, -1);
1006 Start();
1008 // Test ensures that default construction of a BufferedResourceLoader has sane
1009 // values.
1011 // Please do not change these values in order to make a test pass! Instead,
1012 // start a conversation on what the default buffer window capacities should
1013 // be.
1014 ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024);
1015 ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024);
1017 StopWhenLoad();
1020 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) {
1021 Initialize(kHttpUrl, -1, -1);
1022 Start();
1023 loader_->SetBitrate(0);
1024 CheckBufferWindowBounds();
1025 StopWhenLoad();
1028 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_BelowLowerBound) {
1029 Initialize(kHttpUrl, -1, -1);
1030 Start();
1031 loader_->SetBitrate(1024 * 8); // 1 Kbps.
1032 CheckBufferWindowBounds();
1033 StopWhenLoad();
1036 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_WithinBounds) {
1037 Initialize(kHttpUrl, -1, -1);
1038 Start();
1039 loader_->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps.
1040 CheckBufferWindowBounds();
1041 StopWhenLoad();
1044 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_AboveUpperBound) {
1045 Initialize(kHttpUrl, -1, -1);
1046 Start();
1047 loader_->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps.
1048 CheckBufferWindowBounds();
1049 StopWhenLoad();
1052 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) {
1053 Initialize(kHttpUrl, -1, -1);
1054 Start();
1055 loader_->SetPlaybackRate(-10);
1056 CheckBufferWindowBounds();
1057 StopWhenLoad();
1060 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) {
1061 Initialize(kHttpUrl, -1, -1);
1062 Start();
1063 loader_->SetPlaybackRate(0);
1064 CheckBufferWindowBounds();
1065 StopWhenLoad();
1068 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) {
1069 Initialize(kHttpUrl, -1, -1);
1070 Start();
1071 loader_->SetPlaybackRate(0.1f);
1072 CheckBufferWindowBounds();
1073 StopWhenLoad();
1076 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) {
1077 Initialize(kHttpUrl, -1, -1);
1078 Start();
1079 loader_->SetPlaybackRate(10);
1080 CheckBufferWindowBounds();
1081 StopWhenLoad();
1084 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) {
1085 Initialize(kHttpUrl, -1, -1);
1086 Start();
1087 loader_->SetPlaybackRate(100);
1088 CheckBufferWindowBounds();
1089 StopWhenLoad();
1092 static void ExpectContentRange(
1093 const std::string& str, bool expect_success,
1094 int64 expected_first, int64 expected_last, int64 expected_size) {
1095 int64 first, last, size;
1096 ASSERT_EQ(expect_success, BufferedResourceLoader::ParseContentRange(
1097 str, &first, &last, &size)) << str;
1098 if (!expect_success)
1099 return;
1100 EXPECT_EQ(first, expected_first);
1101 EXPECT_EQ(last, expected_last);
1102 EXPECT_EQ(size, expected_size);
1105 static void ExpectContentRangeFailure(const std::string& str) {
1106 ExpectContentRange(str, false, 0, 0, 0);
1109 static void ExpectContentRangeSuccess(
1110 const std::string& str,
1111 int64 expected_first, int64 expected_last, int64 expected_size) {
1112 ExpectContentRange(str, true, expected_first, expected_last, expected_size);
1115 TEST(BufferedResourceLoaderStandaloneTest, ParseContentRange) {
1116 ExpectContentRangeFailure("cytes 0-499/500");
1117 ExpectContentRangeFailure("bytes 0499/500");
1118 ExpectContentRangeFailure("bytes 0-499500");
1119 ExpectContentRangeFailure("bytes 0-499/500-blorg");
1120 ExpectContentRangeFailure("bytes 0-499/500-1");
1121 ExpectContentRangeFailure("bytes 0-499/400");
1122 ExpectContentRangeFailure("bytes 0-/400");
1123 ExpectContentRangeFailure("bytes -300/400");
1124 ExpectContentRangeFailure("bytes 20-10/400");
1126 ExpectContentRangeSuccess("bytes 0-499/500", 0, 499, 500);
1127 ExpectContentRangeSuccess("bytes 0-0/500", 0, 0, 500);
1128 ExpectContentRangeSuccess("bytes 10-11/50", 10, 11, 50);
1129 ExpectContentRangeSuccess("bytes 10-11/*", 10, 11,
1130 kPositionNotSpecified);
1133 // Tests the data buffering logic of ReadThenDefer strategy.
1134 TEST_F(BufferedResourceLoaderTest, CancelAfterDeferral) {
1135 Initialize(kHttpUrl, 10, 99);
1136 SetLoaderBuffer(10, 20);
1137 loader_->UpdateDeferStrategy(BufferedResourceLoader::kReadThenDefer);
1138 loader_->CancelUponDeferral();
1139 Start();
1140 PartialResponse(10, 99, 100);
1142 uint8 buffer[10];
1144 // Make an outstanding read request.
1145 ReadLoader(10, 10, buffer);
1147 // Receive almost enough data to cover, shouldn't defer.
1148 WriteLoader(10, 9);
1149 EXPECT_TRUE(HasActiveLoader());
1151 // As soon as we have received enough data to fulfill the read, defer.
1152 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
1153 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
1154 WriteLoader(19, 1);
1155 VerifyBuffer(buffer, 10, 10);
1156 EXPECT_FALSE(HasActiveLoader());
1159 } // namespace media