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 "media/base/media_log.h" 14 #include "media/base/seekable_buffer.h" 15 #include "net/base/net_errors.h" 16 #include "net/http/http_request_headers.h" 17 #include "net/http/http_util.h" 18 #include "third_party/WebKit/public/platform/WebString.h" 19 #include "third_party/WebKit/public/platform/WebURLError.h" 20 #include "third_party/WebKit/public/platform/WebURLRequest.h" 21 #include "third_party/WebKit/public/platform/WebURLResponse.h" 22 #include "third_party/WebKit/public/web/WebFrame.h" 23 #include "third_party/WebKit/public/web/WebView.h" 24 #include "webkit/mocks/mock_webframeclient.h" 25 #include "webkit/mocks/mock_weburlloader.h" 26 27 using ::testing::_; 28 using ::testing::InSequence; 29 using ::testing::Return; 30 using ::testing::Truly; 31 using ::testing::NiceMock; 32 33 using WebKit::WebString; 34 using WebKit::WebURLError; 35 using WebKit::WebURLResponse; 36 using WebKit::WebView; 37 38 using webkit_glue::MockWebFrameClient; 39 using webkit_glue::MockWebURLLoader; 40 41 namespace content { 42 43 static const char* kHttpUrl = "http://test"; 44 static const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing"; 45 static const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2"; 46 static const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2"; 47 48 static const int kDataSize = 1024; 49 static const int kHttpOK = 200; 50 static const int kHttpPartialContent = 206; 51 52 enum NetworkState { 53 NONE, 54 LOADED, 55 LOADING 56 }; 57 58 // Predicate that tests that request disallows compressed data. 59 static bool CorrectAcceptEncoding(const WebKit::WebURLRequest &request) { 60 std::string value = request.httpHeaderField( 61 WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding)).utf8(); 62 return (value.find("identity;q=1") != std::string::npos) && 63 (value.find("*;q=0") != std::string::npos); 64 } 65 66 class BufferedResourceLoaderTest : public testing::Test { 67 public: 68 BufferedResourceLoaderTest() 69 : view_(WebView::create(NULL)) { 70 view_->initializeMainFrame(&client_); 71 72 for (int i = 0; i < kDataSize; ++i) { 73 data_[i] = i; 74 } 75 } 76 77 virtual ~BufferedResourceLoaderTest() { 78 view_->close(); 79 } 80 81 void Initialize(const char* url, int first_position, int last_position) { 82 gurl_ = GURL(url); 83 first_position_ = first_position; 84 last_position_ = last_position; 85 86 loader_.reset(new BufferedResourceLoader( 87 gurl_, BufferedResourceLoader::kUnspecified, 88 first_position_, last_position_, 89 BufferedResourceLoader::kCapacityDefer, 0, 0, 90 new media::MediaLog())); 91 92 // |test_loader_| will be used when Start() is called. 93 url_loader_ = new NiceMock<MockWebURLLoader>(); 94 loader_->test_loader_ = scoped_ptr<WebKit::WebURLLoader>(url_loader_); 95 } 96 97 void SetLoaderBuffer(int forward_capacity, int backward_capacity) { 98 loader_->buffer_.set_forward_capacity(forward_capacity); 99 loader_->buffer_.set_backward_capacity(backward_capacity); 100 loader_->buffer_.Clear(); 101 } 102 103 void Start() { 104 InSequence s; 105 EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding), 106 loader_.get())); 107 108 EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); 109 loader_->Start( 110 base::Bind(&BufferedResourceLoaderTest::StartCallback, 111 base::Unretained(this)), 112 base::Bind(&BufferedResourceLoaderTest::LoadingCallback, 113 base::Unretained(this)), 114 base::Bind(&BufferedResourceLoaderTest::ProgressCallback, 115 base::Unretained(this)), 116 view_->mainFrame()); 117 } 118 119 void FullResponse(int64 instance_size) { 120 FullResponse(instance_size, BufferedResourceLoader::kOk); 121 } 122 123 void FullResponse(int64 instance_size, 124 BufferedResourceLoader::Status status) { 125 EXPECT_CALL(*this, StartCallback(status)); 126 127 WebURLResponse response(gurl_); 128 response.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), 129 WebString::fromUTF8(base::StringPrintf("%" 130 PRId64, instance_size))); 131 response.setExpectedContentLength(instance_size); 132 response.setHTTPStatusCode(kHttpOK); 133 loader_->didReceiveResponse(url_loader_, response); 134 135 if (status == BufferedResourceLoader::kOk) { 136 EXPECT_EQ(instance_size, loader_->content_length()); 137 EXPECT_EQ(instance_size, loader_->instance_size()); 138 } 139 140 EXPECT_FALSE(loader_->range_supported()); 141 } 142 143 void PartialResponse(int64 first_position, int64 last_position, 144 int64 instance_size) { 145 PartialResponse(first_position, last_position, instance_size, false, true); 146 } 147 148 void PartialResponse(int64 first_position, int64 last_position, 149 int64 instance_size, bool chunked, bool accept_ranges) { 150 EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kOk)); 151 152 WebURLResponse response(gurl_); 153 response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"), 154 WebString::fromUTF8(base::StringPrintf("bytes " 155 "%" PRId64 "-%" PRId64 "/%" PRId64, 156 first_position, 157 last_position, 158 instance_size))); 159 160 // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked. 161 int64 content_length = -1; 162 if (chunked) { 163 response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"), 164 WebString::fromUTF8("chunked")); 165 } else { 166 content_length = last_position - first_position + 1; 167 } 168 response.setExpectedContentLength(content_length); 169 170 // A server isn't required to return Accept-Ranges even though it might. 171 if (accept_ranges) { 172 response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"), 173 WebString::fromUTF8("bytes")); 174 } 175 176 response.setHTTPStatusCode(kHttpPartialContent); 177 loader_->didReceiveResponse(url_loader_, response); 178 179 // XXX: what's the difference between these two? For example in the chunked 180 // range request case, Content-Length is unspecified (because it's chunked) 181 // but Content-Range: a-b/c can be returned, where c == Content-Length 182 // 183 // Can we eliminate one? 184 EXPECT_EQ(content_length, loader_->content_length()); 185 EXPECT_EQ(instance_size, loader_->instance_size()); 186 187 // A valid partial response should always result in this being true. 188 EXPECT_TRUE(loader_->range_supported()); 189 } 190 191 void Redirect(const char* url) { 192 GURL redirectUrl(url); 193 WebKit::WebURLRequest newRequest(redirectUrl); 194 WebKit::WebURLResponse redirectResponse(gurl_); 195 196 loader_->willSendRequest(url_loader_, newRequest, redirectResponse); 197 198 base::MessageLoop::current()->RunUntilIdle(); 199 } 200 201 void StopWhenLoad() { 202 InSequence s; 203 EXPECT_CALL(*url_loader_, cancel()); 204 loader_->Stop(); 205 loader_.reset(); 206 } 207 208 // Helper method to write to |loader_| from |data_|. 209 void WriteLoader(int position, int size) { 210 EXPECT_CALL(*this, ProgressCallback(position + size - 1)); 211 loader_->didReceiveData(url_loader_, 212 reinterpret_cast<char*>(data_ + position), 213 size, 214 size); 215 } 216 217 void WriteData(int size) { 218 EXPECT_CALL(*this, ProgressCallback(_)); 219 220 scoped_ptr<char[]> data(new char[size]); 221 loader_->didReceiveData(url_loader_, data.get(), size, size); 222 } 223 224 void WriteUntilThreshold() { 225 int buffered = loader_->buffer_.forward_bytes(); 226 int capacity = loader_->buffer_.forward_capacity(); 227 CHECK_LT(buffered, capacity); 228 229 EXPECT_CALL(*this, LoadingCallback( 230 BufferedResourceLoader::kLoadingDeferred)); 231 WriteData(capacity - buffered); 232 } 233 234 // Helper method to read from |loader_|. 235 void ReadLoader(int64 position, int size, uint8* buffer) { 236 loader_->Read(position, size, buffer, 237 base::Bind(&BufferedResourceLoaderTest::ReadCallback, 238 base::Unretained(this))); 239 } 240 241 // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size]. 242 void VerifyBuffer(uint8* buffer, int pos, int size) { 243 EXPECT_EQ(0, memcmp(buffer, data_ + pos, size)); 244 } 245 246 void ConfirmLoaderOffsets(int64 expected_offset, 247 int expected_first_offset, 248 int expected_last_offset) { 249 EXPECT_EQ(loader_->offset_, expected_offset); 250 EXPECT_EQ(loader_->first_offset_, expected_first_offset); 251 EXPECT_EQ(loader_->last_offset_, expected_last_offset); 252 } 253 254 void ConfirmBufferState(int backward_bytes, 255 int backward_capacity, 256 int forward_bytes, 257 int forward_capacity) { 258 EXPECT_EQ(backward_bytes, loader_->buffer_.backward_bytes()); 259 EXPECT_EQ(backward_capacity, loader_->buffer_.backward_capacity()); 260 EXPECT_EQ(forward_bytes, loader_->buffer_.forward_bytes()); 261 EXPECT_EQ(forward_capacity, loader_->buffer_.forward_capacity()); 262 } 263 264 void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity) { 265 EXPECT_EQ(loader_->buffer_.backward_capacity(), 266 expected_backward_capacity); 267 } 268 269 void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity) { 270 EXPECT_EQ(loader_->buffer_.forward_capacity(), expected_forward_capacity); 271 } 272 273 // Makes sure the |loader_| buffer window is in a reasonable range. 274 void CheckBufferWindowBounds() { 275 // Corresponds to value defined in buffered_resource_loader.cc. 276 static const int kMinBufferCapacity = 2 * 1024 * 1024; 277 EXPECT_GE(loader_->buffer_.forward_capacity(), kMinBufferCapacity); 278 EXPECT_GE(loader_->buffer_.backward_capacity(), kMinBufferCapacity); 279 280 // Corresponds to value defined in buffered_resource_loader.cc. 281 static const int kMaxBufferCapacity = 20 * 1024 * 1024; 282 EXPECT_LE(loader_->buffer_.forward_capacity(), kMaxBufferCapacity); 283 EXPECT_LE(loader_->buffer_.backward_capacity(), kMaxBufferCapacity); 284 } 285 286 MOCK_METHOD1(StartCallback, void(BufferedResourceLoader::Status)); 287 MOCK_METHOD2(ReadCallback, void(BufferedResourceLoader::Status, int)); 288 MOCK_METHOD1(LoadingCallback, void(BufferedResourceLoader::LoadingState)); 289 MOCK_METHOD1(ProgressCallback, void(int64)); 290 291 protected: 292 GURL gurl_; 293 int64 first_position_; 294 int64 last_position_; 295 296 scoped_ptr<BufferedResourceLoader> loader_; 297 NiceMock<MockWebURLLoader>* url_loader_; 298 299 MockWebFrameClient client_; 300 WebView* view_; 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); 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); 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 content 1132