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