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. 4 5 #include <algorithm> 6 #include <string> 7 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" 26 27 using ::testing::_; 28 using ::testing::InSequence; 29 using ::testing::Return; 30 using ::testing::Truly; 31 using ::testing::NiceMock; 32 33 using blink::WebLocalFrame; 34 using blink::WebString; 35 using blink::WebURLError; 36 using blink::WebURLResponse; 37 using blink::WebView; 38 39 namespace media { 40 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"; 45 46 static const int kDataSize = 1024; 47 static const int kHttpOK = 200; 48 static const int kHttpPartialContent = 206; 49 50 enum NetworkState { 51 NONE, 52 LOADED, 53 LOADING 54 }; 55 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); 62 } 63 64 class BufferedResourceLoaderTest : public testing::Test { 65 public: 66 BufferedResourceLoaderTest() 67 : view_(WebView::create(NULL)), frame_(WebLocalFrame::create(&client_)) { 68 view_->setMainFrame(frame_); 69 70 for (int i = 0; i < kDataSize; ++i) { 71 data_[i] = i; 72 } 73 } 74 75 virtual ~BufferedResourceLoaderTest() { 76 view_->close(); 77 frame_->close(); 78 } 79 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; 84 85 loader_.reset(new BufferedResourceLoader( 86 gurl_, BufferedResourceLoader::kUnspecified, 87 first_position_, last_position_, 88 BufferedResourceLoader::kCapacityDefer, 0, 0, 89 new MediaLog())); 90 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_); 94 } 95 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(); 100 } 101 102 void Start() { 103 InSequence s; 104 EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding), 105 loader_.get())); 106 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()); 116 } 117 118 void FullResponse(int64 instance_size) { 119 FullResponse(instance_size, BufferedResourceLoader::kOk); 120 } 121 122 void FullResponse(int64 instance_size, 123 BufferedResourceLoader::Status status) { 124 EXPECT_CALL(*this, StartCallback(status)); 125 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); 133 134 if (status == BufferedResourceLoader::kOk) { 135 EXPECT_EQ(instance_size, loader_->content_length()); 136 EXPECT_EQ(instance_size, loader_->instance_size()); 137 } 138 139 EXPECT_FALSE(loader_->range_supported()); 140 } 141 142 void PartialResponse(int64 first_position, int64 last_position, 143 int64 instance_size) { 144 PartialResponse(first_position, last_position, instance_size, false, true); 145 } 146 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)); 150 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))); 158 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; 166 } 167 response.setExpectedContentLength(content_length); 168 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")); 173 } 174 175 response.setHTTPStatusCode(kHttpPartialContent); 176 loader_->didReceiveResponse(url_loader_, response); 177 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 181 // 182 // Can we eliminate one? 183 EXPECT_EQ(content_length, loader_->content_length()); 184 EXPECT_EQ(instance_size, loader_->instance_size()); 185 186 // A valid partial response should always result in this being true. 187 EXPECT_TRUE(loader_->range_supported()); 188 } 189 190 void Redirect(const char* url) { 191 GURL redirectUrl(url); 192 blink::WebURLRequest newRequest(redirectUrl); 193 blink::WebURLResponse redirectResponse(gurl_); 194 195 loader_->willSendRequest(url_loader_, newRequest, redirectResponse); 196 197 base::MessageLoop::current()->RunUntilIdle(); 198 } 199 200 void StopWhenLoad() { 201 InSequence s; 202 EXPECT_CALL(*url_loader_, cancel()); 203 loader_->Stop(); 204 loader_.reset(); 205 } 206 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); 214 } 215 216 void WriteData(int size) { 217 EXPECT_CALL(*this, ProgressCallback(_)); 218 219 scoped_ptr<char[]> data(new char[size]); 220 loader_->didReceiveData(url_loader_, data.get(), size, size); 221 } 222 223 void WriteUntilThreshold() { 224 int buffered = loader_->buffer_.forward_bytes(); 225 int capacity = loader_->buffer_.forward_capacity(); 226 CHECK_LT(buffered, capacity); 227 228 EXPECT_CALL(*this, LoadingCallback( 229 BufferedResourceLoader::kLoadingDeferred)); 230 WriteData(capacity - buffered); 231 } 232 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))); 238 } 239 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)); 243 } 244 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); 251 } 252 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()); 261 } 262 263 void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity) { 264 EXPECT_EQ(loader_->buffer_.backward_capacity(), 265 expected_backward_capacity); 266 } 267 268 void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity) { 269 EXPECT_EQ(loader_->buffer_.forward_capacity(), expected_forward_capacity); 270 } 271 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); 278 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); 283 } 284 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)); 289 290 protected: 291 GURL gurl_; 292 int64 first_position_; 293 int64 last_position_; 294 295 scoped_ptr<BufferedResourceLoader> loader_; 296 NiceMock<MockWebURLLoader>* url_loader_; 297 298 MockWebFrameClient client_; 299 WebView* view_; 300 WebLocalFrame* frame_; 301 302 base::MessageLoop message_loop_; 303 304 uint8 data_[kDataSize]; 305 306 private: 307 DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest); 308 }; 309 310 TEST_F(BufferedResourceLoaderTest, StartStop) { 311 Initialize(kHttpUrl, -1, -1); 312 Start(); 313 StopWhenLoad(); 314 } 315 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(); 320 321 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed)); 322 323 WebURLResponse response(gurl_); 324 response.setHTTPStatusCode(404); 325 response.setHTTPStatusText("Not Found\n"); 326 loader_->didReceiveResponse(url_loader_, response); 327 StopWhenLoad(); 328 } 329 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(); 336 } 337 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(); 344 } 345 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(); 352 } 353 354 TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) { 355 Initialize(kHttpUrl, 100, 200); 356 Start(); 357 PartialResponse(100, 200, 1024, true, true); 358 StopWhenLoad(); 359 } 360 361 TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) { 362 Initialize(kHttpUrl, 100, 200); 363 Start(); 364 PartialResponse(100, 200, 1024, false, false); 365 StopWhenLoad(); 366 } 367 368 TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) { 369 Initialize(kHttpUrl, 100, 200); 370 Start(); 371 PartialResponse(100, 200, 1024, true, false); 372 StopWhenLoad(); 373 } 374 375 // Tests that an invalid partial response is received. 376 TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) { 377 Initialize(kHttpUrl, 0, 10); 378 Start(); 379 380 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed)); 381 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(); 390 } 391 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); 398 399 uint8 buffer[10]; 400 InSequence s; 401 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); 407 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); 416 417 // Read backward within buffer. 418 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); 419 ReadLoader(10, 10, buffer); 420 VerifyBuffer(buffer, 10, 10); 421 422 // Read backward outside buffer. 423 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 424 ReadLoader(9, 10, buffer); 425 426 // Response has completed. 427 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished)); 428 loader_->didFinishLoading(url_loader_, 0, -1); 429 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); 434 435 // Try to read outside buffered range after request has completed. 436 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 437 ReadLoader(5, 10, buffer); 438 439 // Try to read beyond the instance size. 440 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 0)); 441 ReadLoader(30, 10, buffer); 442 } 443 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); 450 451 uint8 buffer[20]; 452 InSequence s; 453 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); 458 459 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20)); 460 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 461 ReadLoader(10, 20, buffer); 462 463 VerifyBuffer(buffer, 10, 20); 464 ConfirmLoaderBufferForwardCapacity(10); 465 466 // Make and outstanding read request larger than forward capacity. Ensure 467 // forward capacity gets extended. 468 ReadLoader(30, 20, buffer); 469 ConfirmLoaderBufferForwardCapacity(20); 470 471 // Fulfill outstanding request. Ensure forward capacity gets reset. 472 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20)); 473 WriteLoader(30, 20); 474 475 VerifyBuffer(buffer, 30, 20); 476 ConfirmLoaderBufferForwardCapacity(10); 477 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); 482 483 ConfirmLoaderBufferForwardCapacity(10); 484 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); 489 490 ConfirmLoaderBufferForwardCapacity(10); 491 492 StopWhenLoad(); 493 } 494 495 TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) { 496 Initialize(kHttpUrl, 10, 0x00FFFFFF); 497 Start(); 498 PartialResponse(10, 0x00FFFFFF, 0x01000000); 499 500 uint8 buffer[10]; 501 InSequence s; 502 503 // Read very far ahead will get a cache miss. 504 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 505 ReadLoader(0x00FFFFFF, 1, buffer); 506 507 // The following call will not call ReadCallback() because it is waiting for 508 // data to arrive. 509 ReadLoader(10, 10, buffer); 510 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); 515 516 // The following call cannot be fulfilled now. 517 ReadLoader(25, 10, buffer); 518 519 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished)); 520 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); 521 loader_->didFinishLoading(url_loader_, 0, -1); 522 } 523 524 TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) { 525 Initialize(kHttpUrl, 10, 29); 526 Start(); 527 PartialResponse(10, 29, 30); 528 529 uint8 buffer[10]; 530 InSequence s; 531 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); 540 } 541 542 TEST_F(BufferedResourceLoaderTest, RequestFailedWithNoPendingReads) { 543 Initialize(kHttpUrl, 10, 29); 544 Start(); 545 PartialResponse(10, 29, 30); 546 547 uint8 buffer[10]; 548 InSequence s; 549 550 // Write enough data so that a read would technically complete had the request 551 // not failed. 552 WriteLoader(10, 20); 553 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); 560 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); 564 } 565 566 TEST_F(BufferedResourceLoaderTest, RequestCancelledWhenRead) { 567 Initialize(kHttpUrl, 10, 29); 568 Start(); 569 PartialResponse(10, 29, 30); 570 571 uint8 buffer[10]; 572 InSequence s; 573 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); 582 } 583 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); 591 592 uint8 buffer[10]; 593 594 // Read past the buffer size; should not defer regardless. 595 WriteLoader(10, 10); 596 WriteLoader(20, 50); 597 598 // Should move past window. 599 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 600 ReadLoader(10, 10, buffer); 601 602 StopWhenLoad(); 603 } 604 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); 612 613 uint8 buffer[10]; 614 615 // Make an outstanding read request. 616 ReadLoader(10, 10, buffer); 617 618 // Receive almost enough data to cover, shouldn't defer. 619 WriteLoader(10, 9); 620 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); 625 626 VerifyBuffer(buffer, 10, 10); 627 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); 632 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); 637 638 VerifyBuffer(buffer, 20, 10); 639 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); 644 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); 649 650 VerifyBuffer(buffer, 80, 10); 651 652 StopWhenLoad(); 653 } 654 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); 661 662 uint8 buffer[10]; 663 InSequence s; 664 665 // Write half of capacity: keep not deferring. 666 WriteData(5); 667 668 // Write rest of space until capacity: start deferring. 669 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); 670 WriteData(5); 671 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); 676 677 // Write a byte to hit capacity: start deferring. 678 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); 679 WriteData(6); 680 681 StopWhenLoad(); 682 } 683 684 TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) { 685 Initialize(kHttpUrl, 10, 99); 686 SetLoaderBuffer(10, 10); 687 Start(); 688 PartialResponse(10, 99, 100); 689 690 uint8 buffer[256]; 691 InSequence s; 692 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); 700 701 // *** TRICKY BUSINESS, PT. I *** 702 // Read past buffered: stop deferring. 703 // 704 // In order for the read to complete we must: 705 // 1) Stop deferring to receive more data. 706 // 707 // BEFORE 708 // offset=11 [xxxxxxxxx_] 709 // ^ ^^^ requested 4 bytes @ offset 20 710 // AFTER 711 // offset=24 [__________] 712 // 713 ReadLoader(20, 4, buffer); 714 715 // Write a little, make sure we didn't start deferring. 716 WriteData(2); 717 718 // Write the rest, read should complete. 719 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4)); 720 WriteData(2); 721 722 // POSTCONDITION 723 ConfirmBufferState(4, 10, 0, 10); 724 ConfirmLoaderOffsets(24, 0, 0); 725 726 StopWhenLoad(); 727 } 728 729 TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) { 730 Initialize(kHttpUrl, 10, 99); 731 SetLoaderBuffer(10, 10); 732 Start(); 733 PartialResponse(10, 99, 100); 734 735 uint8 buffer[256]; 736 InSequence s; 737 738 // PRECONDITION 739 WriteUntilThreshold(); 740 ConfirmBufferState(0, 10, 10, 10); 741 ConfirmLoaderOffsets(10, 0, 0); 742 743 // *** TRICKY BUSINESS, PT. II *** 744 // Read backwards a little too much: cache miss. 745 // 746 // BEFORE 747 // offset=10 [__________|xxxxxxxxxx] 748 // ^ ^^^ requested 10 bytes @ offset 9 749 // AFTER 750 // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!! 751 // 752 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 753 ReadLoader(9, 4, buffer); 754 755 // POSTCONDITION 756 ConfirmBufferState(0, 10, 10, 10); 757 ConfirmLoaderOffsets(10, 0, 0); 758 759 StopWhenLoad(); 760 } 761 762 TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) { 763 Initialize(kHttpUrl, 10, 99); 764 SetLoaderBuffer(10, 10); 765 Start(); 766 PartialResponse(10, 99, 100); 767 768 uint8 buffer[256]; 769 InSequence s; 770 771 // PRECONDITION 772 WriteUntilThreshold(); 773 ConfirmBufferState(0, 10, 10, 10); 774 ConfirmLoaderOffsets(10, 0, 0); 775 776 // *** TRICKY BUSINESS, PT. III *** 777 // Read past forward capacity but within capacity: stop deferring. 778 // 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. 782 // 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 [__________] 791 // 792 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 793 ReadLoader(24, 4, buffer); 794 ConfirmLoaderOffsets(20, 4, 8); 795 796 // Write a little, make sure we didn't start deferring. 797 WriteData(4); 798 799 // Write the rest, read should complete. 800 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4)); 801 WriteData(4); 802 803 // POSTCONDITION 804 ConfirmBufferState(8, 10, 0, 10); 805 ConfirmLoaderOffsets(28, 0, 0); 806 807 StopWhenLoad(); 808 } 809 810 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) { 811 Initialize(kHttpUrl, 10, 99); 812 SetLoaderBuffer(10, 10); 813 Start(); 814 PartialResponse(10, 99, 100); 815 816 uint8 buffer[256]; 817 InSequence s; 818 819 // PRECONDITION 820 WriteUntilThreshold(); 821 ConfirmBufferState(0, 10, 10, 10); 822 ConfirmLoaderOffsets(10, 0, 0); 823 824 // *** TRICKY BUSINESS, PT. IV *** 825 // Read a large amount past forward capacity but within 826 // capacity: stop deferring. 827 // 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. 832 // 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 [__________] 844 // 845 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 846 ReadLoader(24, 12, buffer); 847 ConfirmLoaderOffsets(20, 4, 16); 848 ConfirmBufferState(10, 10, 0, 16); 849 850 // Write a little, make sure we didn't start deferring. 851 WriteData(10); 852 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); 857 858 // POSTCONDITION 859 ConfirmBufferState(6, 10, 0, 10); 860 ConfirmLoaderOffsets(36, 0, 0); 861 862 StopWhenLoad(); 863 } 864 865 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) { 866 Initialize(kHttpUrl, 10, 99); 867 SetLoaderBuffer(10, 10); 868 Start(); 869 PartialResponse(10, 99, 100); 870 871 uint8 buffer[256]; 872 InSequence s; 873 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); 882 883 // *** TRICKY BUSINESS, PT. V *** 884 // Read a large amount that involves backwards data: stop deferring. 885 // 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. 890 // 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|__________] 902 // 903 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 904 ReadLoader(16, 18, buffer); 905 ConfirmLoaderOffsets(16, 0, 18); 906 ConfirmBufferState(6, 10, 14, 18); 907 908 // Write a little, make sure we didn't start deferring. 909 WriteData(2); 910 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); 915 916 // POSTCONDITION 917 ConfirmBufferState(4, 10, 0, 10); 918 ConfirmLoaderOffsets(34, 0, 0); 919 920 StopWhenLoad(); 921 } 922 923 TEST_F(BufferedResourceLoaderTest, Tricky_ReadPastThreshold) { 924 const int kSize = 5 * 1024 * 1024; 925 const int kThreshold = 2 * 1024 * 1024; 926 927 Initialize(kHttpUrl, 10, kSize); 928 SetLoaderBuffer(10, 10); 929 Start(); 930 PartialResponse(10, kSize - 1, kSize); 931 932 uint8 buffer[256]; 933 InSequence s; 934 935 // PRECONDITION 936 WriteUntilThreshold(); 937 ConfirmBufferState(0, 10, 10, 10); 938 ConfirmLoaderOffsets(10, 0, 0); 939 940 // *** TRICKY BUSINESS, PT. VI *** 941 // Read past the forward wait threshold: cache miss. 942 // 943 // BEFORE 944 // offset=10 [xxxxxxxxxx] ... 945 // ^^^^ requested 10 bytes @ threshold 946 // AFTER 947 // offset=10 [xxxxxxxxxx] !!! cache miss !!! 948 // 949 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 950 ReadLoader(kThreshold + 20, 10, buffer); 951 952 // POSTCONDITION 953 ConfirmBufferState(0, 10, 10, 10); 954 ConfirmLoaderOffsets(10, 0, 0); 955 956 StopWhenLoad(); 957 } 958 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(); 966 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(); 974 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(); 983 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(); 991 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(); 1000 } 1001 1002 TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) { 1003 Initialize(kHttpUrl, -1, -1); 1004 Start(); 1005 1006 // Test ensures that default construction of a BufferedResourceLoader has sane 1007 // values. 1008 // 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); 1014 1015 StopWhenLoad(); 1016 } 1017 1018 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) { 1019 Initialize(kHttpUrl, -1, -1); 1020 Start(); 1021 loader_->SetBitrate(0); 1022 CheckBufferWindowBounds(); 1023 StopWhenLoad(); 1024 } 1025 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(); 1032 } 1033 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(); 1040 } 1041 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(); 1048 } 1049 1050 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) { 1051 Initialize(kHttpUrl, -1, -1); 1052 Start(); 1053 loader_->SetPlaybackRate(-10); 1054 CheckBufferWindowBounds(); 1055 StopWhenLoad(); 1056 } 1057 1058 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) { 1059 Initialize(kHttpUrl, -1, -1); 1060 Start(); 1061 loader_->SetPlaybackRate(0); 1062 CheckBufferWindowBounds(); 1063 StopWhenLoad(); 1064 } 1065 1066 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) { 1067 Initialize(kHttpUrl, -1, -1); 1068 Start(); 1069 loader_->SetPlaybackRate(0.1f); 1070 CheckBufferWindowBounds(); 1071 StopWhenLoad(); 1072 } 1073 1074 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) { 1075 Initialize(kHttpUrl, -1, -1); 1076 Start(); 1077 loader_->SetPlaybackRate(10); 1078 CheckBufferWindowBounds(); 1079 StopWhenLoad(); 1080 } 1081 1082 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) { 1083 Initialize(kHttpUrl, -1, -1); 1084 Start(); 1085 loader_->SetPlaybackRate(100); 1086 CheckBufferWindowBounds(); 1087 StopWhenLoad(); 1088 } 1089 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); 1101 } 1102 1103 static void ExpectContentRangeFailure(const std::string& str) { 1104 ExpectContentRange(str, false, 0, 0, 0); 1105 } 1106 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); 1111 } 1112 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"); 1123 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); 1129 } 1130 1131 } // namespace media 1132