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