component_updater_service_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2012 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 "chrome/browser/component_updater/test/component_updater_service_unittest.h" 6#include "base/file_util.h" 7#include "base/path_service.h" 8#include "base/run_loop.h" 9#include "base/strings/string_number_conversions.h" 10#include "base/strings/string_util.h" 11#include "base/strings/stringprintf.h" 12#include "base/values.h" 13#include "chrome/browser/component_updater/component_updater_utils.h" 14#include "chrome/browser/component_updater/test/test_installer.h" 15#include "chrome/common/chrome_paths.h" 16#include "content/public/browser/browser_thread.h" 17#include "content/public/browser/resource_controller.h" 18#include "content/public/browser/resource_request_info.h" 19#include "content/public/browser/resource_throttle.h" 20#include "libxml/globals.h" 21#include "net/base/upload_bytes_element_reader.h" 22#include "net/url_request/url_fetcher.h" 23#include "net/url_request/url_request_test_util.h" 24#include "url/gurl.h" 25 26using content::BrowserThread; 27 28using ::testing::_; 29using ::testing::InSequence; 30using ::testing::Mock; 31 32namespace component_updater { 33 34#define POST_INTERCEPT_SCHEME "http" 35#define POST_INTERCEPT_HOSTNAME "localhost2" 36#define POST_INTERCEPT_PATH "/update2" 37 38MockComponentObserver::MockComponentObserver() { 39} 40 41MockComponentObserver::~MockComponentObserver() { 42} 43 44bool PartialMatch::Match(const std::string& actual) const { 45 return actual.find(expected_) != std::string::npos; 46} 47 48TestConfigurator::TestConfigurator() 49 : initial_time_(0), 50 times_(1), 51 recheck_time_(0), 52 ondemand_time_(0), 53 cus_(NULL), 54 context_(new net::TestURLRequestContextGetter( 55 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) { 56} 57 58TestConfigurator::~TestConfigurator() { 59} 60 61int TestConfigurator::InitialDelay() { return initial_time_; } 62 63int TestConfigurator::NextCheckDelay() { 64 // This is called when a new full cycle of checking for updates is going 65 // to happen. In test we normally only test one cycle so it is a good 66 // time to break from the test messageloop Run() method so the test can 67 // finish. 68 if (--times_ <= 0) { 69 quit_closure_.Run(); 70 return 0; 71 } 72 return 1; 73} 74 75int TestConfigurator::StepDelay() { 76 return 0; 77} 78 79int TestConfigurator::StepDelayMedium() { 80 return NextCheckDelay(); 81} 82 83int TestConfigurator::MinimumReCheckWait() { 84 return recheck_time_; 85} 86 87int TestConfigurator::OnDemandDelay() { 88 return ondemand_time_; 89} 90 91GURL TestConfigurator::UpdateUrl() { 92 return GURL(POST_INTERCEPT_SCHEME "://" 93 POST_INTERCEPT_HOSTNAME POST_INTERCEPT_PATH); 94} 95 96GURL TestConfigurator::PingUrl() { 97 return UpdateUrl(); 98} 99 100std::string TestConfigurator::ExtraRequestParams() { return "extra=\"foo\""; } 101 102size_t TestConfigurator::UrlSizeLimit() { return 256; } 103 104net::URLRequestContextGetter* TestConfigurator::RequestContext() { 105 return context_.get(); 106} 107 108// Don't use the utility process to run code out-of-process. 109bool TestConfigurator::InProcess() { return true; } 110 111ComponentPatcher* TestConfigurator::CreateComponentPatcher() { 112 return new MockComponentPatcher(); 113} 114 115bool TestConfigurator::DeltasEnabled() const { 116 return true; 117} 118 119bool TestConfigurator::UseBackgroundDownloader() const { 120 return false; 121} 122 123// Set how many update checks are called, the default value is just once. 124void TestConfigurator::SetLoopCount(int times) { times_ = times; } 125 126void TestConfigurator::SetRecheckTime(int seconds) { 127 recheck_time_ = seconds; 128} 129 130void TestConfigurator::SetOnDemandTime(int seconds) { 131 ondemand_time_ = seconds; 132} 133 134void TestConfigurator::SetComponentUpdateService(ComponentUpdateService* cus) { 135 cus_ = cus; 136} 137 138void TestConfigurator::SetQuitClosure(const base::Closure& quit_closure) { 139 quit_closure_ = quit_closure; 140} 141 142void TestConfigurator::SetInitialDelay(int seconds) { 143 initial_time_ = seconds; 144} 145 146InterceptorFactory::InterceptorFactory() 147 : URLRequestPostInterceptorFactory(POST_INTERCEPT_SCHEME, 148 POST_INTERCEPT_HOSTNAME) {} 149 150InterceptorFactory::~InterceptorFactory() {} 151 152URLRequestPostInterceptor* InterceptorFactory::CreateInterceptor() { 153 return URLRequestPostInterceptorFactory::CreateInterceptor( 154 base::FilePath::FromUTF8Unsafe(POST_INTERCEPT_PATH)); 155} 156 157ComponentUpdaterTest::ComponentUpdaterTest() 158 : test_config_(NULL), 159 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { 160 // The component updater instance under test. 161 test_config_ = new TestConfigurator; 162 component_updater_.reset(ComponentUpdateServiceFactory(test_config_)); 163 test_config_->SetComponentUpdateService(component_updater_.get()); 164 165 // The test directory is chrome/test/data/components. 166 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_); 167 test_data_dir_ = test_data_dir_.AppendASCII("components"); 168 169 net::URLFetcher::SetEnableInterceptionForTests(true); 170} 171 172ComponentUpdaterTest::~ComponentUpdaterTest() { 173 net::URLFetcher::SetEnableInterceptionForTests(false); 174} 175 176void ComponentUpdaterTest::SetUp() { 177 get_interceptor_.reset(new GetInterceptor); 178 interceptor_factory_.reset(new InterceptorFactory); 179 post_interceptor_ = interceptor_factory_->CreateInterceptor(); 180 EXPECT_TRUE(post_interceptor_); 181} 182 183void ComponentUpdaterTest::TearDown() { 184 interceptor_factory_.reset(); 185 get_interceptor_.reset(); 186 xmlCleanupGlobals(); 187} 188 189ComponentUpdateService* ComponentUpdaterTest::component_updater() { 190 return component_updater_.get(); 191} 192 193 // Makes the full path to a component updater test file. 194const base::FilePath ComponentUpdaterTest::test_file(const char* file) { 195 return test_data_dir_.AppendASCII(file); 196} 197 198TestConfigurator* ComponentUpdaterTest::test_configurator() { 199 return test_config_; 200} 201 202ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent( 203 CrxComponent* com, 204 TestComponents component, 205 const Version& version, 206 TestInstaller* installer) { 207 if (component == kTestComponent_abag) { 208 com->name = "test_abag"; 209 com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); 210 } else if (component == kTestComponent_jebg) { 211 com->name = "test_jebg"; 212 com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); 213 } else { 214 com->name = "test_ihfo"; 215 com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); 216 } 217 com->version = version; 218 com->installer = installer; 219 return component_updater_->RegisterComponent(*com); 220} 221 222void ComponentUpdaterTest::RunThreads() { 223 base::RunLoop runloop; 224 test_configurator()->SetQuitClosure(runloop.QuitClosure()); 225 runloop.Run(); 226 227 // Since some tests need to drain currently enqueued tasks such as network 228 // intercepts on the IO thread, run the threads until they are 229 // idle. The component updater service won't loop again until the loop count 230 // is set and the service is started. 231 RunThreadsUntilIdle(); 232} 233 234void ComponentUpdaterTest::RunThreadsUntilIdle() { 235 base::RunLoop().RunUntilIdle(); 236} 237 238ComponentUpdateService::Status OnDemandTester::OnDemand( 239 ComponentUpdateService* cus, const std::string& component_id) { 240 return cus->OnDemandUpdate(component_id); 241} 242 243// Verify that our test fixture work and the component updater can 244// be created and destroyed with no side effects. 245TEST_F(ComponentUpdaterTest, VerifyFixture) { 246 EXPECT_TRUE(component_updater() != NULL); 247} 248 249// Verify that the component updater can be caught in a quick 250// start-shutdown situation. Failure of this test will be a crash. 251TEST_F(ComponentUpdaterTest, StartStop) { 252 component_updater()->Start(); 253 RunThreadsUntilIdle(); 254 component_updater()->Stop(); 255} 256 257// Verify that when the server has no updates, we go back to sleep and 258// the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications 259// are generated. No pings are sent. 260TEST_F(ComponentUpdaterTest, CheckCrxSleep) { 261 MockComponentObserver observer; 262 263 EXPECT_CALL(observer, 264 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 265 .Times(1); 266 EXPECT_CALL(observer, 267 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 268 .Times(2); 269 EXPECT_CALL(observer, 270 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 271 .Times(2); 272 273 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 274 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 275 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 276 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 277 278 TestInstaller installer; 279 CrxComponent com; 280 com.observer = &observer; 281 EXPECT_EQ(ComponentUpdateService::kOk, 282 RegisterComponent(&com, 283 kTestComponent_abag, 284 Version("1.1"), 285 &installer)); 286 287 // We loop twice, but there are no updates so we expect two sleep messages. 288 test_configurator()->SetLoopCount(2); 289 component_updater()->Start(); 290 RunThreads(); 291 292 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 293 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 294 295 // Expect to see the two update check requests and no other requests, 296 // including pings. 297 EXPECT_EQ(2, post_interceptor_->GetHitCount()) 298 << post_interceptor_->GetRequestsAsString(); 299 EXPECT_EQ(2, post_interceptor_->GetCount()) 300 << post_interceptor_->GetRequestsAsString(); 301 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 302 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" 303 "<updatecheck /></app>")) 304 << post_interceptor_->GetRequestsAsString(); 305 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 306 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" 307 "<updatecheck /></app>")) 308 << post_interceptor_->GetRequestsAsString(); 309 310 component_updater()->Stop(); 311 312 // Loop twice again but this case we simulate a server error by returning 313 // an empty file. Expect the behavior of the service to be the same as before. 314 EXPECT_CALL(observer, 315 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 316 .Times(1); 317 EXPECT_CALL(observer, 318 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 319 .Times(2); 320 EXPECT_CALL(observer, 321 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 322 .Times(2); 323 324 post_interceptor_->Reset(); 325 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 326 "updatecheck"), test_file("updatecheck_reply_empty"))); 327 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 328 "updatecheck"), test_file("updatecheck_reply_empty"))); 329 330 test_configurator()->SetLoopCount(2); 331 component_updater()->Start(); 332 RunThreads(); 333 334 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 335 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 336 337 EXPECT_EQ(2, post_interceptor_->GetHitCount()) 338 << post_interceptor_->GetRequestsAsString(); 339 EXPECT_EQ(2, post_interceptor_->GetCount()) 340 << post_interceptor_->GetRequestsAsString(); 341 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 342 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" 343 "<updatecheck /></app>")) 344 << post_interceptor_->GetRequestsAsString(); 345 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 346 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" 347 "<updatecheck /></app>")) 348 << post_interceptor_->GetRequestsAsString(); 349 350 component_updater()->Stop(); 351} 352 353// Verify that we can check for updates and install one component. Besides 354// the notifications above COMPONENT_UPDATE_FOUND and COMPONENT_UPDATE_READY 355// should have been fired. We do two loops so the second time around there 356// should be nothing left to do. 357// We also check that the following network requests are issued: 358// 1- update check 359// 2- download crx 360// 3- ping 361// 4- second update check. 362TEST_F(ComponentUpdaterTest, InstallCrx) { 363 MockComponentObserver observer1; 364 { 365 InSequence seq; 366 EXPECT_CALL(observer1, 367 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 368 .Times(1); 369 EXPECT_CALL(observer1, 370 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0)) 371 .Times(1); 372 EXPECT_CALL(observer1, 373 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0)) 374 .Times(1); 375 EXPECT_CALL(observer1, 376 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0)) 377 .Times(1); 378 EXPECT_CALL(observer1, 379 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 380 .Times(1); 381 EXPECT_CALL(observer1, 382 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 383 .Times(1); 384 EXPECT_CALL(observer1, 385 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 386 .Times(1); 387 } 388 389 MockComponentObserver observer2; 390 { 391 InSequence seq; 392 EXPECT_CALL(observer2, 393 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 394 .Times(1); 395 EXPECT_CALL(observer2, 396 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 397 .Times(1); 398 EXPECT_CALL(observer2, 399 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 400 .Times(1); 401 EXPECT_CALL(observer2, 402 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 403 .Times(1); 404 EXPECT_CALL(observer2, 405 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 406 .Times(1); 407 } 408 409 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 410 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 411 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 412 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 413 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 414 415 get_interceptor_->SetResponse( 416 GURL(expected_crx_url), 417 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 418 419 TestInstaller installer1; 420 CrxComponent com1; 421 com1.observer = &observer1; 422 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1); 423 TestInstaller installer2; 424 CrxComponent com2; 425 com2.observer = &observer2; 426 RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2); 427 428 test_configurator()->SetLoopCount(2); 429 component_updater()->Start(); 430 RunThreads(); 431 432 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 433 EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count()); 434 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 435 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 436 437 // Expect three request in total: two update checks and one ping. 438 EXPECT_EQ(3, post_interceptor_->GetHitCount()) 439 << post_interceptor_->GetRequestsAsString(); 440 EXPECT_EQ(3, post_interceptor_->GetCount()) 441 << post_interceptor_->GetRequestsAsString(); 442 443 // Expect one component download. 444 EXPECT_EQ(1, get_interceptor_->GetHitCount()); 445 446 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 447 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 448 "<updatecheck /></app>")) 449 << post_interceptor_->GetRequestsAsString(); 450 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 451 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">" 452 "<updatecheck /></app>")) 453 << post_interceptor_->GetRequestsAsString(); 454 455 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 456 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 457 "version=\"0.9\" nextversion=\"1.0\">" 458 "<event eventtype=\"3\" eventresult=\"1\"/>")) 459 << post_interceptor_->GetRequestsAsString(); 460 461 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 462 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">" 463 "<updatecheck /></app>")); 464 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 465 "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">" 466 "<updatecheck /></app>")) 467 << post_interceptor_->GetRequestsAsString(); 468 469 // Test the protocol version is correct and the extra request attributes 470 // are included in the request. 471 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 472 "request protocol=\"3.0\" extra=\"foo\"")) 473 << post_interceptor_->GetRequestsAsString(); 474 475 // Tokenize the request string to look for specific attributes, which 476 // are important for backward compatibility with the version v2 of the update 477 // protocol. In this case, inspect the <request>, which is the first element 478 // after the xml declaration of the update request body. 479 // Expect to find the |os|, |arch|, |prodchannel|, and |prodversion| 480 // attributes: 481 // <?xml version="1.0" encoding="UTF-8"?> 482 // <request... os=... arch=... prodchannel=... prodversion=...> 483 // ... 484 // </request> 485 const std::string update_request(post_interceptor_->GetRequests()[0]); 486 std::vector<base::StringPiece> elements; 487 Tokenize(update_request, "<>", &elements); 488 EXPECT_NE(string::npos, elements[1].find(" os=")); 489 EXPECT_NE(string::npos, elements[1].find(" arch=")); 490 EXPECT_NE(string::npos, elements[1].find(" prodchannel=")); 491 EXPECT_NE(string::npos, elements[1].find(" prodversion=")); 492 493 // Look for additional attributes of the request, such as |version|, 494 // |requestid|, |lang|, and |nacl_arch|. 495 EXPECT_NE(string::npos, elements[1].find(" version=")); 496 EXPECT_NE(string::npos, elements[1].find(" requestid=")); 497 EXPECT_NE(string::npos, elements[1].find(" lang=")); 498 EXPECT_NE(string::npos, elements[1].find(" nacl_arch=")); 499 500 component_updater()->Stop(); 501} 502 503// This test checks that the "prodversionmin" value is handled correctly. In 504// particular there should not be an install because the minimum product 505// version is much higher than of chrome. 506TEST_F(ComponentUpdaterTest, ProdVersionCheck) { 507 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 508 "updatecheck"), test_file("updatecheck_reply_2.xml"))); 509 510 get_interceptor_->SetResponse( 511 GURL(expected_crx_url), 512 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 513 514 TestInstaller installer; 515 CrxComponent com; 516 RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer); 517 518 test_configurator()->SetLoopCount(1); 519 component_updater()->Start(); 520 RunThreads(); 521 522 // Expect one update check and no ping. 523 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 524 << post_interceptor_->GetRequestsAsString(); 525 EXPECT_EQ(1, post_interceptor_->GetCount()) 526 << post_interceptor_->GetRequestsAsString(); 527 528 // Expect no download to occur. 529 EXPECT_EQ(0, get_interceptor_->GetHitCount()); 530 531 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 532 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 533 534 component_updater()->Stop(); 535} 536 537// Test that a update check due to an on demand call can cause installs. 538// Here is the timeline: 539// - First loop: we return a reply that indicates no update, so 540// nothing happens. 541// - We make an on demand call. 542// - This triggers a second loop, which has a reply that triggers an install. 543TEST_F(ComponentUpdaterTest, OnDemandUpdate) { 544 MockComponentObserver observer1; 545 { 546 InSequence seq; 547 EXPECT_CALL(observer1, 548 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 549 .Times(1); 550 EXPECT_CALL(observer1, 551 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 552 .Times(1); 553 EXPECT_CALL(observer1, 554 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 555 .Times(1); 556 EXPECT_CALL(observer1, 557 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 558 .Times(1); 559 EXPECT_CALL(observer1, 560 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 561 .Times(1); 562 EXPECT_CALL(observer1, 563 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 564 .Times(1); 565 } 566 567 MockComponentObserver observer2; 568 { 569 InSequence seq; 570 EXPECT_CALL(observer2, 571 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 572 .Times(1); 573 EXPECT_CALL(observer2, 574 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 575 .Times(1); 576 EXPECT_CALL(observer2, 577 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 578 .Times(1); 579 EXPECT_CALL(observer2, 580 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 581 .Times(1); 582 EXPECT_CALL(observer2, 583 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0)) 584 .Times(1); 585 EXPECT_CALL(observer2, 586 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0)) 587 .Times(1); 588 EXPECT_CALL(observer2, 589 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0)) 590 .Times(1); 591 EXPECT_CALL(observer2, 592 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 593 .Times(1); 594 } 595 596 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 597 "updatecheck"), test_file("updatecheck_reply_empty"))); 598 599 get_interceptor_->SetResponse( 600 GURL(expected_crx_url), 601 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 602 603 TestInstaller installer1; 604 CrxComponent com1; 605 com1.observer = &observer1; 606 RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1); 607 TestInstaller installer2; 608 CrxComponent com2; 609 com2.observer = &observer2; 610 RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2); 611 612 // No update normally. 613 test_configurator()->SetLoopCount(1); 614 component_updater()->Start(); 615 RunThreads(); 616 component_updater()->Stop(); 617 618 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 619 << post_interceptor_->GetRequestsAsString(); 620 EXPECT_EQ(1, post_interceptor_->GetCount()) 621 << post_interceptor_->GetRequestsAsString(); 622 623 EXPECT_EQ(0, get_interceptor_->GetHitCount()); 624 625 // Update after an on-demand check is issued. 626 post_interceptor_->Reset(); 627 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 628 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 629 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 630 631 EXPECT_EQ(ComponentUpdateService::kOk, 632 OnDemandTester::OnDemand(component_updater(), 633 GetCrxComponentID(com2))); 634 test_configurator()->SetLoopCount(1); 635 component_updater()->Start(); 636 RunThreads(); 637 638 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 639 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count()); 640 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 641 EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count()); 642 643 EXPECT_EQ(2, post_interceptor_->GetHitCount()) 644 << post_interceptor_->GetRequestsAsString(); 645 EXPECT_EQ(2, post_interceptor_->GetCount()) 646 << post_interceptor_->GetRequestsAsString(); 647 648 EXPECT_EQ(1, get_interceptor_->GetHitCount()); 649 650 // Expect the update check to contain an "ondemand" request for the 651 // second component (com2) and a normal request for the other component. 652 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 653 "<app appid=\"abagagagagagagagagagagagagagagag\" " 654 "version=\"2.2\"><updatecheck /></app>")) 655 << post_interceptor_->GetRequestsAsString(); 656 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 657 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 658 "version=\"0.9\" installsource=\"ondemand\"><updatecheck /></app>")) 659 << post_interceptor_->GetRequestsAsString(); 660 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 661 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 662 "version=\"0.9\" nextversion=\"1.0\">" 663 "<event eventtype=\"3\" eventresult=\"1\"/>")) 664 << post_interceptor_->GetRequestsAsString(); 665 666 // Also check what happens if previous check too soon. 667 test_configurator()->SetOnDemandTime(60 * 60); 668 EXPECT_EQ(ComponentUpdateService::kError, 669 OnDemandTester::OnDemand(component_updater(), 670 GetCrxComponentID(com2))); 671 // Okay, now reset to 0 for the other tests. 672 test_configurator()->SetOnDemandTime(0); 673 component_updater()->Stop(); 674 675 // Test a few error cases. NOTE: We don't have callbacks for 676 // when the updates failed yet. 677 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); 678 { 679 InSequence seq; 680 EXPECT_CALL(observer1, 681 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 682 .Times(1); 683 EXPECT_CALL(observer1, 684 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 685 .Times(1); 686 EXPECT_CALL(observer1, 687 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 688 .Times(1); 689 } 690 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); 691 { 692 InSequence seq; 693 EXPECT_CALL(observer2, 694 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 695 .Times(1); 696 EXPECT_CALL(observer2, 697 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 698 .Times(1); 699 EXPECT_CALL(observer2, 700 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 701 .Times(1); 702 } 703 704 // No update: error from no server response 705 post_interceptor_->Reset(); 706 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 707 "updatecheck"), test_file("updatecheck_reply_empty"))); 708 709 test_configurator()->SetLoopCount(1); 710 component_updater()->Start(); 711 EXPECT_EQ(ComponentUpdateService::kOk, 712 OnDemandTester::OnDemand(component_updater(), 713 GetCrxComponentID(com2))); 714 RunThreads(); 715 component_updater()->Stop(); 716 717 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 718 << post_interceptor_->GetRequestsAsString(); 719 EXPECT_EQ(1, post_interceptor_->GetCount()) 720 << post_interceptor_->GetRequestsAsString(); 721 722 // No update: already updated to 1.0 so nothing new 723 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); 724 { 725 InSequence seq; 726 EXPECT_CALL(observer1, 727 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 728 .Times(1); 729 EXPECT_CALL(observer1, 730 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 731 .Times(1); 732 EXPECT_CALL(observer1, 733 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 734 .Times(1); 735 } 736 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); 737 { 738 InSequence seq; 739 EXPECT_CALL(observer2, 740 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 741 .Times(1); 742 EXPECT_CALL(observer2, 743 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 744 .Times(1); 745 EXPECT_CALL(observer2, 746 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 747 .Times(1); 748 } 749 750 post_interceptor_->Reset(); 751 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 752 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 753 754 test_configurator()->SetLoopCount(1); 755 component_updater()->Start(); 756 EXPECT_EQ(ComponentUpdateService::kOk, 757 OnDemandTester::OnDemand(component_updater(), 758 GetCrxComponentID(com2))); 759 RunThreads(); 760 761 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 762 << post_interceptor_->GetRequestsAsString(); 763 EXPECT_EQ(1, post_interceptor_->GetCount()) 764 << post_interceptor_->GetRequestsAsString(); 765 766 component_updater()->Stop(); 767} 768 769// Verify that a previously registered component can get re-registered 770// with a different version. 771TEST_F(ComponentUpdaterTest, CheckReRegistration) { 772 MockComponentObserver observer1; 773 { 774 InSequence seq; 775 EXPECT_CALL(observer1, 776 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 777 .Times(1); 778 EXPECT_CALL(observer1, 779 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0)) 780 .Times(1); 781 EXPECT_CALL(observer1, 782 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0)) 783 .Times(1); 784 EXPECT_CALL(observer1, 785 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0)) 786 .Times(1); 787 EXPECT_CALL(observer1, 788 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 789 .Times(1); 790 EXPECT_CALL(observer1, 791 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 792 .Times(1); 793 EXPECT_CALL(observer1, 794 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 795 .Times(1); 796 } 797 798 MockComponentObserver observer2; 799 { 800 InSequence seq; 801 EXPECT_CALL(observer2, 802 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 803 .Times(1); 804 EXPECT_CALL(observer2, 805 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 806 .Times(1); 807 EXPECT_CALL(observer2, 808 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 809 .Times(1); 810 EXPECT_CALL(observer2, 811 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 812 .Times(1); 813 EXPECT_CALL(observer2, 814 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 815 .Times(1); 816 } 817 818 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 819 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 820 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 821 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 822 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 823 824 get_interceptor_->SetResponse( 825 GURL(expected_crx_url), 826 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 827 828 TestInstaller installer1; 829 CrxComponent com1; 830 com1.observer = &observer1; 831 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1); 832 TestInstaller installer2; 833 CrxComponent com2; 834 com2.observer = &observer2; 835 RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2); 836 837 // Loop twice to issue two checks: (1) with original 0.9 version, update to 838 // 1.0, and do the second check (2) with the updated 1.0 version. 839 test_configurator()->SetLoopCount(2); 840 component_updater()->Start(); 841 RunThreads(); 842 843 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 844 EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count()); 845 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 846 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 847 848 EXPECT_EQ(3, post_interceptor_->GetHitCount()) 849 << post_interceptor_->GetRequestsAsString(); 850 EXPECT_EQ(1, get_interceptor_->GetHitCount()); 851 852 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 853 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 854 "<updatecheck /></app>")) 855 << post_interceptor_->GetRequestsAsString(); 856 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 857 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 858 "version=\"0.9\" nextversion=\"1.0\">" 859 "<event eventtype=\"3\" eventresult=\"1\"/>")) 860 << post_interceptor_->GetRequestsAsString(); 861 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 862 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">" 863 "<updatecheck /></app>")) 864 << post_interceptor_->GetRequestsAsString(); 865 866 component_updater()->Stop(); 867 868 // Now re-register, pretending to be an even newer version (2.2) 869 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); 870 { 871 InSequence seq; 872 EXPECT_CALL(observer1, 873 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 874 .Times(1); 875 EXPECT_CALL(observer1, 876 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 877 .Times(1); 878 EXPECT_CALL(observer1, 879 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 880 .Times(1); 881 } 882 883 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); 884 { 885 InSequence seq; 886 EXPECT_CALL(observer2, 887 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 888 .Times(1); 889 EXPECT_CALL(observer2, 890 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 891 .Times(1); 892 EXPECT_CALL(observer2, 893 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 894 .Times(1); 895 } 896 897 post_interceptor_->Reset(); 898 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 899 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 900 901 TestInstaller installer3; 902 EXPECT_EQ(ComponentUpdateService::kReplaced, 903 RegisterComponent(&com1, 904 kTestComponent_jebg, 905 Version("2.2"), 906 &installer3)); 907 908 // Loop once just to notice the check happening with the re-register version. 909 test_configurator()->SetLoopCount(1); 910 component_updater()->Start(); 911 RunThreads(); 912 913 // We created a new installer, so the counts go back to 0. 914 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 915 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count()); 916 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 917 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 918 919 // One update check and no additional pings are expected. 920 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 921 << post_interceptor_->GetRequestsAsString(); 922 EXPECT_EQ(1, post_interceptor_->GetCount()) 923 << post_interceptor_->GetRequestsAsString(); 924 925 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 926 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"2.2\">" 927 "<updatecheck /></app>")); 928 929 component_updater()->Stop(); 930} 931 932// Verify that we can download and install a component and a differential 933// update to that component. We do three loops; the final loop should do 934// nothing. 935// We also check that exactly 5 non-ping network requests are issued: 936// 1- update check (response: v1 available) 937// 2- download crx (v1) 938// 3- update check (response: v2 available) 939// 4- download differential crx (v1 to v2) 940// 5- update check (response: no further update available) 941// There should be two pings, one for each update. The second will bear a 942// diffresult=1, while the first will not. 943TEST_F(ComponentUpdaterTest, DifferentialUpdate) { 944 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 945 "updatecheck"), test_file("updatecheck_diff_reply_1.xml"))); 946 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 947 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 948 "updatecheck"), test_file("updatecheck_diff_reply_2.xml"))); 949 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 950 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 951 "updatecheck"), test_file("updatecheck_diff_reply_3.xml"))); 952 953 get_interceptor_->SetResponse( 954 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), 955 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); 956 get_interceptor_->SetResponse( 957 GURL("http://localhost/download/" 958 "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), 959 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx")); 960 961 VersionedTestInstaller installer; 962 CrxComponent com; 963 RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer); 964 965 test_configurator()->SetLoopCount(3); 966 component_updater()->Start(); 967 RunThreads(); 968 969 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 970 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count()); 971 972 EXPECT_EQ(5, post_interceptor_->GetHitCount()) 973 << post_interceptor_->GetRequestsAsString(); 974 EXPECT_EQ(5, post_interceptor_->GetCount()) 975 << post_interceptor_->GetRequestsAsString(); 976 EXPECT_EQ(2, get_interceptor_->GetHitCount()); 977 978 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 979 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">" 980 "<updatecheck /></app>")) 981 << post_interceptor_->GetRequestsAsString(); 982 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 983 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 984 "version=\"0.0\" nextversion=\"1.0\">" 985 "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>")) 986 << post_interceptor_->GetRequestsAsString(); 987 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 988 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" 989 "<updatecheck /><packages><package fp=\"1\"/></packages></app>")) 990 << post_interceptor_->GetRequestsAsString(); 991 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find( 992 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 993 "version=\"1.0\" nextversion=\"2.0\">" 994 "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"1\" " 995 "previousfp=\"1\" nextfp=\"22\"/>")) 996 << post_interceptor_->GetRequestsAsString(); 997 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find( 998 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" 999 "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) 1000 << post_interceptor_->GetRequestsAsString(); 1001 component_updater()->Stop(); 1002} 1003 1004// Verify that component installation falls back to downloading and installing 1005// a full update if the differential update fails (in this case, because the 1006// installer does not know about the existing files). We do two loops; the final 1007// loop should do nothing. 1008// We also check that exactly 4 non-ping network requests are issued: 1009// 1- update check (loop 1) 1010// 2- download differential crx 1011// 3- download full crx 1012// 4- update check (loop 2 - no update available) 1013// There should be one ping for the first attempted update. 1014TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) { 1015 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1016 "updatecheck"), test_file("updatecheck_diff_reply_2.xml"))); 1017 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1018 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1019 "updatecheck"), test_file("updatecheck_diff_reply_3.xml"))); 1020 1021 get_interceptor_->SetResponse( 1022 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), 1023 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); 1024 get_interceptor_->SetResponse( 1025 GURL("http://localhost/download/" 1026 "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), 1027 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx")); 1028 get_interceptor_->SetResponse( 1029 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), 1030 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx")); 1031 1032 TestInstaller installer; 1033 CrxComponent com; 1034 RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer); 1035 1036 test_configurator()->SetLoopCount(2); 1037 component_updater()->Start(); 1038 RunThreads(); 1039 1040 // A failed differential update does not count as a failed install. 1041 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1042 EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count()); 1043 1044 EXPECT_EQ(3, post_interceptor_->GetHitCount()) 1045 << post_interceptor_->GetRequestsAsString(); 1046 EXPECT_EQ(3, post_interceptor_->GetCount()) 1047 << post_interceptor_->GetRequestsAsString(); 1048 EXPECT_EQ(2, get_interceptor_->GetHitCount()); 1049 1050 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 1051 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" 1052 "<updatecheck /></app>")) 1053 << post_interceptor_->GetRequestsAsString(); 1054 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 1055 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 1056 "version=\"1.0\" nextversion=\"2.0\">" 1057 "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"0\" " 1058 "differrorcat=\"2\" differrorcode=\"16\" nextfp=\"22\"/>")) 1059 << post_interceptor_->GetRequestsAsString(); 1060 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 1061 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" 1062 "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) 1063 << post_interceptor_->GetRequestsAsString(); 1064 1065 component_updater()->Stop(); 1066} 1067 1068// Test is flakey on Android bots. See crbug.com/331420. 1069#if defined(OS_ANDROID) 1070#define MAYBE_CheckFailedInstallPing DISABLED_CheckFailedInstallPing 1071#else 1072#define MAYBE_CheckFailedInstallPing CheckFailedInstallPing 1073#endif 1074// Verify that a failed installation causes an install failure ping. 1075 TEST_F(ComponentUpdaterTest, MAYBE_CheckFailedInstallPing) { 1076 // This test installer reports installation failure. 1077 class : public TestInstaller { 1078 virtual bool Install(const base::DictionaryValue& manifest, 1079 const base::FilePath& unpack_path) OVERRIDE { 1080 ++install_count_; 1081 base::DeleteFile(unpack_path, true); 1082 return false; 1083 } 1084 } installer; 1085 1086 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1087 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 1088 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1089 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1090 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 1091 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1092 get_interceptor_->SetResponse( 1093 GURL(expected_crx_url), 1094 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 1095 1096 // Start with 0.9, and attempt update to 1.0. 1097 // Loop twice to issue two checks: (1) with original 0.9 version 1098 // and (2), which should retry with 0.9. 1099 CrxComponent com; 1100 RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer); 1101 1102 test_configurator()->SetLoopCount(2); 1103 component_updater()->Start(); 1104 RunThreads(); 1105 1106 EXPECT_EQ(4, post_interceptor_->GetHitCount()) 1107 << post_interceptor_->GetRequestsAsString(); 1108 EXPECT_EQ(2, get_interceptor_->GetHitCount()); 1109 1110 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 1111 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 1112 "<updatecheck /></app>")) 1113 << post_interceptor_->GetRequestsAsString(); 1114 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 1115 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 1116 "version=\"0.9\" nextversion=\"1.0\">" 1117 "<event eventtype=\"3\" eventresult=\"0\" " 1118 "errorcat=\"3\" errorcode=\"9\"/>")) 1119 << post_interceptor_->GetRequestsAsString(); 1120 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 1121 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 1122 "<updatecheck /></app>")) 1123 << post_interceptor_->GetRequestsAsString(); 1124 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find( 1125 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " 1126 "version=\"0.9\" nextversion=\"1.0\">" 1127 "<event eventtype=\"3\" eventresult=\"0\" " 1128 "errorcat=\"3\" errorcode=\"9\"/>")) 1129 << post_interceptor_->GetRequestsAsString(); 1130 1131 // Loop once more, but expect no ping because a noupdate response is issued. 1132 // This is necessary to clear out the fire-and-forget ping from the previous 1133 // iteration. 1134 post_interceptor_->Reset(); 1135 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1136 "updatecheck"), test_file("updatecheck_reply_noupdate.xml"))); 1137 1138 test_configurator()->SetLoopCount(1); 1139 component_updater()->Start(); 1140 RunThreads(); 1141 1142 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1143 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count()); 1144 1145 EXPECT_EQ(1, post_interceptor_->GetHitCount()) 1146 << post_interceptor_->GetRequestsAsString(); 1147 EXPECT_EQ(1, post_interceptor_->GetCount()) 1148 << post_interceptor_->GetRequestsAsString(); 1149 1150 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 1151 "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" 1152 "<updatecheck /></app>")) 1153 << post_interceptor_->GetRequestsAsString(); 1154 1155 component_updater()->Stop(); 1156} 1157 1158// Verify that we successfully propagate a patcher error. 1159// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect 1160// patching instruction that should fail. 1161TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) { 1162 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1163 "updatecheck"), test_file("updatecheck_diff_reply_1.xml"))); 1164 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1165 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1166 "updatecheck"), test_file("updatecheck_diff_reply_2.xml"))); 1167 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); 1168 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1169 "updatecheck"), test_file("updatecheck_diff_reply_3.xml"))); 1170 1171 get_interceptor_->SetResponse( 1172 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), 1173 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); 1174 // This intercept returns a different file than what is specified in the 1175 // update check response and requested in the download. The file that is 1176 // actually dowloaded contains a patching error, an therefore, an error 1177 // is injected at the time of patching. 1178 get_interceptor_->SetResponse( 1179 GURL("http://localhost/download/" 1180 "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), 1181 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx")); 1182 get_interceptor_->SetResponse( 1183 GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), 1184 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx")); 1185 1186 VersionedTestInstaller installer; 1187 CrxComponent com; 1188 RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer); 1189 1190 test_configurator()->SetLoopCount(3); 1191 component_updater()->Start(); 1192 RunThreads(); 1193 component_updater()->Stop(); 1194 1195 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1196 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count()); 1197 1198 EXPECT_EQ(5, post_interceptor_->GetHitCount()) 1199 << post_interceptor_->GetRequestsAsString(); 1200 EXPECT_EQ(5, post_interceptor_->GetCount()) 1201 << post_interceptor_->GetRequestsAsString(); 1202 EXPECT_EQ(3, get_interceptor_->GetHitCount()); 1203 1204 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( 1205 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">" 1206 "<updatecheck /></app>")) 1207 << post_interceptor_->GetRequestsAsString(); 1208 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( 1209 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 1210 "version=\"0.0\" nextversion=\"1.0\">" 1211 "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>")) 1212 << post_interceptor_->GetRequestsAsString(); 1213 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find( 1214 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" 1215 "<updatecheck /><packages><package fp=\"1\"/></packages></app>")) 1216 << post_interceptor_->GetRequestsAsString(); 1217 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find( 1218 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " 1219 "version=\"1.0\" nextversion=\"2.0\">" 1220 "<event eventtype=\"3\" eventresult=\"1\" " 1221 "diffresult=\"0\" differrorcat=\"2\" " 1222 "differrorcode=\"14\" diffextracode1=\"305\" " 1223 "previousfp=\"1\" nextfp=\"22\"/>")) 1224 << post_interceptor_->GetRequestsAsString(); 1225 EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find( 1226 "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" 1227 "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) 1228 << post_interceptor_->GetRequestsAsString(); 1229} 1230 1231class TestResourceController : public content::ResourceController { 1232 public: 1233 virtual void SetThrottle(content::ResourceThrottle* throttle) {} 1234}; 1235 1236content::ResourceThrottle* RequestTestResourceThrottle( 1237 ComponentUpdateService* cus, 1238 TestResourceController* controller, 1239 const char* crx_id) { 1240 1241 net::TestURLRequestContext context; 1242 net::TestURLRequest url_request( 1243 GURL("http://foo.example.com/thing.bin"), 1244 net::DEFAULT_PRIORITY, 1245 NULL, 1246 &context); 1247 1248 content::ResourceThrottle* rt = 1249 cus->GetOnDemandResourceThrottle(&url_request, crx_id); 1250 rt->set_controller_for_testing(controller); 1251 controller->SetThrottle(rt); 1252 return rt; 1253} 1254 1255void RequestAndDeleteResourceThrottle( 1256 ComponentUpdateService* cus, const char* crx_id) { 1257 // By requesting a throttle and deleting it immediately we ensure that we 1258 // hit the case where the component updater tries to use the weak 1259 // pointer to a dead Resource throttle. 1260 class NoCallResourceController : public TestResourceController { 1261 public: 1262 virtual ~NoCallResourceController() {} 1263 virtual void Cancel() OVERRIDE { CHECK(false); } 1264 virtual void CancelAndIgnore() OVERRIDE { CHECK(false); } 1265 virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); } 1266 virtual void Resume() OVERRIDE { CHECK(false); } 1267 } controller; 1268 1269 delete RequestTestResourceThrottle(cus, &controller, crx_id); 1270} 1271 1272TEST_F(ComponentUpdaterTest, ResourceThrottleDeletedNoUpdate) { 1273 MockComponentObserver observer; 1274 EXPECT_CALL(observer, 1275 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 1276 .Times(1); 1277 EXPECT_CALL(observer, 1278 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 1279 .Times(1); 1280 EXPECT_CALL(observer, 1281 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 1282 .Times(1); 1283 1284 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1285 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 1286 1287 TestInstaller installer; 1288 CrxComponent com; 1289 com.observer = &observer; 1290 EXPECT_EQ(ComponentUpdateService::kOk, 1291 RegisterComponent(&com, 1292 kTestComponent_abag, 1293 Version("1.1"), 1294 &installer)); 1295 // The following two calls ensure that we don't do an update check via the 1296 // timer, so the only update check should be the on-demand one. 1297 test_configurator()->SetInitialDelay(1000000); 1298 test_configurator()->SetRecheckTime(1000000); 1299 test_configurator()->SetLoopCount(1); 1300 component_updater()->Start(); 1301 1302 RunThreadsUntilIdle(); 1303 1304 EXPECT_EQ(0, post_interceptor_->GetHitCount()); 1305 1306 BrowserThread::PostTask( 1307 BrowserThread::IO, 1308 FROM_HERE, 1309 base::Bind(&RequestAndDeleteResourceThrottle, 1310 component_updater(), 1311 "abagagagagagagagagagagagagagagag")); 1312 1313 RunThreads(); 1314 1315 EXPECT_EQ(1, post_interceptor_->GetHitCount()); 1316 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1317 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 1318 1319 component_updater()->Stop(); 1320} 1321 1322class CancelResourceController: public TestResourceController { 1323 public: 1324 CancelResourceController() : throttle_(NULL), resume_called_(0) {} 1325 virtual ~CancelResourceController() { 1326 // Check that the throttle has been resumed by the time we 1327 // exit the test. 1328 CHECK(resume_called_ == 1); 1329 delete throttle_; 1330 } 1331 virtual void Cancel() OVERRIDE { CHECK(false); } 1332 virtual void CancelAndIgnore() OVERRIDE { CHECK(false); } 1333 virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); } 1334 virtual void Resume() OVERRIDE { 1335 BrowserThread::PostTask( 1336 BrowserThread::IO, 1337 FROM_HERE, 1338 base::Bind(&CancelResourceController::ResumeCalled, 1339 base::Unretained(this))); 1340 } 1341 virtual void SetThrottle(content::ResourceThrottle* throttle) OVERRIDE { 1342 throttle_ = throttle; 1343 bool defer = false; 1344 // Initially the throttle is blocked. The CUS needs to run a 1345 // task on the UI thread to decide if it should unblock. 1346 throttle_->WillStartRequest(&defer); 1347 CHECK(defer); 1348 } 1349 1350 private: 1351 void ResumeCalled() { ++resume_called_; } 1352 1353 content::ResourceThrottle* throttle_; 1354 int resume_called_; 1355}; 1356 1357TEST_F(ComponentUpdaterTest, ResourceThrottleLiveNoUpdate) { 1358 MockComponentObserver observer; 1359 EXPECT_CALL(observer, 1360 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0)) 1361 .Times(1); 1362 EXPECT_CALL(observer, 1363 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0)) 1364 .Times(1); 1365 EXPECT_CALL(observer, 1366 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0)) 1367 .Times(1); 1368 1369 EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch( 1370 "updatecheck"), test_file("updatecheck_reply_1.xml"))); 1371 1372 TestInstaller installer; 1373 CrxComponent com; 1374 com.observer = &observer; 1375 EXPECT_EQ(ComponentUpdateService::kOk, 1376 RegisterComponent(&com, 1377 kTestComponent_abag, 1378 Version("1.1"), 1379 &installer)); 1380 // The following two calls ensure that we don't do an update check via the 1381 // timer, so the only update check should be the on-demand one. 1382 test_configurator()->SetInitialDelay(1000000); 1383 test_configurator()->SetRecheckTime(1000000); 1384 test_configurator()->SetLoopCount(1); 1385 component_updater()->Start(); 1386 1387 RunThreadsUntilIdle(); 1388 1389 EXPECT_EQ(0, post_interceptor_->GetHitCount()); 1390 1391 CancelResourceController controller; 1392 1393 BrowserThread::PostTask( 1394 BrowserThread::IO, 1395 FROM_HERE, 1396 base::Bind(base::IgnoreResult(&RequestTestResourceThrottle), 1397 component_updater(), 1398 &controller, 1399 "abagagagagagagagagagagagagagagag")); 1400 1401 RunThreads(); 1402 1403 EXPECT_EQ(1, post_interceptor_->GetHitCount()); 1404 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 1405 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 1406 1407 component_updater()->Stop(); 1408} 1409 1410 1411} // namespace component_updater 1412 1413