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