component_updater_service_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 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/component_updater_service.h" 6 7#include <list> 8#include <utility> 9 10#include "base/compiler_specific.h" 11#include "base/file_util.h" 12#include "base/files/file_path.h" 13#include "base/memory/scoped_vector.h" 14#include "base/message_loop.h" 15#include "base/path_service.h" 16#include "base/values.h" 17#include "chrome/common/chrome_notification_types.h" 18#include "chrome/common/chrome_paths.h" 19#include "content/public/browser/notification_observer.h" 20#include "content/public/browser/notification_service.h" 21#include "content/public/test/test_browser_thread.h" 22#include "content/public/test/test_notification_tracker.h" 23#include "content/test/net/url_request_prepackaged_interceptor.h" 24#include "googleurl/src/gurl.h" 25#include "libxml/globals.h" 26#include "net/url_request/url_fetcher.h" 27#include "net/url_request/url_request_test_util.h" 28#include "testing/gtest/include/gtest/gtest.h" 29 30using content::BrowserThread; 31using content::TestNotificationTracker; 32 33namespace { 34// Overrides some of the component updater behaviors so it is easier to test 35// and loops faster. In actual usage it takes hours do to a full cycle. 36class TestConfigurator : public ComponentUpdateService::Configurator { 37 public: 38 TestConfigurator() 39 : times_(1), recheck_time_(0), ondemand_time_(0), cus_(NULL) { 40 } 41 42 virtual int InitialDelay() OVERRIDE { return 0; } 43 44 typedef std::pair<CrxComponent*, int> CheckAtLoopCount; 45 46 virtual int NextCheckDelay() OVERRIDE { 47 // This is called when a new full cycle of checking for updates is going 48 // to happen. In test we normally only test one cycle so it is a good 49 // time to break from the test messageloop Run() method so the test can 50 // finish. 51 if (--times_ <= 0) { 52 MessageLoop::current()->Quit(); 53 return 0; 54 55 } 56 57 // Look for checks to issue in the middle of the loop. 58 for (std::list<CheckAtLoopCount>::iterator 59 i = components_to_check_.begin(); 60 i != components_to_check_.end(); ) { 61 if (i->second == times_) { 62 cus_->CheckForUpdateSoon(*i->first); 63 i = components_to_check_.erase(i); 64 } else { 65 ++i; 66 } 67 } 68 return 1; 69 } 70 71 virtual int StepDelay() OVERRIDE { 72 return 0; 73 } 74 75 virtual int MinimumReCheckWait() OVERRIDE { 76 return recheck_time_; 77 } 78 79 virtual int OnDemandDelay() OVERRIDE { 80 return ondemand_time_; 81 } 82 83 virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE { 84 switch (source) { 85 case CrxComponent::BANDAID: 86 return GURL("http://localhost/upd"); 87 case CrxComponent::CWS_PUBLIC: 88 return GURL("http://localhost/cws"); 89 default: 90 return GURL("http://wronghost/bad"); 91 }; 92 } 93 94 virtual const char* ExtraRequestParams() OVERRIDE { return "extra=foo"; } 95 96 virtual size_t UrlSizeLimit() OVERRIDE { return 256; } 97 98 virtual net::URLRequestContextGetter* RequestContext() OVERRIDE { 99 return new net::TestURLRequestContextGetter( 100 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 101 } 102 103 // Don't use the utility process to decode files. 104 virtual bool InProcess() OVERRIDE { return true; } 105 106 virtual void OnEvent(Events event, int extra) OVERRIDE { } 107 108 // Set how many update checks are called, the default value is just once. 109 void SetLoopCount(int times) { times_ = times; } 110 111 void SetRecheckTime(int seconds) { 112 recheck_time_ = seconds; 113 } 114 115 void SetOnDemandTime(int seconds) { 116 ondemand_time_ = seconds; 117 } 118 119 void AddComponentToCheck(CrxComponent* com, int at_loop_iter) { 120 components_to_check_.push_back(std::make_pair(com, at_loop_iter)); 121 } 122 123 void SetComponentUpdateService(ComponentUpdateService* cus) { 124 cus_ = cus; 125 } 126 127 private: 128 int times_; 129 int recheck_time_; 130 int ondemand_time_; 131 132 std::list<CheckAtLoopCount> components_to_check_; 133 ComponentUpdateService* cus_; 134}; 135 136class TestInstaller : public ComponentInstaller { 137 public : 138 explicit TestInstaller() 139 : error_(0), install_count_(0) { 140 } 141 142 virtual void OnUpdateError(int error) OVERRIDE { 143 EXPECT_NE(0, error); 144 error_ = error; 145 } 146 147 virtual bool Install(const base::DictionaryValue& manifest, 148 const base::FilePath& unpack_path) OVERRIDE { 149 ++install_count_; 150 return file_util::Delete(unpack_path, true); 151 } 152 153 int error() const { return error_; } 154 155 int install_count() const { return install_count_; } 156 157 private: 158 int error_; 159 int install_count_; 160}; 161 162// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and 163// the RSA public key the following hash: 164const uint8 jebg_hash[] = {0x94,0x16,0x0b,0x6d,0x41,0x75,0xe9,0xec,0x8e,0xd5, 165 0xfa,0x54,0xb0,0xd2,0xdd,0xa5,0x6e,0x05,0x6b,0xe8, 166 0x73,0x47,0xf6,0xc4,0x11,0x9f,0xbc,0xb3,0x09,0xb3, 167 0x5b,0x40}; 168// component 2 has extension id "abagagagagagagagagagagagagagagag", and 169// the RSA public key the following hash: 170const uint8 abag_hash[] = {0x01,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, 171 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, 172 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, 173 0x06,0x01}; 174 175const char expected_crx_url[] = 176 "http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"; 177 178} // namespace 179 180// Common fixture for all the component updater tests. 181class ComponentUpdaterTest : public testing::Test { 182 public: 183 enum TestComponents { 184 kTestComponent_abag, 185 kTestComponent_jebg 186 }; 187 188 ComponentUpdaterTest() : component_updater_(NULL), test_config_(NULL) { 189 // The component updater instance under test. 190 test_config_ = new TestConfigurator; 191 component_updater_.reset(ComponentUpdateServiceFactory(test_config_)); 192 test_config_->SetComponentUpdateService(component_updater_.get()); 193 // The test directory is chrome/test/data/components. 194 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_); 195 test_data_dir_ = test_data_dir_.AppendASCII("components"); 196 197 // Subscribe to all component updater notifications. 198 const int notifications[] = { 199 chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, 200 chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, 201 chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, 202 chrome::NOTIFICATION_COMPONENT_UPDATE_READY 203 }; 204 205 for (int ix = 0; ix != arraysize(notifications); ++ix) { 206 notification_tracker_.ListenFor( 207 notifications[ix], content::NotificationService::AllSources()); 208 } 209 net::URLFetcher::SetEnableInterceptionForTests(true); 210 } 211 212 virtual ~ComponentUpdaterTest() { 213 net::URLFetcher::SetEnableInterceptionForTests(false); 214 } 215 216 virtual void TearDown() { 217 xmlCleanupGlobals(); 218 } 219 220 ComponentUpdateService* component_updater() { 221 return component_updater_.get(); 222 } 223 224 // Makes the full path to a component updater test file. 225 const base::FilePath test_file(const char* file) { 226 return test_data_dir_.AppendASCII(file); 227 } 228 229 TestNotificationTracker& notification_tracker() { 230 return notification_tracker_; 231 } 232 233 TestConfigurator* test_configurator() { 234 return test_config_; 235 } 236 237 ComponentUpdateService::Status RegisterComponent(CrxComponent* com, 238 TestComponents component, 239 const Version& version) { 240 if (component == kTestComponent_abag) { 241 com->name = "test_abag"; 242 com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); 243 } else { 244 com->name = "test_jebg"; 245 com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); 246 } 247 com->version = version; 248 TestInstaller* installer = new TestInstaller; 249 com->installer = installer; 250 test_installers_.push_back(installer); 251 return component_updater_->RegisterComponent(*com); 252 } 253 254 private: 255 scoped_ptr<ComponentUpdateService> component_updater_; 256 base::FilePath test_data_dir_; 257 TestNotificationTracker notification_tracker_; 258 TestConfigurator* test_config_; 259 // ComponentInstaller objects to delete after each test. 260 ScopedVector<TestInstaller> test_installers_; 261}; 262 263// Verify that our test fixture work and the component updater can 264// be created and destroyed with no side effects. 265TEST_F(ComponentUpdaterTest, VerifyFixture) { 266 EXPECT_TRUE(component_updater() != NULL); 267 EXPECT_EQ(0ul, notification_tracker().size()); 268} 269 270// Verify that the component updater can be caught in a quick 271// start-shutdown situation. Failure of this test will be a crash. Also 272// if there is no work to do, there are no notifications generated. 273TEST_F(ComponentUpdaterTest, StartStop) { 274 MessageLoop message_loop; 275 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); 276 277 component_updater()->Start(); 278 message_loop.RunUntilIdle(); 279 component_updater()->Stop(); 280 281 EXPECT_EQ(0ul, notification_tracker().size()); 282} 283 284// Verify that when the server has no updates, we go back to sleep and 285// the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications 286// are generated. 287TEST_F(ComponentUpdaterTest, CheckCrxSleep) { 288 MessageLoop message_loop; 289 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); 290 content::TestBrowserThread file_thread(BrowserThread::FILE); 291 content::TestBrowserThread io_thread(BrowserThread::IO); 292 293 io_thread.StartIOThread(); 294 file_thread.Start(); 295 296 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 297 298 CrxComponent com; 299 EXPECT_EQ(ComponentUpdateService::kOk, 300 RegisterComponent(&com, kTestComponent_abag, Version("1.1"))); 301 302 const GURL expected_update_url( 303 "http://localhost/upd?extra=foo&x=id%3D" 304 "abagagagagagagagagagagagagagagag%26v%3D1.1%26uc"); 305 306 interceptor.SetResponse(expected_update_url, 307 test_file("updatecheck_reply_1.xml")); 308 309 // We loop twice, but there are no updates so we expect two sleep messages. 310 test_configurator()->SetLoopCount(2); 311 component_updater()->Start(); 312 313 ASSERT_EQ(1ul, notification_tracker().size()); 314 TestNotificationTracker::Event ev1 = notification_tracker().at(0); 315 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type); 316 317 message_loop.Run(); 318 319 ASSERT_EQ(3ul, notification_tracker().size()); 320 TestNotificationTracker::Event ev2 = notification_tracker().at(1); 321 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type); 322 TestNotificationTracker::Event ev3 = notification_tracker().at(2); 323 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type); 324 EXPECT_EQ(2, interceptor.GetHitCount()); 325 326 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 327 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 328 329 component_updater()->Stop(); 330 331 // Loop twice again but this case we simulate a server error by returning 332 // an empty file. 333 334 interceptor.SetResponse(expected_update_url, 335 test_file("updatecheck_reply_empty")); 336 337 notification_tracker().Reset(); 338 test_configurator()->SetLoopCount(2); 339 component_updater()->Start(); 340 341 message_loop.Run(); 342 343 ASSERT_EQ(3ul, notification_tracker().size()); 344 ev1 = notification_tracker().at(0); 345 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type); 346 ev2 = notification_tracker().at(1); 347 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type); 348 ev3 = notification_tracker().at(2); 349 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type); 350 EXPECT_EQ(4, interceptor.GetHitCount()); 351 352 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error()); 353 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count()); 354 355 component_updater()->Stop(); 356} 357 358// Verify that we can check for updates and install one component. Besides 359// the notifications above NOTIFICATION_COMPONENT_UPDATE_FOUND and 360// NOTIFICATION_COMPONENT_UPDATE_READY should have been fired. We do two loops 361// so the second time around there should be nothing left to do. 362// We also check that only 3 network requests are issued: 363// 1- manifest check 364// 2- download crx 365// 3- second manifest check. 366TEST_F(ComponentUpdaterTest, InstallCrx) { 367 MessageLoop message_loop; 368 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); 369 content::TestBrowserThread file_thread(BrowserThread::FILE); 370 content::TestBrowserThread io_thread(BrowserThread::IO); 371 372 io_thread.StartIOThread(); 373 file_thread.Start(); 374 375 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 376 377 CrxComponent com1; 378 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9")); 379 CrxComponent com2; 380 RegisterComponent(&com2, kTestComponent_abag, Version("2.2")); 381 382 const GURL expected_update_url_1( 383 "http://localhost/upd?extra=foo&x=id%3D" 384 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D" 385 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc"); 386 387 const GURL expected_update_url_2( 388 "http://localhost/upd?extra=foo&x=id%3D" 389 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D" 390 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc"); 391 392 interceptor.SetResponse(expected_update_url_1, 393 test_file("updatecheck_reply_1.xml")); 394 interceptor.SetResponse(expected_update_url_2, 395 test_file("updatecheck_reply_1.xml")); 396 interceptor.SetResponse(GURL(expected_crx_url), 397 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 398 399 test_configurator()->SetLoopCount(2); 400 401 component_updater()->Start(); 402 message_loop.Run(); 403 404 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 405 EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count()); 406 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 407 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 408 409 EXPECT_EQ(3, interceptor.GetHitCount()); 410 411 ASSERT_EQ(5ul, notification_tracker().size()); 412 413 TestNotificationTracker::Event ev1 = notification_tracker().at(1); 414 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type); 415 416 TestNotificationTracker::Event ev2 = notification_tracker().at(2); 417 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type); 418 419 TestNotificationTracker::Event ev3 = notification_tracker().at(3); 420 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); 421 422 TestNotificationTracker::Event ev4 = notification_tracker().at(4); 423 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type); 424 425 component_updater()->Stop(); 426} 427 428// This test is like the above InstallCrx but the second component 429// has a different source. In this case there would be two manifest 430// checks to different urls, each only containing one component. 431TEST_F(ComponentUpdaterTest, InstallCrxTwoSources) { 432 MessageLoop message_loop; 433 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); 434 content::TestBrowserThread file_thread(BrowserThread::FILE); 435 content::TestBrowserThread io_thread(BrowserThread::IO); 436 437 io_thread.StartIOThread(); 438 file_thread.Start(); 439 440 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 441 442 CrxComponent com1; 443 RegisterComponent(&com1, kTestComponent_abag, Version("2.2")); 444 CrxComponent com2; 445 com2.source = CrxComponent::CWS_PUBLIC; 446 RegisterComponent(&com2, kTestComponent_jebg, Version("0.9")); 447 448 const GURL expected_update_url_1( 449 "http://localhost/upd?extra=foo&x=id%3D" 450 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc"); 451 452 const GURL expected_update_url_2( 453 "http://localhost/cws?extra=foo&x=id%3D" 454 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc"); 455 456 interceptor.SetResponse(expected_update_url_1, 457 test_file("updatecheck_reply_3.xml")); 458 interceptor.SetResponse(expected_update_url_2, 459 test_file("updatecheck_reply_1.xml")); 460 interceptor.SetResponse(GURL(expected_crx_url), 461 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 462 463 test_configurator()->SetLoopCount(3); 464 465 // We have to set SetRecheckTime to something bigger than 0 or else the 466 // component updater will keep re-checking the 'abag' component because 467 // the default source pre-empts the other sources. 468 test_configurator()->SetRecheckTime(60*60); 469 470 component_updater()->Start(); 471 message_loop.Run(); 472 473 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 474 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count()); 475 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 476 EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count()); 477 478 EXPECT_EQ(3, interceptor.GetHitCount()); 479 480 ASSERT_EQ(6ul, notification_tracker().size()); 481 482 TestNotificationTracker::Event ev0 = notification_tracker().at(1); 483 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev0.type); 484 485 TestNotificationTracker::Event ev1 = notification_tracker().at(2); 486 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type); 487 488 TestNotificationTracker::Event ev2 = notification_tracker().at(3); 489 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type); 490 491 TestNotificationTracker::Event ev3 = notification_tracker().at(4); 492 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); 493 494 TestNotificationTracker::Event ev4 = notification_tracker().at(5); 495 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type); 496 497 component_updater()->Stop(); 498} 499 500// This test checks that the "prodversionmin" value is handled correctly. In 501// particular there should not be an install because the minimum product 502// version is much higher than of chrome. 503TEST_F(ComponentUpdaterTest, ProdVersionCheck) { 504 MessageLoop message_loop; 505 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); 506 content::TestBrowserThread file_thread(BrowserThread::FILE); 507 content::TestBrowserThread io_thread(BrowserThread::IO); 508 509 io_thread.StartIOThread(); 510 file_thread.Start(); 511 512 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 513 514 CrxComponent com; 515 RegisterComponent(&com, kTestComponent_jebg, Version("0.9")); 516 517 const GURL expected_update_url( 518 "http://localhost/upd?extra=foo&x=id%3D" 519 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc"); 520 521 interceptor.SetResponse(expected_update_url, 522 test_file("updatecheck_reply_2.xml")); 523 interceptor.SetResponse(GURL(expected_crx_url), 524 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 525 526 test_configurator()->SetLoopCount(1); 527 component_updater()->Start(); 528 message_loop.Run(); 529 530 EXPECT_EQ(1, interceptor.GetHitCount()); 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 ping for an update check 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 ping. 542// - This triggers a second loop, which has a reply that triggers an install. 543TEST_F(ComponentUpdaterTest, CheckForUpdateSoon) { 544 MessageLoop message_loop; 545 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); 546 content::TestBrowserThread file_thread(BrowserThread::FILE); 547 content::TestBrowserThread io_thread(BrowserThread::IO); 548 549 io_thread.StartIOThread(); 550 file_thread.Start(); 551 552 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 553 554 CrxComponent com1; 555 RegisterComponent(&com1, kTestComponent_abag, Version("2.2")); 556 CrxComponent com2; 557 RegisterComponent(&com2, kTestComponent_jebg, Version("0.9")); 558 559 const GURL expected_update_url_1( 560 "http://localhost/upd?extra=foo&x=id%3D" 561 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D" 562 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc"); 563 564 const GURL expected_update_url_2( 565 "http://localhost/upd?extra=foo&x=id%3D" 566 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D" 567 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc"); 568 569 interceptor.SetResponse(expected_update_url_1, 570 test_file("updatecheck_reply_empty")); 571 interceptor.SetResponse(expected_update_url_2, 572 test_file("updatecheck_reply_1.xml")); 573 interceptor.SetResponse(GURL(expected_crx_url), 574 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 575 // Test success. 576 test_configurator()->SetLoopCount(2); 577 test_configurator()->AddComponentToCheck(&com2, 1); 578 component_updater()->Start(); 579 message_loop.Run(); 580 581 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 582 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count()); 583 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 584 EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count()); 585 586 EXPECT_EQ(3, interceptor.GetHitCount()); 587 588 ASSERT_EQ(5ul, notification_tracker().size()); 589 590 TestNotificationTracker::Event ev0= notification_tracker().at(0); 591 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type); 592 593 TestNotificationTracker::Event ev1 = notification_tracker().at(1); 594 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type); 595 596 TestNotificationTracker::Event ev2 = notification_tracker().at(2); 597 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev2.type); 598 599 TestNotificationTracker::Event ev3 = notification_tracker().at(3); 600 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev3.type); 601 602 TestNotificationTracker::Event ev4 = notification_tracker().at(4); 603 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type); 604 605 // Also check what happens if previous check too soon. 606 test_configurator()->SetOnDemandTime(60 * 60); 607 EXPECT_EQ(ComponentUpdateService::kError, 608 component_updater()->CheckForUpdateSoon(com2)); 609 // Okay, now reset to 0 for the other tests. 610 test_configurator()->SetOnDemandTime(0); 611 component_updater()->Stop(); 612 613 // Test a few error cases. NOTE: We don't have callbacks for 614 // when the updates failed yet. 615 const GURL expected_update_url_3( 616 "http://localhost/upd?extra=foo&x=id%3D" 617 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc&x=id%3D" 618 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc"); 619 620 // No update: error from no server response 621 interceptor.SetResponse(expected_update_url_3, 622 test_file("updatecheck_reply_empty")); 623 notification_tracker().Reset(); 624 test_configurator()->SetLoopCount(1); 625 component_updater()->Start(); 626 EXPECT_EQ(ComponentUpdateService::kOk, 627 component_updater()->CheckForUpdateSoon(com2)); 628 629 message_loop.Run(); 630 631 ASSERT_EQ(2ul, notification_tracker().size()); 632 ev0 = notification_tracker().at(0); 633 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type); 634 ev1 = notification_tracker().at(1); 635 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type); 636 component_updater()->Stop(); 637 638 // No update: already updated to 1.0 so nothing new 639 interceptor.SetResponse(expected_update_url_3, 640 test_file("updatecheck_reply_1.xml")); 641 notification_tracker().Reset(); 642 test_configurator()->SetLoopCount(1); 643 component_updater()->Start(); 644 EXPECT_EQ(ComponentUpdateService::kOk, 645 component_updater()->CheckForUpdateSoon(com2)); 646 647 message_loop.Run(); 648 649 ASSERT_EQ(2ul, notification_tracker().size()); 650 ev0 = notification_tracker().at(0); 651 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type); 652 ev1 = notification_tracker().at(1); 653 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type); 654 component_updater()->Stop(); 655} 656 657// Verify that a previously registered component can get re-registered 658// with a different version. 659TEST_F(ComponentUpdaterTest, CheckReRegistration) { 660 MessageLoop message_loop; 661 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); 662 content::TestBrowserThread file_thread(BrowserThread::FILE); 663 content::TestBrowserThread io_thread(BrowserThread::IO); 664 665 io_thread.StartIOThread(); 666 file_thread.Start(); 667 668 content::URLLocalHostRequestPrepackagedInterceptor interceptor; 669 670 CrxComponent com1; 671 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9")); 672 CrxComponent com2; 673 RegisterComponent(&com2, kTestComponent_abag, Version("2.2")); 674 675 // Start with 0.9, and update to 1.0 676 const GURL expected_update_url_1( 677 "http://localhost/upd?extra=foo&x=id%3D" 678 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D" 679 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc"); 680 681 const GURL expected_update_url_2( 682 "http://localhost/upd?extra=foo&x=id%3D" 683 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D" 684 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc"); 685 686 interceptor.SetResponse(expected_update_url_1, 687 test_file("updatecheck_reply_1.xml")); 688 interceptor.SetResponse(expected_update_url_2, 689 test_file("updatecheck_reply_1.xml")); 690 interceptor.SetResponse(GURL(expected_crx_url), 691 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); 692 693 // Loop twice to issue two checks: (1) with original 0.9 version 694 // and (2) with the updated 1.0 version. 695 test_configurator()->SetLoopCount(2); 696 697 component_updater()->Start(); 698 message_loop.Run(); 699 700 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 701 EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count()); 702 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 703 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 704 705 EXPECT_EQ(3, interceptor.GetHitCount()); 706 707 ASSERT_EQ(5ul, notification_tracker().size()); 708 709 TestNotificationTracker::Event ev0 = notification_tracker().at(0); 710 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type); 711 712 TestNotificationTracker::Event ev1 = notification_tracker().at(1); 713 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type); 714 715 TestNotificationTracker::Event ev2 = notification_tracker().at(2); 716 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type); 717 718 TestNotificationTracker::Event ev3 = notification_tracker().at(3); 719 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type); 720 721 TestNotificationTracker::Event ev4 = notification_tracker().at(4); 722 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type); 723 724 // Now re-register, pretending to be an even newer version (2.2) 725 component_updater()->Stop(); 726 EXPECT_EQ(ComponentUpdateService::kReplaced, 727 RegisterComponent(&com1, kTestComponent_jebg, Version("2.2"))); 728 729 // Check that we send out 2.2 as our version. 730 // Interceptor's hit count should go up by 1. 731 const GURL expected_update_url_3( 732 "http://localhost/upd?extra=foo&x=id%3D" 733 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D2.2%26uc&x=id%3D" 734 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc"); 735 736 interceptor.SetResponse(expected_update_url_3, 737 test_file("updatecheck_reply_1.xml")); 738 739 notification_tracker().Reset(); 740 741 // Loop once just to notice the check happening with the re-register version. 742 test_configurator()->SetLoopCount(1); 743 component_updater()->Start(); 744 message_loop.Run(); 745 746 ASSERT_EQ(2ul, notification_tracker().size()); 747 748 ev0 = notification_tracker().at(0); 749 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type); 750 751 ev1 = notification_tracker().at(1); 752 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type); 753 754 EXPECT_EQ(4, interceptor.GetHitCount()); 755 756 // The test harness's Register() function creates a new installer, 757 // so the counts go back to 0. 758 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error()); 759 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count()); 760 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error()); 761 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count()); 762 763 component_updater()->Stop(); 764} 765