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.
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/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/component_updater/test/test_installer.h"
13 #include "chrome/common/chrome_paths.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/test/net/url_request_prepackaged_interceptor.h"
16 #include "libxml/globals.h"
17 #include "net/base/upload_bytes_element_reader.h"
18 #include "net/url_request/url_fetcher.h"
21 using content::BrowserThread;
24 using ::testing::InSequence;
25 using ::testing::Mock;
27 MockComponentObserver::MockComponentObserver() {
30 MockComponentObserver::~MockComponentObserver() {
33 TestConfigurator::TestConfigurator()
38 context_(new net::TestURLRequestContextGetter(
39 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) {
42 TestConfigurator::~TestConfigurator() {
45 int TestConfigurator::InitialDelay() { return 0; }
47 int TestConfigurator::NextCheckDelay() {
48 // This is called when a new full cycle of checking for updates is going
49 // to happen. In test we normally only test one cycle so it is a good
50 // time to break from the test messageloop Run() method so the test can
59 int TestConfigurator::StepDelay() {
63 int TestConfigurator::StepDelayMedium() {
64 return NextCheckDelay();
67 int TestConfigurator::MinimumReCheckWait() {
71 int TestConfigurator::OnDemandDelay() {
72 return ondemand_time_;
75 GURL TestConfigurator::UpdateUrl() {
76 return GURL("http://localhost/upd");
79 GURL TestConfigurator::PingUrl() {
80 return GURL("http://localhost2/ping");
83 const char* TestConfigurator::ExtraRequestParams() { return "extra=foo"; }
85 size_t TestConfigurator::UrlSizeLimit() { return 256; }
87 net::URLRequestContextGetter* TestConfigurator::RequestContext() {
88 return context_.get();
91 // Don't use the utility process to decode files.
92 bool TestConfigurator::InProcess() { return true; }
94 ComponentPatcher* TestConfigurator::CreateComponentPatcher() {
95 return new MockComponentPatcher();
98 bool TestConfigurator::DeltasEnabled() const {
102 // Set how many update checks are called, the default value is just once.
103 void TestConfigurator::SetLoopCount(int times) { times_ = times; }
105 void TestConfigurator::SetRecheckTime(int seconds) {
106 recheck_time_ = seconds;
109 void TestConfigurator::SetOnDemandTime(int seconds) {
110 ondemand_time_ = seconds;
113 void TestConfigurator::SetComponentUpdateService(ComponentUpdateService* cus) {
117 void TestConfigurator::SetQuitClosure(const base::Closure& quit_closure) {
118 quit_closure_ = quit_closure;
121 ComponentUpdaterTest::ComponentUpdaterTest()
122 : test_config_(NULL),
123 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
124 // The component updater instance under test.
125 test_config_ = new TestConfigurator;
126 component_updater_.reset(ComponentUpdateServiceFactory(test_config_));
127 test_config_->SetComponentUpdateService(component_updater_.get());
129 // The test directory is chrome/test/data/components.
130 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
131 test_data_dir_ = test_data_dir_.AppendASCII("components");
133 net::URLFetcher::SetEnableInterceptionForTests(true);
136 ComponentUpdaterTest::~ComponentUpdaterTest() {
137 net::URLFetcher::SetEnableInterceptionForTests(false);
140 void ComponentUpdaterTest::TearDown() {
144 ComponentUpdateService* ComponentUpdaterTest::component_updater() {
145 return component_updater_.get();
148 // Makes the full path to a component updater test file.
149 const base::FilePath ComponentUpdaterTest::test_file(const char* file) {
150 return test_data_dir_.AppendASCII(file);
153 TestConfigurator* ComponentUpdaterTest::test_configurator() {
157 ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent(
159 TestComponents component,
160 const Version& version,
161 TestInstaller* installer) {
162 if (component == kTestComponent_abag) {
163 com->name = "test_abag";
164 com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
165 } else if (component == kTestComponent_jebg) {
166 com->name = "test_jebg";
167 com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
169 com->name = "test_ihfo";
170 com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
172 com->version = version;
173 com->installer = installer;
174 return component_updater_->RegisterComponent(*com);
177 void ComponentUpdaterTest::RunThreads() {
178 base::RunLoop runloop;
179 test_configurator()->SetQuitClosure(runloop.QuitClosure());
183 void ComponentUpdaterTest::RunThreadsUntilIdle() {
184 base::RunLoop().RunUntilIdle();
187 PingChecker::PingChecker(const std::map<std::string, std::string>& attributes)
188 : num_hits_(0), num_misses_(0), attributes_(attributes) {
191 PingChecker::~PingChecker() {}
193 void PingChecker::Trial(net::URLRequest* request) {
200 bool PingChecker::Test(net::URLRequest* request) {
201 if (request->has_upload()) {
202 const net::UploadDataStream* stream = request->get_upload();
203 const net::UploadBytesElementReader* reader =
204 stream->element_readers()[0]->AsBytesReader();
205 int size = reader->length();
206 scoped_refptr <net::IOBuffer> buffer = new net::IOBuffer(size);
207 std::string data(reader->bytes());
208 pings_.push_back(data);
209 // For now, we assume that there is only one ping per POST.
210 std::string::size_type start = data.find("<o:event");
211 if (start != std::string::npos) {
212 std::string::size_type end = data.find(">", start);
213 if (end != std::string::npos) {
214 std::string ping = data.substr(start, end - start);
215 std::map<std::string, std::string>::const_iterator iter;
216 for (iter = attributes_.begin(); iter != attributes_.end(); ++iter) {
217 // does the ping contain the specified attribute/value?
218 if (ping.find(std::string(" ") + (iter->first) +
219 std::string("=") + (iter->second)) == string::npos) {
230 std::string PingChecker::GetPings() const {
231 std::string pings_str = "Pings are:";
233 for (std::vector<std::string>::const_iterator it = pings_.begin();
234 it != pings_.end(); ++it) {
235 pings_str.append(base::StringPrintf("\n (%d): %s", ++i, it->c_str()));
240 ComponentUpdateService::Status OnDemandTester::OnDemand(
241 ComponentUpdateService* cus, const std::string& component_id) {
242 return cus->OnDemandUpdate(component_id);
245 // Verify that our test fixture work and the component updater can
246 // be created and destroyed with no side effects.
247 TEST_F(ComponentUpdaterTest, VerifyFixture) {
248 EXPECT_TRUE(component_updater() != NULL);
251 // Verify that the component updater can be caught in a quick
252 // start-shutdown situation. Failure of this test will be a crash.
253 TEST_F(ComponentUpdaterTest, StartStop) {
254 component_updater()->Start();
255 RunThreadsUntilIdle();
256 component_updater()->Stop();
259 // Verify that when the server has no updates, we go back to sleep and
260 // the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications
262 TEST_F(ComponentUpdaterTest, CheckCrxSleep) {
263 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
265 MockComponentObserver observer;
267 TestInstaller installer;
269 com.observer = &observer;
270 EXPECT_EQ(ComponentUpdateService::kOk,
271 RegisterComponent(&com,
276 const GURL expected_update_url(
277 "http://localhost/upd?extra=foo"
278 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D1.1%26fp%3D%26uc");
280 interceptor.SetResponse(expected_update_url,
281 test_file("updatecheck_reply_1.xml"));
283 // We loop twice, but there are no updates so we expect two sleep messages.
284 test_configurator()->SetLoopCount(2);
286 EXPECT_CALL(observer,
287 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
289 component_updater()->Start();
291 EXPECT_CALL(observer,
292 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
295 EXPECT_CALL(observer,
296 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
300 EXPECT_EQ(2, interceptor.GetHitCount());
302 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
303 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
305 component_updater()->Stop();
307 // Loop twice again but this case we simulate a server error by returning
310 interceptor.SetResponse(expected_update_url,
311 test_file("updatecheck_reply_empty"));
313 test_configurator()->SetLoopCount(2);
315 EXPECT_CALL(observer,
316 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
318 component_updater()->Start();
320 EXPECT_CALL(observer,
321 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
323 EXPECT_CALL(observer,
324 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
328 EXPECT_EQ(4, interceptor.GetHitCount());
330 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
331 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
333 component_updater()->Stop();
336 // Verify that we can check for updates and install one component. Besides
337 // the notifications above COMPONENT_UPDATE_FOUND and COMPONENT_UPDATE_READY
338 // should have been fired. We do two loops so the second time around there
339 // should be nothing left to do.
340 // We also check that only 3 non-ping network requests are issued:
343 // 3- second manifest check.
344 TEST_F(ComponentUpdaterTest, InstallCrx) {
345 std::map<std::string, std::string> map;
346 map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
347 map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
348 map.insert(std::pair<std::string, std::string>("previousversion",
350 map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
351 PingChecker ping_checker(map);
352 URLRequestPostInterceptor post_interceptor(&ping_checker);
353 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
355 MockComponentObserver observer1;
358 EXPECT_CALL(observer1,
359 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
361 EXPECT_CALL(observer1,
362 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
364 EXPECT_CALL(observer1,
365 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
367 EXPECT_CALL(observer1,
368 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
370 EXPECT_CALL(observer1,
371 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
373 EXPECT_CALL(observer1,
374 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
376 EXPECT_CALL(observer1,
377 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
381 MockComponentObserver observer2;
384 EXPECT_CALL(observer2,
385 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
387 EXPECT_CALL(observer2,
388 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
390 EXPECT_CALL(observer2,
391 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
393 EXPECT_CALL(observer2,
394 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
396 EXPECT_CALL(observer2,
397 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
401 TestInstaller installer1;
403 com1.observer = &observer1;
404 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
405 TestInstaller installer2;
407 com2.observer = &observer2;
408 RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
410 const GURL expected_update_url_1(
411 "http://localhost/upd?extra=foo"
412 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
413 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
415 const GURL expected_update_url_2(
416 "http://localhost/upd?extra=foo"
417 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
418 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc");
420 interceptor.SetResponse(expected_update_url_1,
421 test_file("updatecheck_reply_1.xml"));
422 interceptor.SetResponse(expected_update_url_2,
423 test_file("updatecheck_reply_1.xml"));
424 interceptor.SetResponse(GURL(expected_crx_url),
425 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
427 test_configurator()->SetLoopCount(2);
429 component_updater()->Start();
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());
437 EXPECT_EQ(3, interceptor.GetHitCount());
438 EXPECT_EQ(1, ping_checker.NumHits()) << ping_checker.GetPings();
439 EXPECT_EQ(0, ping_checker.NumMisses()) << ping_checker.GetPings();
441 component_updater()->Stop();
444 // This test checks that the "prodversionmin" value is handled correctly. In
445 // particular there should not be an install because the minimum product
446 // version is much higher than of chrome.
447 TEST_F(ComponentUpdaterTest, ProdVersionCheck) {
448 std::map<std::string, std::string> map;
449 PingChecker ping_checker(map);
450 URLRequestPostInterceptor post_interceptor(&ping_checker);
451 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
453 TestInstaller installer;
455 RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
457 const GURL expected_update_url(
458 "http://localhost/upd?extra=foo&x=id%3D"
459 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
461 interceptor.SetResponse(expected_update_url,
462 test_file("updatecheck_reply_2.xml"));
463 interceptor.SetResponse(GURL(expected_crx_url),
464 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
466 test_configurator()->SetLoopCount(1);
467 component_updater()->Start();
470 EXPECT_EQ(0, ping_checker.NumHits()) << ping_checker.GetPings();
471 EXPECT_EQ(0, ping_checker.NumMisses()) << ping_checker.GetPings();
472 EXPECT_EQ(1, interceptor.GetHitCount());
473 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
474 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
476 component_updater()->Stop();
479 // Test that a ping for an update check can cause installs.
480 // Here is the timeline:
481 // - First loop: we return a reply that indicates no update, so
484 // - This triggers a second loop, which has a reply that triggers an install.
485 TEST_F(ComponentUpdaterTest, OnDemandUpdate) {
486 std::map<std::string, std::string> map;
487 map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
488 map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
489 map.insert(std::pair<std::string, std::string>("previousversion",
491 map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
492 PingChecker ping_checker(map);
493 URLRequestPostInterceptor post_interceptor(&ping_checker);
494 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
496 MockComponentObserver observer1;
499 EXPECT_CALL(observer1,
500 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
502 EXPECT_CALL(observer1,
503 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
505 EXPECT_CALL(observer1,
506 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
508 EXPECT_CALL(observer1,
509 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
511 EXPECT_CALL(observer1,
512 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
514 EXPECT_CALL(observer1,
515 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
519 MockComponentObserver observer2;
522 EXPECT_CALL(observer2,
523 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
525 EXPECT_CALL(observer2,
526 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
528 EXPECT_CALL(observer2,
529 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
531 EXPECT_CALL(observer2,
532 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
534 EXPECT_CALL(observer2,
535 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
537 EXPECT_CALL(observer2,
538 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
540 EXPECT_CALL(observer2,
541 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
543 EXPECT_CALL(observer2,
544 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
548 TestInstaller installer1;
550 com1.observer = &observer1;
551 RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1);
552 TestInstaller installer2;
554 com2.observer = &observer2;
555 RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2);
557 const GURL expected_update_url_1(
558 "http://localhost/upd?extra=foo"
559 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
560 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
562 const GURL expected_update_url_2(
563 "http://localhost/upd?extra=foo"
564 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
565 "%26installsource%3Dondemand"
566 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
568 interceptor.SetResponse(expected_update_url_1,
569 test_file("updatecheck_reply_empty"));
570 interceptor.SetResponse(expected_update_url_2,
571 test_file("updatecheck_reply_1.xml"));
572 interceptor.SetResponse(GURL(expected_crx_url),
573 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
574 // No update normally.
575 test_configurator()->SetLoopCount(1);
576 component_updater()->Start();
578 component_updater()->Stop();
580 // Update after an on-demand check is issued.
581 EXPECT_EQ(ComponentUpdateService::kOk,
582 OnDemandTester::OnDemand(component_updater(),
583 GetCrxComponentID(com2)));
584 test_configurator()->SetLoopCount(1);
585 component_updater()->Start();
588 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
589 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
590 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
591 EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count());
593 EXPECT_EQ(3, interceptor.GetHitCount());
595 // Also check what happens if previous check too soon.
596 test_configurator()->SetOnDemandTime(60 * 60);
597 EXPECT_EQ(ComponentUpdateService::kError,
598 OnDemandTester::OnDemand(component_updater(),
599 GetCrxComponentID(com2)));
600 // Okay, now reset to 0 for the other tests.
601 test_configurator()->SetOnDemandTime(0);
602 component_updater()->Stop();
604 // Test a few error cases. NOTE: We don't have callbacks for
605 // when the updates failed yet.
606 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
609 EXPECT_CALL(observer1,
610 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
612 EXPECT_CALL(observer1,
613 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
615 EXPECT_CALL(observer1,
616 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
619 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
622 EXPECT_CALL(observer2,
623 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
625 EXPECT_CALL(observer2,
626 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
628 EXPECT_CALL(observer2,
629 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
633 const GURL expected_update_url_3(
634 "http://localhost/upd?extra=foo"
635 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc"
636 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
638 // No update: error from no server response
639 interceptor.SetResponse(expected_update_url_3,
640 test_file("updatecheck_reply_empty"));
641 test_configurator()->SetLoopCount(1);
642 component_updater()->Start();
643 EXPECT_EQ(ComponentUpdateService::kOk,
644 OnDemandTester::OnDemand(component_updater(),
645 GetCrxComponentID(com2)));
649 component_updater()->Stop();
651 // No update: already updated to 1.0 so nothing new
652 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
655 EXPECT_CALL(observer1,
656 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
658 EXPECT_CALL(observer1,
659 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
661 EXPECT_CALL(observer1,
662 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
665 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
668 EXPECT_CALL(observer2,
669 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
671 EXPECT_CALL(observer2,
672 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
674 EXPECT_CALL(observer2,
675 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
679 interceptor.SetResponse(expected_update_url_3,
680 test_file("updatecheck_reply_1.xml"));
681 test_configurator()->SetLoopCount(1);
682 component_updater()->Start();
683 EXPECT_EQ(ComponentUpdateService::kOk,
684 OnDemandTester::OnDemand(component_updater(),
685 GetCrxComponentID(com2)));
689 EXPECT_EQ(1, ping_checker.NumHits()) << ping_checker.GetPings();
690 EXPECT_EQ(0, ping_checker.NumMisses()) << ping_checker.GetPings();
692 component_updater()->Stop();
695 // Verify that a previously registered component can get re-registered
696 // with a different version.
697 TEST_F(ComponentUpdaterTest, CheckReRegistration) {
698 std::map<std::string, std::string> map;
699 map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
700 map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
701 map.insert(std::pair<std::string, std::string>("previousversion",
703 map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
704 PingChecker ping_checker(map);
705 URLRequestPostInterceptor post_interceptor(&ping_checker);
706 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
708 MockComponentObserver observer1;
711 EXPECT_CALL(observer1,
712 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
714 EXPECT_CALL(observer1,
715 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
717 EXPECT_CALL(observer1,
718 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
720 EXPECT_CALL(observer1,
721 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
723 EXPECT_CALL(observer1,
724 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
726 EXPECT_CALL(observer1,
727 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
729 EXPECT_CALL(observer1,
730 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
734 MockComponentObserver observer2;
737 EXPECT_CALL(observer2,
738 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
740 EXPECT_CALL(observer2,
741 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
743 EXPECT_CALL(observer2,
744 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
746 EXPECT_CALL(observer2,
747 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
749 EXPECT_CALL(observer2,
750 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
754 TestInstaller installer1;
756 com1.observer = &observer1;
757 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
758 TestInstaller installer2;
760 com2.observer = &observer2;
761 RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
763 // Start with 0.9, and update to 1.0
764 const GURL expected_update_url_1(
765 "http://localhost/upd?extra=foo"
766 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
767 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
769 const GURL expected_update_url_2(
770 "http://localhost/upd?extra=foo"
771 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
772 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc");
774 interceptor.SetResponse(expected_update_url_1,
775 test_file("updatecheck_reply_1.xml"));
776 interceptor.SetResponse(expected_update_url_2,
777 test_file("updatecheck_reply_1.xml"));
778 interceptor.SetResponse(GURL(expected_crx_url),
779 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
781 // Loop twice to issue two checks: (1) with original 0.9 version
782 // and (2) with the updated 1.0 version.
783 test_configurator()->SetLoopCount(2);
785 component_updater()->Start();
788 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
789 EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
790 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
791 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
793 EXPECT_EQ(1, ping_checker.NumHits()) << ping_checker.GetPings();
794 EXPECT_EQ(0, ping_checker.NumMisses()) << ping_checker.GetPings();
795 EXPECT_EQ(3, interceptor.GetHitCount());
797 component_updater()->Stop();
799 // Now re-register, pretending to be an even newer version (2.2)
800 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
803 EXPECT_CALL(observer1,
804 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
806 EXPECT_CALL(observer1,
807 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
809 EXPECT_CALL(observer1,
810 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
814 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
817 EXPECT_CALL(observer2,
818 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
820 EXPECT_CALL(observer2,
821 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
823 EXPECT_CALL(observer2,
824 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
828 TestInstaller installer3;
829 EXPECT_EQ(ComponentUpdateService::kReplaced,
830 RegisterComponent(&com1,
835 // Check that we send out 2.2 as our version.
836 // Interceptor's hit count should go up by 1.
837 const GURL expected_update_url_3(
838 "http://localhost/upd?extra=foo"
839 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D2.2%26fp%3D%26uc"
840 "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
842 interceptor.SetResponse(expected_update_url_3,
843 test_file("updatecheck_reply_1.xml"));
845 // Loop once just to notice the check happening with the re-register version.
846 test_configurator()->SetLoopCount(1);
847 component_updater()->Start();
850 EXPECT_EQ(4, interceptor.GetHitCount());
852 // We created a new installer, so the counts go back to 0.
853 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
854 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
855 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
856 EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
858 component_updater()->Stop();
861 // Verify that we can download and install a component and a differential
862 // update to that component. We do three loops; the final loop should do
864 // We also check that exactly 5 non-ping network requests are issued:
865 // 1- update check (response: v1 available)
866 // 2- download crx (v1)
867 // 3- update check (response: v2 available)
868 // 4- download differential crx (v1 to v2)
869 // 5- update check (response: no further update available)
870 // There should be two pings, one for each update. The second will bear a
871 // diffresult=1, while the first will not.
872 TEST_F(ComponentUpdaterTest, DifferentialUpdate) {
873 std::map<std::string, std::string> map;
874 map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
875 map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
876 map.insert(std::pair<std::string, std::string>("diffresult", "\"1\""));
877 PingChecker ping_checker(map);
878 URLRequestPostInterceptor post_interceptor(&ping_checker);
879 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
881 VersionedTestInstaller installer;
883 RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
885 const GURL expected_update_url_0(
886 "http://localhost/upd?extra=foo"
887 "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D0.0%26fp%3D%26uc");
888 const GURL expected_update_url_1(
889 "http://localhost/upd?extra=foo"
890 "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D1%26uc");
891 const GURL expected_update_url_2(
892 "http://localhost/upd?extra=foo"
893 "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
894 const GURL expected_crx_url_1(
895 "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
896 const GURL expected_crx_url_1_diff_2(
897 "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
899 interceptor.SetResponse(expected_update_url_0,
900 test_file("updatecheck_diff_reply_1.xml"));
901 interceptor.SetResponse(expected_update_url_1,
902 test_file("updatecheck_diff_reply_2.xml"));
903 interceptor.SetResponse(expected_update_url_2,
904 test_file("updatecheck_diff_reply_3.xml"));
905 interceptor.SetResponse(expected_crx_url_1,
906 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
907 interceptor.SetResponse(
908 expected_crx_url_1_diff_2,
909 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
911 test_configurator()->SetLoopCount(3);
913 component_updater()->Start();
916 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
917 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
919 // One ping has the diffresult=1, the other does not.
920 EXPECT_EQ(1, ping_checker.NumHits()) << ping_checker.GetPings();
921 EXPECT_EQ(1, ping_checker.NumMisses()) << ping_checker.GetPings();
923 EXPECT_EQ(5, interceptor.GetHitCount());
925 component_updater()->Stop();
928 // Verify that component installation falls back to downloading and installing
929 // a full update if the differential update fails (in this case, because the
930 // installer does not know about the existing files). We do two loops; the final
931 // loop should do nothing.
932 // We also check that exactly 4 non-ping network requests are issued:
933 // 1- update check (loop 1)
934 // 2- download differential crx
935 // 3- download full crx
936 // 4- update check (loop 2 - no update available)
937 // There should be one ping for the first attempted update.
939 TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) {
940 std::map<std::string, std::string> map;
941 map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
942 map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
943 map.insert(std::pair<std::string, std::string>("diffresult", "\"0\""));
944 map.insert(std::pair<std::string, std::string>("differrorcode", "\"16\""));
945 PingChecker ping_checker(map);
946 URLRequestPostInterceptor post_interceptor(&ping_checker);
947 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
949 TestInstaller installer;
951 RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer);
953 const GURL expected_update_url_1(
954 "http://localhost/upd?extra=foo"
955 "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D%26uc");
956 const GURL expected_update_url_2(
957 "http://localhost/upd?extra=foo"
958 "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
959 const GURL expected_crx_url_1(
960 "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
961 const GURL expected_crx_url_1_diff_2(
962 "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
963 const GURL expected_crx_url_2(
964 "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx");
966 interceptor.SetResponse(expected_update_url_1,
967 test_file("updatecheck_diff_reply_2.xml"));
968 interceptor.SetResponse(expected_update_url_2,
969 test_file("updatecheck_diff_reply_3.xml"));
970 interceptor.SetResponse(expected_crx_url_1,
971 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
972 interceptor.SetResponse(
973 expected_crx_url_1_diff_2,
974 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
975 interceptor.SetResponse(expected_crx_url_2,
976 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
978 test_configurator()->SetLoopCount(2);
980 component_updater()->Start();
983 // A failed differential update does not count as a failed install.
984 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
985 EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count());
987 EXPECT_EQ(1, ping_checker.NumHits()) << ping_checker.GetPings();
988 EXPECT_EQ(0, ping_checker.NumMisses()) << ping_checker.GetPings();
989 EXPECT_EQ(4, interceptor.GetHitCount());
991 component_updater()->Stop();
994 // Verify that a failed installation causes an install failure ping.
995 TEST_F(ComponentUpdaterTest, CheckFailedInstallPing) {
996 std::map<std::string, std::string> map;
997 map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
998 map.insert(std::pair<std::string, std::string>("eventresult", "\"0\""));
999 map.insert(std::pair<std::string, std::string>("errorcode", "\"9\""));
1000 map.insert(std::pair<std::string, std::string>("previousversion",
1002 map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
1003 PingChecker ping_checker(map);
1004 URLRequestPostInterceptor post_interceptor(&ping_checker);
1005 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
1007 // This test installer reports installation failure.
1008 class : public TestInstaller {
1009 virtual bool Install(const base::DictionaryValue& manifest,
1010 const base::FilePath& unpack_path) OVERRIDE {
1012 base::DeleteFile(unpack_path, true);
1018 RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
1020 // Start with 0.9, and attempt update to 1.0
1021 const GURL expected_update_url_1(
1022 "http://localhost/upd?extra=foo"
1023 "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
1025 interceptor.SetResponse(expected_update_url_1,
1026 test_file("updatecheck_reply_1.xml"));
1027 interceptor.SetResponse(GURL(expected_crx_url),
1028 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
1030 // Loop twice to issue two checks: (1) with original 0.9 version
1031 // and (2), which should retry with 0.9.
1032 test_configurator()->SetLoopCount(2);
1033 component_updater()->Start();
1036 // Loop once more, but expect no ping because a noupdate response is issued.
1037 // This is necessary to clear out the fire-and-forget ping from the previous
1039 interceptor.SetResponse(expected_update_url_1,
1040 test_file("updatecheck_reply_noupdate.xml"));
1041 test_configurator()->SetLoopCount(1);
1042 component_updater()->Start();
1045 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1046 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1048 EXPECT_EQ(2, ping_checker.NumHits()) << ping_checker.GetPings();
1049 EXPECT_EQ(0, ping_checker.NumMisses()) << ping_checker.GetPings();
1050 EXPECT_EQ(5, interceptor.GetHitCount());
1052 component_updater()->Stop();
1055 // Verify that we successfully propagate a patcher error.
1056 // ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect
1057 // patching instruction that should fail.
1058 TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) {
1059 std::map<std::string, std::string> map;
1060 map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
1061 map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
1062 map.insert(std::pair<std::string, std::string>("diffresult", "\"0\""));
1063 map.insert(std::pair<std::string, std::string>("differrorcode", "\"14\""));
1064 map.insert(std::pair<std::string, std::string>("diffextracode1", "\"305\""));
1065 PingChecker ping_checker(map);
1066 URLRequestPostInterceptor post_interceptor(&ping_checker);
1067 content::URLLocalHostRequestPrepackagedInterceptor interceptor;
1069 VersionedTestInstaller installer;
1071 RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
1073 const GURL expected_update_url_0(
1074 "http://localhost/upd?extra=foo"
1075 "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D0.0%26fp%3D%26uc");
1076 const GURL expected_update_url_1(
1077 "http://localhost/upd?extra=foo"
1078 "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D1%26uc");
1079 const GURL expected_update_url_2(
1080 "http://localhost/upd?extra=foo"
1081 "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
1082 const GURL expected_crx_url_1(
1083 "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
1084 const GURL expected_crx_url_1_diff_2(
1085 "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
1086 const GURL expected_crx_url_2(
1087 "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx");
1089 interceptor.SetResponse(expected_update_url_0,
1090 test_file("updatecheck_diff_reply_1.xml"));
1091 interceptor.SetResponse(expected_update_url_1,
1092 test_file("updatecheck_diff_reply_2.xml"));
1093 interceptor.SetResponse(expected_update_url_2,
1094 test_file("updatecheck_diff_reply_3.xml"));
1095 interceptor.SetResponse(expected_crx_url_1,
1096 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
1097 interceptor.SetResponse(
1098 expected_crx_url_1_diff_2,
1099 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx"));
1100 interceptor.SetResponse(expected_crx_url_2,
1101 test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
1103 test_configurator()->SetLoopCount(2);
1105 component_updater()->Start();
1107 component_updater()->Stop();
1108 // There may still be pings in the queue.
1109 RunThreadsUntilIdle();
1111 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1112 EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1114 EXPECT_EQ(1, ping_checker.NumHits()) << ping_checker.GetPings();
1115 EXPECT_EQ(1, ping_checker.NumMisses()) << ping_checker.GetPings();
1116 EXPECT_EQ(5, interceptor.GetHitCount());