- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / component_updater / test / component_updater_service_unittest.cc
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/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"
19 #include "url/gurl.h"
20
21 using content::BrowserThread;
22
23 using ::testing::_;
24 using ::testing::InSequence;
25 using ::testing::Mock;
26
27 MockComponentObserver::MockComponentObserver() {
28 }
29
30 MockComponentObserver::~MockComponentObserver() {
31 }
32
33 TestConfigurator::TestConfigurator()
34     : times_(1),
35       recheck_time_(0),
36       ondemand_time_(0),
37       cus_(NULL),
38       context_(new net::TestURLRequestContextGetter(
39           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) {
40 }
41
42 TestConfigurator::~TestConfigurator() {
43 }
44
45 int TestConfigurator::InitialDelay() { return 0; }
46
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
51   // finish.
52   if (--times_ <= 0) {
53     quit_closure_.Run();
54     return 0;
55   }
56   return 1;
57 }
58
59 int TestConfigurator::StepDelay() {
60   return 0;
61 }
62
63 int TestConfigurator::StepDelayMedium() {
64   return NextCheckDelay();
65 }
66
67 int TestConfigurator::MinimumReCheckWait() {
68   return recheck_time_;
69 }
70
71 int TestConfigurator::OnDemandDelay() {
72   return ondemand_time_;
73 }
74
75 GURL TestConfigurator::UpdateUrl() {
76   return GURL("http://localhost/upd");
77 }
78
79 GURL TestConfigurator::PingUrl() {
80   return GURL("http://localhost2/ping");
81 }
82
83 const char* TestConfigurator::ExtraRequestParams() { return "extra=foo"; }
84
85 size_t TestConfigurator::UrlSizeLimit() { return 256; }
86
87 net::URLRequestContextGetter* TestConfigurator::RequestContext() {
88   return context_.get();
89 }
90
91 // Don't use the utility process to decode files.
92 bool TestConfigurator::InProcess() { return true; }
93
94 ComponentPatcher* TestConfigurator::CreateComponentPatcher() {
95   return new MockComponentPatcher();
96 }
97
98 bool TestConfigurator::DeltasEnabled() const {
99   return true;
100 }
101
102 // Set how many update checks are called, the default value is just once.
103 void TestConfigurator::SetLoopCount(int times) { times_ = times; }
104
105 void TestConfigurator::SetRecheckTime(int seconds) {
106   recheck_time_ = seconds;
107 }
108
109 void TestConfigurator::SetOnDemandTime(int seconds) {
110   ondemand_time_ = seconds;
111 }
112
113 void TestConfigurator::SetComponentUpdateService(ComponentUpdateService* cus) {
114   cus_ = cus;
115 }
116
117 void TestConfigurator::SetQuitClosure(const base::Closure& quit_closure) {
118   quit_closure_ = quit_closure;
119 }
120
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());
128
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");
132
133   net::URLFetcher::SetEnableInterceptionForTests(true);
134 }
135
136 ComponentUpdaterTest::~ComponentUpdaterTest() {
137   net::URLFetcher::SetEnableInterceptionForTests(false);
138 }
139
140 void ComponentUpdaterTest::TearDown() {
141   xmlCleanupGlobals();
142 }
143
144 ComponentUpdateService* ComponentUpdaterTest::component_updater() {
145   return component_updater_.get();
146 }
147
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);
151 }
152
153 TestConfigurator* ComponentUpdaterTest::test_configurator() {
154   return test_config_;
155 }
156
157 ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent(
158     CrxComponent* com,
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));
168   } else {
169     com->name = "test_ihfo";
170     com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
171   }
172   com->version = version;
173   com->installer = installer;
174   return component_updater_->RegisterComponent(*com);
175 }
176
177 void ComponentUpdaterTest::RunThreads() {
178   base::RunLoop runloop;
179   test_configurator()->SetQuitClosure(runloop.QuitClosure());
180   runloop.Run();
181 }
182
183 void ComponentUpdaterTest::RunThreadsUntilIdle() {
184   base::RunLoop().RunUntilIdle();
185 }
186
187 PingChecker::PingChecker(const std::map<std::string, std::string>& attributes)
188     : num_hits_(0), num_misses_(0), attributes_(attributes) {
189 }
190
191 PingChecker::~PingChecker() {}
192
193 void PingChecker::Trial(net::URLRequest* request) {
194   if (Test(request))
195     ++num_hits_;
196   else
197     ++num_misses_;
198 }
199
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) {
220             return false;
221           }
222         }
223         return true;
224       }
225     }
226   }
227   return false;
228 }
229
230 std::string PingChecker::GetPings() const {
231   std::string pings_str = "Pings are:";
232   int i = 0;
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()));
236   }
237   return pings_str;
238 }
239
240 ComponentUpdateService::Status OnDemandTester::OnDemand(
241     ComponentUpdateService* cus, const std::string& component_id) {
242   return cus->OnDemandUpdate(component_id);
243 }
244
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);
249 }
250
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();
257 }
258
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
261 // are generated.
262 TEST_F(ComponentUpdaterTest, CheckCrxSleep) {
263   content::URLLocalHostRequestPrepackagedInterceptor interceptor;
264
265   MockComponentObserver observer;
266
267   TestInstaller installer;
268   CrxComponent com;
269   com.observer = &observer;
270   EXPECT_EQ(ComponentUpdateService::kOk,
271             RegisterComponent(&com,
272                               kTestComponent_abag,
273                               Version("1.1"),
274                               &installer));
275
276   const GURL expected_update_url(
277       "http://localhost/upd?extra=foo"
278       "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D1.1%26fp%3D%26uc");
279
280   interceptor.SetResponse(expected_update_url,
281                           test_file("updatecheck_reply_1.xml"));
282
283   // We loop twice, but there are no updates so we expect two sleep messages.
284   test_configurator()->SetLoopCount(2);
285
286   EXPECT_CALL(observer,
287               OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
288               .Times(1);
289   component_updater()->Start();
290
291   EXPECT_CALL(observer,
292               OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
293               .Times(2);
294
295   EXPECT_CALL(observer,
296               OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
297               .Times(2);
298   RunThreads();
299
300   EXPECT_EQ(2, interceptor.GetHitCount());
301
302   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
303   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
304
305   component_updater()->Stop();
306
307   // Loop twice again but this case we simulate a server error by returning
308   // an empty file.
309
310   interceptor.SetResponse(expected_update_url,
311                           test_file("updatecheck_reply_empty"));
312
313   test_configurator()->SetLoopCount(2);
314
315   EXPECT_CALL(observer,
316               OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
317               .Times(1);
318   component_updater()->Start();
319
320   EXPECT_CALL(observer,
321               OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
322               .Times(2);
323   EXPECT_CALL(observer,
324               OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
325               .Times(2);
326   RunThreads();
327
328   EXPECT_EQ(4, interceptor.GetHitCount());
329
330   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
331   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
332
333   component_updater()->Stop();
334 }
335
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:
341 // 1- manifest check
342 // 2- download crx
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",
349                                                  "\"0.9\""));
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;
354
355   MockComponentObserver observer1;
356   {
357     InSequence seq;
358     EXPECT_CALL(observer1,
359                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
360                 .Times(1);
361     EXPECT_CALL(observer1,
362                 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
363                 .Times(1);
364     EXPECT_CALL(observer1,
365                 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
366                 .Times(1);
367     EXPECT_CALL(observer1,
368                 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
369                 .Times(1);
370     EXPECT_CALL(observer1,
371                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
372                 .Times(1);
373     EXPECT_CALL(observer1,
374                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
375                 .Times(1);
376     EXPECT_CALL(observer1,
377                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
378                 .Times(1);
379   }
380
381   MockComponentObserver observer2;
382   {
383     InSequence seq;
384     EXPECT_CALL(observer2,
385                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
386                 .Times(1);
387     EXPECT_CALL(observer2,
388                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
389                 .Times(1);
390     EXPECT_CALL(observer2,
391                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
392                 .Times(1);
393     EXPECT_CALL(observer2,
394                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
395                 .Times(1);
396     EXPECT_CALL(observer2,
397                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
398                 .Times(1);
399   }
400
401   TestInstaller installer1;
402   CrxComponent com1;
403   com1.observer = &observer1;
404   RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
405   TestInstaller installer2;
406   CrxComponent com2;
407   com2.observer = &observer2;
408   RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
409
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");
414
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");
419
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"));
426
427   test_configurator()->SetLoopCount(2);
428
429   component_updater()->Start();
430   RunThreads();
431
432   EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
433   EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
434   EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
435   EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
436
437   EXPECT_EQ(3, interceptor.GetHitCount());
438   EXPECT_EQ(1, ping_checker.NumHits()) << ping_checker.GetPings();
439   EXPECT_EQ(0, ping_checker.NumMisses()) << ping_checker.GetPings();
440
441   component_updater()->Stop();
442 }
443
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;
452
453   TestInstaller installer;
454   CrxComponent com;
455   RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
456
457   const GURL expected_update_url(
458       "http://localhost/upd?extra=foo&x=id%3D"
459       "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
460
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"));
465
466   test_configurator()->SetLoopCount(1);
467   component_updater()->Start();
468   RunThreads();
469
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());
475
476   component_updater()->Stop();
477 }
478
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
482 //    nothing happens.
483 //  - We ping.
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",
490                                                  "\"0.9\""));
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;
495
496   MockComponentObserver observer1;
497   {
498     InSequence seq;
499     EXPECT_CALL(observer1,
500                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
501                 .Times(1);
502     EXPECT_CALL(observer1,
503                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
504                 .Times(1);
505     EXPECT_CALL(observer1,
506                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
507                 .Times(1);
508     EXPECT_CALL(observer1,
509                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
510                 .Times(1);
511     EXPECT_CALL(observer1,
512                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
513                 .Times(1);
514     EXPECT_CALL(observer1,
515                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
516                 .Times(1);
517   }
518
519   MockComponentObserver observer2;
520   {
521     InSequence seq;
522     EXPECT_CALL(observer2,
523                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
524                 .Times(1);
525     EXPECT_CALL(observer2,
526                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
527                 .Times(1);
528     EXPECT_CALL(observer2,
529                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
530                 .Times(1);
531     EXPECT_CALL(observer2,
532                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
533                 .Times(1);
534     EXPECT_CALL(observer2,
535                 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
536                 .Times(1);
537     EXPECT_CALL(observer2,
538                 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
539                 .Times(1);
540     EXPECT_CALL(observer2,
541                 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
542                 .Times(1);
543     EXPECT_CALL(observer2,
544                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
545                 .Times(1);
546   }
547
548   TestInstaller installer1;
549   CrxComponent com1;
550   com1.observer = &observer1;
551   RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1);
552   TestInstaller installer2;
553   CrxComponent com2;
554   com2.observer = &observer2;
555   RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2);
556
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");
561
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");
567
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();
577   RunThreads();
578   component_updater()->Stop();
579
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();
586   RunThreads();
587
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());
592
593   EXPECT_EQ(3, interceptor.GetHitCount());
594
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();
603
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));
607   {
608     InSequence seq;
609     EXPECT_CALL(observer1,
610                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
611                 .Times(1);
612     EXPECT_CALL(observer1,
613                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
614                 .Times(1);
615     EXPECT_CALL(observer1,
616                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
617                 .Times(1);
618   }
619   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
620   {
621     InSequence seq;
622     EXPECT_CALL(observer2,
623                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
624                 .Times(1);
625     EXPECT_CALL(observer2,
626                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
627                 .Times(1);
628     EXPECT_CALL(observer2,
629                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
630                 .Times(1);
631   }
632
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");
637
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)));
646
647   RunThreads();
648
649   component_updater()->Stop();
650
651   // No update: already updated to 1.0 so nothing new
652   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
653   {
654     InSequence seq;
655     EXPECT_CALL(observer1,
656                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
657                 .Times(1);
658     EXPECT_CALL(observer1,
659                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
660                 .Times(1);
661     EXPECT_CALL(observer1,
662                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
663                 .Times(1);
664   }
665   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
666   {
667     InSequence seq;
668     EXPECT_CALL(observer2,
669                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
670                 .Times(1);
671     EXPECT_CALL(observer2,
672                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
673                 .Times(1);
674     EXPECT_CALL(observer2,
675                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
676                 .Times(1);
677   }
678
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)));
686
687   RunThreads();
688
689   EXPECT_EQ(1, ping_checker.NumHits()) << ping_checker.GetPings();
690   EXPECT_EQ(0, ping_checker.NumMisses()) << ping_checker.GetPings();
691
692   component_updater()->Stop();
693 }
694
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",
702                                                  "\"0.9\""));
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;
707
708   MockComponentObserver observer1;
709   {
710     InSequence seq;
711     EXPECT_CALL(observer1,
712                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
713                 .Times(1);
714     EXPECT_CALL(observer1,
715                 OnEvent(ComponentObserver::COMPONENT_UPDATE_FOUND, 0))
716                 .Times(1);
717     EXPECT_CALL(observer1,
718                 OnEvent(ComponentObserver::COMPONENT_UPDATE_READY, 0))
719                 .Times(1);
720     EXPECT_CALL(observer1,
721                 OnEvent(ComponentObserver::COMPONENT_UPDATED, 0))
722                 .Times(1);
723     EXPECT_CALL(observer1,
724                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
725                 .Times(1);
726     EXPECT_CALL(observer1,
727                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
728                 .Times(1);
729     EXPECT_CALL(observer1,
730                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
731                 .Times(1);
732   }
733
734   MockComponentObserver observer2;
735   {
736     InSequence seq;
737     EXPECT_CALL(observer2,
738                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
739                 .Times(1);
740     EXPECT_CALL(observer2,
741                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
742                 .Times(1);
743     EXPECT_CALL(observer2,
744                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
745                 .Times(1);
746     EXPECT_CALL(observer2,
747                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
748                 .Times(1);
749     EXPECT_CALL(observer2,
750                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
751                 .Times(1);
752   }
753
754   TestInstaller installer1;
755   CrxComponent com1;
756   com1.observer = &observer1;
757   RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
758   TestInstaller installer2;
759   CrxComponent com2;
760   com2.observer = &observer2;
761   RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
762
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");
768
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");
773
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"));
780
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);
784
785   component_updater()->Start();
786   RunThreads();
787
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());
792
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());
796
797   component_updater()->Stop();
798
799   // Now re-register, pretending to be an even newer version (2.2)
800   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1));
801   {
802     InSequence seq;
803     EXPECT_CALL(observer1,
804                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
805                 .Times(1);
806     EXPECT_CALL(observer1,
807                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
808                 .Times(1);
809     EXPECT_CALL(observer1,
810                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
811                 .Times(1);
812   }
813
814   EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2));
815   {
816     InSequence seq;
817     EXPECT_CALL(observer2,
818                 OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
819                 .Times(1);
820     EXPECT_CALL(observer2,
821                 OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
822                 .Times(1);
823     EXPECT_CALL(observer2,
824                 OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
825                 .Times(1);
826   }
827
828   TestInstaller installer3;
829   EXPECT_EQ(ComponentUpdateService::kReplaced,
830             RegisterComponent(&com1,
831                               kTestComponent_jebg,
832                               Version("2.2"),
833                               &installer3));
834
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");
841
842   interceptor.SetResponse(expected_update_url_3,
843                           test_file("updatecheck_reply_1.xml"));
844
845   // Loop once just to notice the check happening with the re-register version.
846   test_configurator()->SetLoopCount(1);
847   component_updater()->Start();
848   RunThreads();
849
850   EXPECT_EQ(4, interceptor.GetHitCount());
851
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());
857
858   component_updater()->Stop();
859 }
860
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
863 // nothing.
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;
880
881   VersionedTestInstaller installer;
882   CrxComponent com;
883   RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
884
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");
898
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"));
910
911   test_configurator()->SetLoopCount(3);
912
913   component_updater()->Start();
914   RunThreads();
915
916   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
917   EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
918
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();
922
923   EXPECT_EQ(5, interceptor.GetHitCount());
924
925   component_updater()->Stop();
926 }
927
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.
938
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;
948
949   TestInstaller installer;
950   CrxComponent com;
951   RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer);
952
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");
965
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"));
977
978   test_configurator()->SetLoopCount(2);
979
980   component_updater()->Start();
981   RunThreads();
982
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());
986
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());
990
991   component_updater()->Stop();
992 }
993
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",
1001                                                  "\"0.9\""));
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;
1006
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 {
1011       ++install_count_;
1012       base::DeleteFile(unpack_path, true);
1013       return false;
1014     }
1015   } installer;
1016
1017   CrxComponent com;
1018   RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
1019
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");
1024
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"));
1029
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();
1034   RunThreads();
1035
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
1038   // iteration.
1039   interceptor.SetResponse(expected_update_url_1,
1040                           test_file("updatecheck_reply_noupdate.xml"));
1041   test_configurator()->SetLoopCount(1);
1042   component_updater()->Start();
1043   RunThreads();
1044
1045   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1046   EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1047
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());
1051
1052   component_updater()->Stop();
1053 }
1054
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;
1068
1069   VersionedTestInstaller installer;
1070   CrxComponent com;
1071   RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
1072
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");
1088
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"));
1102
1103   test_configurator()->SetLoopCount(2);
1104
1105   component_updater()->Start();
1106   RunThreads();
1107   component_updater()->Stop();
1108   // There may still be pings in the queue.
1109   RunThreadsUntilIdle();
1110
1111   EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1112   EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1113
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());
1117 }