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 "content/renderer/media/buffered_resource_loader.h" 13 #include "content/test/mock_webframeclient.h" 14 #include "content/test/mock_weburlloader.h" 15 #include "media/base/media_log.h" 16 #include "media/base/seekable_buffer.h" 17 #include "net/base/net_errors.h" 18 #include "net/http/http_request_headers.h" 19 #include "net/http/http_util.h" 20 #include "third_party/WebKit/public/platform/WebString.h" 21 #include "third_party/WebKit/public/platform/WebURLError.h" 22 #include "third_party/WebKit/public/platform/WebURLRequest.h" 23 #include "third_party/WebKit/public/platform/WebURLResponse.h" 24 #include "third_party/WebKit/public/web/WebFrame.h" 25 #include "third_party/WebKit/public/web/WebView.h" 26 27 using ::testing::_; 28 using ::testing::InSequence; 29 using ::testing::Return; 30 using ::testing::Truly; 31 using ::testing::NiceMock; 32 33 using blink::WebString; 34 using blink::WebURLError; 35 using blink::WebURLResponse; 36 using blink::WebView; 37 38 namespace content { 39 40 static const char* kHttpUrl = "http://test"; 41 static const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing"; 42 static const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2"; 43 static const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2"; 44 45 static const int kDataSize = 1024; 46 static const int kHttpOK = 200; 47 static const int kHttpPartialContent = 206; 48 49 enum NetworkState { 50 NONE, 51 LOADED, 52 LOADING 53 }; 54 55 // Predicate that tests that request disallows compressed data. 56 static bool CorrectAcceptEncoding(const blink::WebURLRequest &request) { 57 std::string value = request.httpHeaderField( 58 WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding)).utf8(); 59 return (value.find("identity;q=1") != std::string::npos) && 60 (value.find("*;q=0") != std::string::npos); 61 } 62 63 class BufferedResourceLoaderTest : public testing::Test { 64 public: 65 BufferedResourceLoaderTest() 66 : view_(WebView::create(NULL)) { 67 view_->initializeMainFrame(&client_); 68 69 for (int i = 0; i < kDataSize; ++i) { 70 data_[i] = i; 71 } 72 } 73 74 virtual ~BufferedResourceLoaderTest() { 75 view_->close(); 76 } 77 78 void Initialize(const char* url, int first_position, int last_position) { 79 gurl_ = GURL(url); 80 first_position_ = first_position; 81 last_position_ = last_position; 82 83 loader_.reset(new BufferedResourceLoader( 84 gurl_, BufferedResourceLoader::kUnspecified, 85 first_position_, last_position_, 86 BufferedResourceLoader::kCapacityDefer, 0, 0, 87 new media::MediaLog())); 88 89 // |test_loader_| will be used when Start() is called. 90 url_loader_ = new NiceMock<MockWebURLLoader>(); 91 loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_); 92 } 93 94 void SetLoaderBuffer(int forward_capacity, int backward_capacity) { 95 loader_->buffer_.set_forward_capacity(forward_capacity); 96 loader_->buffer_.set_backward_capacity(backward_capacity); 97 loader_->buffer_.Clear(); 98 } 99 100 void Start() { 101 InSequence s; 102 EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding), 103 loader_.get())); 104 105 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 106 loader_->Start( 107 base::Bind(&BufferedResourceLoaderTest::StartCallback, 108 base::Unretained(this)), 109 base::Bind(&BufferedResourceLoaderTest::LoadingCallback, 110 base::Unretained(this)), 111 base::Bind(&BufferedResourceLoaderTest::ProgressCallback, 112 base::Unretained(this)), 113 view_->mainFrame()); 114 } 115 116 void FullResponse(int64 instance_size) { 117 FullResponse(instance_size, BufferedResourceLoader::kOk); 118 } 119 120 void FullResponse(int64 instance_size, 121 BufferedResourceLoader::Status status) { 122 EXPECT_CALL(*this, StartCallback(status)); 123 124 WebURLResponse response(gurl_); 125 response.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), 126 WebString::fromUTF8(base::StringPrintf("%" 127 PRId64, instance_size))); 128 response.setExpectedContentLength(instance_size); 129 response.setHTTPStatusCode(kHttpOK); 130 loader_->didReceiveResponse(url_loader_, response); 131 132 if (status == BufferedResourceLoader::kOk) { 133 EXPECT_EQ(instance_size, loader_->content_length()); 134 EXPECT_EQ(instance_size, loader_->instance_size()); 135 } 136 137 EXPECT_FALSE(loader_->range_supported()); 138 } 139 140 void PartialResponse(int64 first_position, int64 last_position, 141 int64 instance_size) { 142 PartialResponse(first_position, last_position, instance_size, false, true); 143 } 144 145 void PartialResponse(int64 first_position, int64 last_position, 146 int64 instance_size, bool chunked, bool accept_ranges) { 147 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kOk)); 148 149 WebURLResponse response(gurl_); 150 response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"), 151 WebString::fromUTF8(base::StringPrintf("bytes " 152 "%" PRId64 "-%" PRId64 "/%" PRId64, 153 first_position, 154 last_position, 155 instance_size))); 156 157 // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked. 158 int64 content_length = -1; 159 if (chunked) { 160 response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"), 161 WebString::fromUTF8("chunked")); 162 } else { 163 content_length = last_position - first_position + 1; 164 } 165 response.setExpectedContentLength(content_length); 166 167 // A server isn't required to return Accept-Ranges even though it might. 168 if (accept_ranges) { 169 response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"), 170 WebString::fromUTF8("bytes")); 171 } 172 173 response.setHTTPStatusCode(kHttpPartialContent); 174 loader_->didReceiveResponse(url_loader_, response); 175 176 // XXX: what's the difference between these two? For example in the chunked 177 // range request case, Content-Length is unspecified (because it's chunked) 178 // but Content-Range: a-b/c can be returned, where c == Content-Length 179 // 180 // Can we eliminate one? 181 EXPECT_EQ(content_length, loader_->content_length()); 182 EXPECT_EQ(instance_size, loader_->instance_size()); 183 184 // A valid partial response should always result in this being true. 185 EXPECT_TRUE(loader_->range_supported()); 186 } 187 188 void Redirect(const char* url) { 189 GURL redirectUrl(url); 190 blink::WebURLRequest newRequest(redirectUrl); 191 blink::WebURLResponse redirectResponse(gurl_); 192 193 loader_->willSendRequest(url_loader_, newRequest, redirectResponse); 194 195 base::MessageLoop::current()->RunUntilIdle(); 196 } 197 198 void StopWhenLoad() { 199 InSequence s; 200 EXPECT_CALL(*url_loader_, cancel()); 201 loader_->Stop(); 202 loader_.reset(); 203 } 204 205 // Helper method to write to |loader_| from |data_|. 206 void WriteLoader(int position, int size) { 207 EXPECT_CALL(*this, ProgressCallback(position + size - 1)); 208 loader_->didReceiveData(url_loader_, 209 reinterpret_cast<char*>(data_ + position), 210 size, 211 size); 212 } 213 214 void WriteData(int size) { 215 EXPECT_CALL(*this, ProgressCallback(_)); 216 217 scoped_ptr<char[]> data(new char[size]); 218 loader_->didReceiveData(url_loader_, data.get(), size, size); 219 } 220 221 void WriteUntilThreshold() { 222 int buffered = loader_->buffer_.forward_bytes(); 223 int capacity = loader_->buffer_.forward_capacity(); 224 CHECK_LT(buffered, capacity); 225 226 EXPECT_CALL(*this, LoadingCallback( 227 BufferedResourceLoader::kLoadingDeferred)); 228 WriteData(capacity - buffered); 229 } 230 231 // Helper method to read from |loader_|. 232 void ReadLoader(int64 position, int size, uint8* buffer) { 233 loader_->Read(position, size, buffer, 234 base::Bind(&BufferedResourceLoaderTest::ReadCallback, 235 base::Unretained(this))); 236 } 237 238 // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size]. 239 void VerifyBuffer(uint8* buffer, int pos, int size) { 240 EXPECT_EQ(0, memcmp(buffer, data_ + pos, size)); 241 } 242 243 void ConfirmLoaderOffsets(int64 expected_offset, 244 int expected_first_offset, 245 int expected_last_offset) { 246 EXPECT_EQ(loader_->offset_, expected_offset); 247 EXPECT_EQ(loader_->first_offset_, expected_first_offset); 248 EXPECT_EQ(loader_->last_offset_, expected_last_offset); 249 } 250 251 void ConfirmBufferState(int backward_bytes, 252 int backward_capacity, 253 int forward_bytes, 254 int forward_capacity) { 255 EXPECT_EQ(backward_bytes, loader_->buffer_.backward_bytes()); 256 EXPECT_EQ(backward_capacity, loader_->buffer_.backward_capacity()); 257 EXPECT_EQ(forward_bytes, loader_->buffer_.forward_bytes()); 258 EXPECT_EQ(forward_capacity, loader_->buffer_.forward_capacity()); 259 } 260 261 void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity) { 262 EXPECT_EQ(loader_->buffer_.backward_capacity(), 263 expected_backward_capacity); 264 } 265 266 void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity) { 267 EXPECT_EQ(loader_->buffer_.forward_capacity(), expected_forward_capacity); 268 } 269 270 // Makes sure the |loader_| buffer window is in a reasonable range. 271 void CheckBufferWindowBounds() { 272 // Corresponds to value defined in buffered_resource_loader.cc. 273 static const int kMinBufferCapacity = 2 * 1024 * 1024; 274 EXPECT_GE(loader_->buffer_.forward_capacity(), kMinBufferCapacity); 275 EXPECT_GE(loader_->buffer_.backward_capacity(), kMinBufferCapacity); 276 277 // Corresponds to value defined in buffered_resource_loader.cc. 278 static const int kMaxBufferCapacity = 20 * 1024 * 1024; 279 EXPECT_LE(loader_->buffer_.forward_capacity(), kMaxBufferCapacity); 280 EXPECT_LE(loader_->buffer_.backward_capacity(), kMaxBufferCapacity); 281 } 282 283 MOCK_METHOD1(StartCallback, void(BufferedResourceLoader::Status)); 284 MOCK_METHOD2(ReadCallback, void(BufferedResourceLoader::Status, int)); 285 MOCK_METHOD1(LoadingCallback, void(BufferedResourceLoader::LoadingState)); 286 MOCK_METHOD1(ProgressCallback, void(int64)); 287 288 protected: 289 GURL gurl_; 290 int64 first_position_; 291 int64 last_position_; 292 293 scoped_ptr<BufferedResourceLoader> loader_; 294 NiceMock<MockWebURLLoader>* url_loader_; 295 296 MockWebFrameClient client_; 297 WebView* view_; 298 299 base::MessageLoop message_loop_; 300 301 uint8 data_[kDataSize]; 302 303 private: 304 DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest); 305 }; 306 307 TEST_F(BufferedResourceLoaderTest, StartStop) { 308 Initialize(kHttpUrl, -1, -1); 309 Start(); 310 StopWhenLoad(); 311 } 312 313 // Tests that a bad HTTP response is recived, e.g. file not found. 314 TEST_F(BufferedResourceLoaderTest, BadHttpResponse) { 315 Initialize(kHttpUrl, -1, -1); 316 Start(); 317 318 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed)); 319 320 WebURLResponse response(gurl_); 321 response.setHTTPStatusCode(404); 322 response.setHTTPStatusText("Not Found\n"); 323 loader_->didReceiveResponse(url_loader_, response); 324 StopWhenLoad(); 325 } 326 327 // Tests that partial content is requested but not fulfilled. 328 TEST_F(BufferedResourceLoaderTest, NotPartialResponse) { 329 Initialize(kHttpUrl, 100, -1); 330 Start(); 331 FullResponse(1024, BufferedResourceLoader::kFailed); 332 StopWhenLoad(); 333 } 334 335 // Tests that a 200 response is received. 336 TEST_F(BufferedResourceLoaderTest, FullResponse) { 337 Initialize(kHttpUrl, -1, -1); 338 Start(); 339 FullResponse(1024); 340 StopWhenLoad(); 341 } 342 343 // Tests that a partial content response is received. 344 TEST_F(BufferedResourceLoaderTest, PartialResponse) { 345 Initialize(kHttpUrl, 100, 200); 346 Start(); 347 PartialResponse(100, 200, 1024); 348 StopWhenLoad(); 349 } 350 351 TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) { 352 Initialize(kHttpUrl, 100, 200); 353 Start(); 354 PartialResponse(100, 200, 1024, true, true); 355 StopWhenLoad(); 356 } 357 358 TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) { 359 Initialize(kHttpUrl, 100, 200); 360 Start(); 361 PartialResponse(100, 200, 1024, false, false); 362 StopWhenLoad(); 363 } 364 365 TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) { 366 Initialize(kHttpUrl, 100, 200); 367 Start(); 368 PartialResponse(100, 200, 1024, true, false); 369 StopWhenLoad(); 370 } 371 372 // Tests that an invalid partial response is received. 373 TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) { 374 Initialize(kHttpUrl, 0, 10); 375 Start(); 376 377 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed)); 378 379 WebURLResponse response(gurl_); 380 response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"), 381 WebString::fromUTF8(base::StringPrintf("bytes " 382 "%d-%d/%d", 1, 10, 1024))); 383 response.setExpectedContentLength(10); 384 response.setHTTPStatusCode(kHttpPartialContent); 385 loader_->didReceiveResponse(url_loader_, response); 386 StopWhenLoad(); 387 } 388 389 // Tests the logic of sliding window for data buffering and reading. 390 TEST_F(BufferedResourceLoaderTest, BufferAndRead) { 391 Initialize(kHttpUrl, 10, 29); 392 loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); 393 Start(); 394 PartialResponse(10, 29, 30); 395 396 uint8 buffer[10]; 397 InSequence s; 398 399 // Writes 10 bytes and read them back. 400 WriteLoader(10, 10); 401 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); 402 ReadLoader(10, 10, buffer); 403 VerifyBuffer(buffer, 10, 10); 404 405 // Writes 10 bytes and read 2 times. 406 WriteLoader(20, 10); 407 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); 408 ReadLoader(20, 5, buffer); 409 VerifyBuffer(buffer, 20, 5); 410 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); 411 ReadLoader(25, 5, buffer); 412 VerifyBuffer(buffer, 25, 5); 413 414 // Read backward within buffer. 415 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); 416 ReadLoader(10, 10, buffer); 417 VerifyBuffer(buffer, 10, 10); 418 419 // Read backward outside buffer. 420 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 421 ReadLoader(9, 10, buffer); 422 423 // Response has completed. 424 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished)); 425 loader_->didFinishLoading(url_loader_, 0); 426 427 // Try to read 10 from position 25 will just return with 5 bytes. 428 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); 429 ReadLoader(25, 10, buffer); 430 VerifyBuffer(buffer, 25, 5); 431 432 // Try to read outside buffered range after request has completed. 433 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 434 ReadLoader(5, 10, buffer); 435 436 // Try to read beyond the instance size. 437 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 0)); 438 ReadLoader(30, 10, buffer); 439 } 440 441 // Tests the logic of expanding the data buffer for large reads. 442 TEST_F(BufferedResourceLoaderTest, ReadExtendBuffer) { 443 Initialize(kHttpUrl, 10, 0x014FFFFFF); 444 SetLoaderBuffer(10, 20); 445 Start(); 446 PartialResponse(10, 0x014FFFFFF, 0x015000000); 447 448 uint8 buffer[20]; 449 InSequence s; 450 451 // Write more than forward capacity and read it back. Ensure forward capacity 452 // gets reset after reading. 453 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); 454 WriteLoader(10, 20); 455 456 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20)); 457 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 458 ReadLoader(10, 20, buffer); 459 460 VerifyBuffer(buffer, 10, 20); 461 ConfirmLoaderBufferForwardCapacity(10); 462 463 // Make and outstanding read request larger than forward capacity. Ensure 464 // forward capacity gets extended. 465 ReadLoader(30, 20, buffer); 466 ConfirmLoaderBufferForwardCapacity(20); 467 468 // Fulfill outstanding request. Ensure forward capacity gets reset. 469 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20)); 470 WriteLoader(30, 20); 471 472 VerifyBuffer(buffer, 30, 20); 473 ConfirmLoaderBufferForwardCapacity(10); 474 475 // Try to read further ahead than kForwardWaitThreshold allows. Ensure 476 // forward capacity is not changed. 477 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 478 ReadLoader(0x00300000, 1, buffer); 479 480 ConfirmLoaderBufferForwardCapacity(10); 481 482 // Try to read more than maximum forward capacity. Ensure forward capacity is 483 // not changed. 484 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0)); 485 ReadLoader(30, 0x01400001, buffer); 486 487 ConfirmLoaderBufferForwardCapacity(10); 488 489 StopWhenLoad(); 490 } 491 492 TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) { 493 Initialize(kHttpUrl, 10, 0x00FFFFFF); 494 Start(); 495 PartialResponse(10, 0x00FFFFFF, 0x01000000); 496 497 uint8 buffer[10]; 498 InSequence s; 499 500 // Read very far ahead will get a cache miss. 501 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 502 ReadLoader(0x00FFFFFF, 1, buffer); 503 504 // The following call will not call ReadCallback() because it is waiting for 505 // data to arrive. 506 ReadLoader(10, 10, buffer); 507 508 // Writing to loader will fulfill the read request. 509 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); 510 WriteLoader(10, 20); 511 VerifyBuffer(buffer, 10, 10); 512 513 // The following call cannot be fulfilled now. 514 ReadLoader(25, 10, buffer); 515 516 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished)); 517 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); 518 loader_->didFinishLoading(url_loader_, 0); 519 } 520 521 TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) { 522 Initialize(kHttpUrl, 10, 29); 523 Start(); 524 PartialResponse(10, 29, 30); 525 526 uint8 buffer[10]; 527 InSequence s; 528 529 // We should convert any error we receive to BufferedResourceLoader::kFailed. 530 ReadLoader(10, 10, buffer); 531 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed)); 532 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0)); 533 WebURLError error; 534 error.reason = net::ERR_TIMED_OUT; 535 error.isCancellation = false; 536 loader_->didFail(url_loader_, error); 537 } 538 539 TEST_F(BufferedResourceLoaderTest, RequestFailedWithNoPendingReads) { 540 Initialize(kHttpUrl, 10, 29); 541 Start(); 542 PartialResponse(10, 29, 30); 543 544 uint8 buffer[10]; 545 InSequence s; 546 547 // Write enough data so that a read would technically complete had the request 548 // not failed. 549 WriteLoader(10, 20); 550 551 // Fail without a pending read. 552 WebURLError error; 553 error.reason = net::ERR_TIMED_OUT; 554 error.isCancellation = false; 555 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed)); 556 loader_->didFail(url_loader_, error); 557 558 // Now we should immediately fail any read even if we have data buffered. 559 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0)); 560 ReadLoader(10, 10, buffer); 561 } 562 563 TEST_F(BufferedResourceLoaderTest, RequestCancelledWhenRead) { 564 Initialize(kHttpUrl, 10, 29); 565 Start(); 566 PartialResponse(10, 29, 30); 567 568 uint8 buffer[10]; 569 InSequence s; 570 571 // We should convert any error we receive to BufferedResourceLoader::kFailed. 572 ReadLoader(10, 10, buffer); 573 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed)); 574 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0)); 575 WebURLError error; 576 error.reason = 0; 577 error.isCancellation = true; 578 loader_->didFail(url_loader_, error); 579 } 580 581 // Tests the data buffering logic of NeverDefer strategy. 582 TEST_F(BufferedResourceLoaderTest, NeverDeferStrategy) { 583 Initialize(kHttpUrl, 10, 99); 584 SetLoaderBuffer(10, 20); 585 loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); 586 Start(); 587 PartialResponse(10, 99, 100); 588 589 uint8 buffer[10]; 590 591 // Read past the buffer size; should not defer regardless. 592 WriteLoader(10, 10); 593 WriteLoader(20, 50); 594 595 // Should move past window. 596 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 597 ReadLoader(10, 10, buffer); 598 599 StopWhenLoad(); 600 } 601 602 // Tests the data buffering logic of ReadThenDefer strategy. 603 TEST_F(BufferedResourceLoaderTest, ReadThenDeferStrategy) { 604 Initialize(kHttpUrl, 10, 99); 605 SetLoaderBuffer(10, 20); 606 loader_->UpdateDeferStrategy(BufferedResourceLoader::kReadThenDefer); 607 Start(); 608 PartialResponse(10, 99, 100); 609 610 uint8 buffer[10]; 611 612 // Make an outstanding read request. 613 ReadLoader(10, 10, buffer); 614 615 // Receive almost enough data to cover, shouldn't defer. 616 WriteLoader(10, 9); 617 618 // As soon as we have received enough data to fulfill the read, defer. 619 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); 620 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); 621 WriteLoader(19, 1); 622 623 VerifyBuffer(buffer, 10, 10); 624 625 // Read again which should disable deferring since there should be nothing 626 // left in our internal buffer. 627 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 628 ReadLoader(20, 10, buffer); 629 630 // Over-fulfill requested bytes, then deferring should be enabled again. 631 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); 632 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); 633 WriteLoader(20, 40); 634 635 VerifyBuffer(buffer, 20, 10); 636 637 // Read far ahead, which should disable deferring. In this case we still have 638 // bytes in our internal buffer. 639 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 640 ReadLoader(80, 10, buffer); 641 642 // Fulfill requested bytes, then deferring should be enabled again. 643 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); 644 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); 645 WriteLoader(60, 40); 646 647 VerifyBuffer(buffer, 80, 10); 648 649 StopWhenLoad(); 650 } 651 652 // Tests the data buffering logic of kCapacityDefer strategy. 653 TEST_F(BufferedResourceLoaderTest, ThresholdDeferStrategy) { 654 Initialize(kHttpUrl, 10, 99); 655 SetLoaderBuffer(10, 20); 656 Start(); 657 PartialResponse(10, 99, 100); 658 659 uint8 buffer[10]; 660 InSequence s; 661 662 // Write half of capacity: keep not deferring. 663 WriteData(5); 664 665 // Write rest of space until capacity: start deferring. 666 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); 667 WriteData(5); 668 669 // Read a byte from the buffer: stop deferring. 670 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1)); 671 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 672 ReadLoader(10, 1, buffer); 673 674 // Write a byte to hit capacity: start deferring. 675 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); 676 WriteData(6); 677 678 StopWhenLoad(); 679 } 680 681 TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) { 682 Initialize(kHttpUrl, 10, 99); 683 SetLoaderBuffer(10, 10); 684 Start(); 685 PartialResponse(10, 99, 100); 686 687 uint8 buffer[256]; 688 InSequence s; 689 690 // PRECONDITION 691 WriteUntilThreshold(); 692 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1)); 693 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 694 ReadLoader(10, 1, buffer); 695 ConfirmBufferState(1, 10, 9, 10); 696 ConfirmLoaderOffsets(11, 0, 0); 697 698 // *** TRICKY BUSINESS, PT. I *** 699 // Read past buffered: stop deferring. 700 // 701 // In order for the read to complete we must: 702 // 1) Stop deferring to receive more data. 703 // 704 // BEFORE 705 // offset=11 [xxxxxxxxx_] 706 // ^ ^^^ requested 4 bytes @ offset 20 707 // AFTER 708 // offset=24 [__________] 709 // 710 ReadLoader(20, 4, buffer); 711 712 // Write a little, make sure we didn't start deferring. 713 WriteData(2); 714 715 // Write the rest, read should complete. 716 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4)); 717 WriteData(2); 718 719 // POSTCONDITION 720 ConfirmBufferState(4, 10, 0, 10); 721 ConfirmLoaderOffsets(24, 0, 0); 722 723 StopWhenLoad(); 724 } 725 726 TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) { 727 Initialize(kHttpUrl, 10, 99); 728 SetLoaderBuffer(10, 10); 729 Start(); 730 PartialResponse(10, 99, 100); 731 732 uint8 buffer[256]; 733 InSequence s; 734 735 // PRECONDITION 736 WriteUntilThreshold(); 737 ConfirmBufferState(0, 10, 10, 10); 738 ConfirmLoaderOffsets(10, 0, 0); 739 740 // *** TRICKY BUSINESS, PT. II *** 741 // Read backwards a little too much: cache miss. 742 // 743 // BEFORE 744 // offset=10 [__________|xxxxxxxxxx] 745 // ^ ^^^ requested 10 bytes @ offset 9 746 // AFTER 747 // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!! 748 // 749 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 750 ReadLoader(9, 4, buffer); 751 752 // POSTCONDITION 753 ConfirmBufferState(0, 10, 10, 10); 754 ConfirmLoaderOffsets(10, 0, 0); 755 756 StopWhenLoad(); 757 } 758 759 TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) { 760 Initialize(kHttpUrl, 10, 99); 761 SetLoaderBuffer(10, 10); 762 Start(); 763 PartialResponse(10, 99, 100); 764 765 uint8 buffer[256]; 766 InSequence s; 767 768 // PRECONDITION 769 WriteUntilThreshold(); 770 ConfirmBufferState(0, 10, 10, 10); 771 ConfirmLoaderOffsets(10, 0, 0); 772 773 // *** TRICKY BUSINESS, PT. III *** 774 // Read past forward capacity but within capacity: stop deferring. 775 // 776 // In order for the read to complete we must: 777 // 1) Adjust offset forward to create capacity. 778 // 2) Stop deferring to receive more data. 779 // 780 // BEFORE 781 // offset=10 [xxxxxxxxxx] 782 // ^^^^ requested 4 bytes @ offset 24 783 // ADJUSTED OFFSET 784 // offset=20 [__________] 785 // ^^^^ requested 4 bytes @ offset 24 786 // AFTER 787 // offset=28 [__________] 788 // 789 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 790 ReadLoader(24, 4, buffer); 791 ConfirmLoaderOffsets(20, 4, 8); 792 793 // Write a little, make sure we didn't start deferring. 794 WriteData(4); 795 796 // Write the rest, read should complete. 797 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4)); 798 WriteData(4); 799 800 // POSTCONDITION 801 ConfirmBufferState(8, 10, 0, 10); 802 ConfirmLoaderOffsets(28, 0, 0); 803 804 StopWhenLoad(); 805 } 806 807 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) { 808 Initialize(kHttpUrl, 10, 99); 809 SetLoaderBuffer(10, 10); 810 Start(); 811 PartialResponse(10, 99, 100); 812 813 uint8 buffer[256]; 814 InSequence s; 815 816 // PRECONDITION 817 WriteUntilThreshold(); 818 ConfirmBufferState(0, 10, 10, 10); 819 ConfirmLoaderOffsets(10, 0, 0); 820 821 // *** TRICKY BUSINESS, PT. IV *** 822 // Read a large amount past forward capacity but within 823 // capacity: stop deferring. 824 // 825 // In order for the read to complete we must: 826 // 1) Adjust offset forward to create capacity. 827 // 2) Expand capacity to make sure we don't defer as data arrives. 828 // 3) Stop deferring to receive more data. 829 // 830 // BEFORE 831 // offset=10 [xxxxxxxxxx] 832 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24 833 // ADJUSTED OFFSET 834 // offset=20 [__________] 835 // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24 836 // ADJUSTED CAPACITY 837 // offset=20 [________________] 838 // ^^^^^^^^^^^^ requested 12 bytes @ offset 24 839 // AFTER 840 // offset=36 [__________] 841 // 842 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 843 ReadLoader(24, 12, buffer); 844 ConfirmLoaderOffsets(20, 4, 16); 845 ConfirmBufferState(10, 10, 0, 16); 846 847 // Write a little, make sure we didn't start deferring. 848 WriteData(10); 849 850 // Write the rest, read should complete and capacity should go back to normal. 851 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 12)); 852 WriteData(6); 853 ConfirmLoaderBufferForwardCapacity(10); 854 855 // POSTCONDITION 856 ConfirmBufferState(6, 10, 0, 10); 857 ConfirmLoaderOffsets(36, 0, 0); 858 859 StopWhenLoad(); 860 } 861 862 TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) { 863 Initialize(kHttpUrl, 10, 99); 864 SetLoaderBuffer(10, 10); 865 Start(); 866 PartialResponse(10, 99, 100); 867 868 uint8 buffer[256]; 869 InSequence s; 870 871 // PRECONDITION 872 WriteUntilThreshold(); 873 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); 874 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 875 ReadLoader(10, 10, buffer); 876 WriteUntilThreshold(); 877 ConfirmBufferState(10, 10, 10, 10); 878 ConfirmLoaderOffsets(20, 0, 0); 879 880 // *** TRICKY BUSINESS, PT. V *** 881 // Read a large amount that involves backwards data: stop deferring. 882 // 883 // In order for the read to complete we must: 884 // 1) Adjust offset *backwards* to create capacity. 885 // 2) Expand capacity to make sure we don't defer as data arrives. 886 // 3) Stop deferring to receive more data. 887 // 888 // BEFORE 889 // offset=20 [xxxxxxxxxx|xxxxxxxxxx] 890 // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16 891 // ADJUSTED OFFSET 892 // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx 893 // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16 894 // ADJUSTED CAPACITY 895 // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____] 896 // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16 897 // AFTER 898 // offset=34 [xxxxxxxxxx|__________] 899 // 900 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 901 ReadLoader(16, 18, buffer); 902 ConfirmLoaderOffsets(16, 0, 18); 903 ConfirmBufferState(6, 10, 14, 18); 904 905 // Write a little, make sure we didn't start deferring. 906 WriteData(2); 907 908 // Write the rest, read should complete and capacity should go back to normal. 909 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 18)); 910 WriteData(2); 911 ConfirmLoaderBufferForwardCapacity(10); 912 913 // POSTCONDITION 914 ConfirmBufferState(4, 10, 0, 10); 915 ConfirmLoaderOffsets(34, 0, 0); 916 917 StopWhenLoad(); 918 } 919 920 TEST_F(BufferedResourceLoaderTest, Tricky_ReadPastThreshold) { 921 const int kSize = 5 * 1024 * 1024; 922 const int kThreshold = 2 * 1024 * 1024; 923 924 Initialize(kHttpUrl, 10, kSize); 925 SetLoaderBuffer(10, 10); 926 Start(); 927 PartialResponse(10, kSize - 1, kSize); 928 929 uint8 buffer[256]; 930 InSequence s; 931 932 // PRECONDITION 933 WriteUntilThreshold(); 934 ConfirmBufferState(0, 10, 10, 10); 935 ConfirmLoaderOffsets(10, 0, 0); 936 937 // *** TRICKY BUSINESS, PT. VI *** 938 // Read past the forward wait threshold: cache miss. 939 // 940 // BEFORE 941 // offset=10 [xxxxxxxxxx] ... 942 // ^^^^ requested 10 bytes @ threshold 943 // AFTER 944 // offset=10 [xxxxxxxxxx] !!! cache miss !!! 945 // 946 EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); 947 ReadLoader(kThreshold + 20, 10, buffer); 948 949 // POSTCONDITION 950 ConfirmBufferState(0, 10, 10, 10); 951 ConfirmLoaderOffsets(10, 0, 0); 952 953 StopWhenLoad(); 954 } 955 956 TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) { 957 // Make sure no redirect case works as expected. 958 Initialize(kHttpUrl, -1, -1); 959 Start(); 960 FullResponse(1024); 961 EXPECT_TRUE(loader_->HasSingleOrigin()); 962 StopWhenLoad(); 963 964 // Test redirect to the same domain. 965 Initialize(kHttpUrl, -1, -1); 966 Start(); 967 Redirect(kHttpRedirectToSameDomainUrl1); 968 FullResponse(1024); 969 EXPECT_TRUE(loader_->HasSingleOrigin()); 970 StopWhenLoad(); 971 972 // Test redirect twice to the same domain. 973 Initialize(kHttpUrl, -1, -1); 974 Start(); 975 Redirect(kHttpRedirectToSameDomainUrl1); 976 Redirect(kHttpRedirectToSameDomainUrl2); 977 FullResponse(1024); 978 EXPECT_TRUE(loader_->HasSingleOrigin()); 979 StopWhenLoad(); 980 981 // Test redirect to a different domain. 982 Initialize(kHttpUrl, -1, -1); 983 Start(); 984 Redirect(kHttpRedirectToDifferentDomainUrl1); 985 FullResponse(1024); 986 EXPECT_FALSE(loader_->HasSingleOrigin()); 987 StopWhenLoad(); 988 989 // Test redirect to the same domain and then to a different domain. 990 Initialize(kHttpUrl, -1, -1); 991 Start(); 992 Redirect(kHttpRedirectToSameDomainUrl1); 993 Redirect(kHttpRedirectToDifferentDomainUrl1); 994 FullResponse(1024); 995 EXPECT_FALSE(loader_->HasSingleOrigin()); 996 StopWhenLoad(); 997 } 998 999 TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) { 1000 Initialize(kHttpUrl, -1, -1); 1001 Start(); 1002 1003 // Test ensures that default construction of a BufferedResourceLoader has sane 1004 // values. 1005 // 1006 // Please do not change these values in order to make a test pass! Instead, 1007 // start a conversation on what the default buffer window capacities should 1008 // be. 1009 ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024); 1010 ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024); 1011 1012 StopWhenLoad(); 1013 } 1014 1015 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) { 1016 Initialize(kHttpUrl, -1, -1); 1017 Start(); 1018 loader_->SetBitrate(0); 1019 CheckBufferWindowBounds(); 1020 StopWhenLoad(); 1021 } 1022 1023 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_BelowLowerBound) { 1024 Initialize(kHttpUrl, -1, -1); 1025 Start(); 1026 loader_->SetBitrate(1024 * 8); // 1 Kbps. 1027 CheckBufferWindowBounds(); 1028 StopWhenLoad(); 1029 } 1030 1031 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_WithinBounds) { 1032 Initialize(kHttpUrl, -1, -1); 1033 Start(); 1034 loader_->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps. 1035 CheckBufferWindowBounds(); 1036 StopWhenLoad(); 1037 } 1038 1039 TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_AboveUpperBound) { 1040 Initialize(kHttpUrl, -1, -1); 1041 Start(); 1042 loader_->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps. 1043 CheckBufferWindowBounds(); 1044 StopWhenLoad(); 1045 } 1046 1047 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) { 1048 Initialize(kHttpUrl, -1, -1); 1049 Start(); 1050 loader_->SetPlaybackRate(-10); 1051 CheckBufferWindowBounds(); 1052 StopWhenLoad(); 1053 } 1054 1055 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) { 1056 Initialize(kHttpUrl, -1, -1); 1057 Start(); 1058 loader_->SetPlaybackRate(0); 1059 CheckBufferWindowBounds(); 1060 StopWhenLoad(); 1061 } 1062 1063 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) { 1064 Initialize(kHttpUrl, -1, -1); 1065 Start(); 1066 loader_->SetPlaybackRate(0.1f); 1067 CheckBufferWindowBounds(); 1068 StopWhenLoad(); 1069 } 1070 1071 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) { 1072 Initialize(kHttpUrl, -1, -1); 1073 Start(); 1074 loader_->SetPlaybackRate(10); 1075 CheckBufferWindowBounds(); 1076 StopWhenLoad(); 1077 } 1078 1079 TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) { 1080 Initialize(kHttpUrl, -1, -1); 1081 Start(); 1082 loader_->SetPlaybackRate(100); 1083 CheckBufferWindowBounds(); 1084 StopWhenLoad(); 1085 } 1086 1087 static void ExpectContentRange( 1088 const std::string& str, bool expect_success, 1089 int64 expected_first, int64 expected_last, int64 expected_size) { 1090 int64 first, last, size; 1091 ASSERT_EQ(expect_success, BufferedResourceLoader::ParseContentRange( 1092 str, &first, &last, &size)) << str; 1093 if (!expect_success) 1094 return; 1095 EXPECT_EQ(first, expected_first); 1096 EXPECT_EQ(last, expected_last); 1097 EXPECT_EQ(size, expected_size); 1098 } 1099 1100 static void ExpectContentRangeFailure(const std::string& str) { 1101 ExpectContentRange(str, false, 0, 0, 0); 1102 } 1103 1104 static void ExpectContentRangeSuccess( 1105 const std::string& str, 1106 int64 expected_first, int64 expected_last, int64 expected_size) { 1107 ExpectContentRange(str, true, expected_first, expected_last, expected_size); 1108 } 1109 1110 TEST(BufferedResourceLoaderStandaloneTest, ParseContentRange) { 1111 ExpectContentRangeFailure("cytes 0-499/500"); 1112 ExpectContentRangeFailure("bytes 0499/500"); 1113 ExpectContentRangeFailure("bytes 0-499500"); 1114 ExpectContentRangeFailure("bytes 0-499/500-blorg"); 1115 ExpectContentRangeFailure("bytes 0-499/500-1"); 1116 ExpectContentRangeFailure("bytes 0-499/400"); 1117 ExpectContentRangeFailure("bytes 0-/400"); 1118 ExpectContentRangeFailure("bytes -300/400"); 1119 ExpectContentRangeFailure("bytes 20-10/400"); 1120 1121 ExpectContentRangeSuccess("bytes 0-499/500", 0, 499, 500); 1122 ExpectContentRangeSuccess("bytes 0-0/500", 0, 0, 500); 1123 ExpectContentRangeSuccess("bytes 10-11/50", 10, 11, 50); 1124 ExpectContentRangeSuccess("bytes 10-11/*", 10, 11, 1125 kPositionNotSpecified); 1126 } 1127 1128 } // namespace content 1129