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