component_updater_service_unittest.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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    "https"
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.
1010// This test is flaky on Android. crbug.com/329883
1011#if defined(OS_ANDROID)
1012#define MAYBE_DifferentialUpdateFails DISABLED_DifferentialUpdateFails
1013#else
1014#define MAYBE_DifferentialUpdateFails DifferentialUpdateFails
1015#endif
1016TEST_F(ComponentUpdaterTest, MAYBE_DifferentialUpdateFails) {
1017  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1018      "updatecheck"), test_file("updatecheck_diff_reply_2.xml")));
1019  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1020  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1021      "updatecheck"), test_file("updatecheck_diff_reply_3.xml")));
1022
1023  get_interceptor_->SetResponse(
1024      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"),
1025      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
1026  get_interceptor_->SetResponse(
1027      GURL("http://localhost/download/"
1028           "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"),
1029      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
1030  get_interceptor_->SetResponse(
1031      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"),
1032      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
1033
1034  TestInstaller installer;
1035  CrxComponent com;
1036  RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer);
1037
1038  test_configurator()->SetLoopCount(2);
1039  component_updater()->Start();
1040  RunThreads();
1041
1042  // A failed differential update does not count as a failed install.
1043  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1044  EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count());
1045
1046  EXPECT_EQ(3, post_interceptor_->GetHitCount())
1047      << post_interceptor_->GetRequestsAsString();
1048  EXPECT_EQ(3, post_interceptor_->GetCount())
1049      << post_interceptor_->GetRequestsAsString();
1050  EXPECT_EQ(2, get_interceptor_->GetHitCount());
1051
1052  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
1053      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">"
1054      "<updatecheck /></app>"))
1055      << post_interceptor_->GetRequestsAsString();
1056  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
1057      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1058      "version=\"1.0\" nextversion=\"2.0\">"
1059      "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"0\" "
1060      "differrorcat=\"2\" differrorcode=\"16\" nextfp=\"22\"/>"))
1061      << post_interceptor_->GetRequestsAsString();
1062  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
1063      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">"
1064      "<updatecheck /><packages><package fp=\"22\"/></packages></app>"))
1065      << post_interceptor_->GetRequestsAsString();
1066
1067  component_updater()->Stop();
1068}
1069
1070// Test is flakey on Android bots. See crbug.com/331420.
1071#if defined(OS_ANDROID)
1072#define MAYBE_CheckFailedInstallPing DISABLED_CheckFailedInstallPing
1073#else
1074#define MAYBE_CheckFailedInstallPing CheckFailedInstallPing
1075#endif
1076// Verify that a failed installation causes an install failure ping.
1077  TEST_F(ComponentUpdaterTest, MAYBE_CheckFailedInstallPing) {
1078  // This test installer reports installation failure.
1079  class : public TestInstaller {
1080    virtual bool Install(const base::DictionaryValue& manifest,
1081                         const base::FilePath& unpack_path) OVERRIDE {
1082      ++install_count_;
1083      base::DeleteFile(unpack_path, true);
1084      return false;
1085    }
1086  } installer;
1087
1088  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1089      "updatecheck"), test_file("updatecheck_reply_1.xml")));
1090  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1091  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1092      "updatecheck"), test_file("updatecheck_reply_1.xml")));
1093  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1094  get_interceptor_->SetResponse(
1095      GURL(expected_crx_url),
1096      test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
1097
1098  // Start with 0.9, and attempt update to 1.0.
1099  // Loop twice to issue two checks: (1) with original 0.9 version
1100  // and (2), which should retry with 0.9.
1101  CrxComponent com;
1102  RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
1103
1104  test_configurator()->SetLoopCount(2);
1105  component_updater()->Start();
1106  RunThreads();
1107
1108  EXPECT_EQ(4, post_interceptor_->GetHitCount())
1109      << post_interceptor_->GetRequestsAsString();
1110  EXPECT_EQ(2, get_interceptor_->GetHitCount());
1111
1112  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
1113      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1114      "<updatecheck /></app>"))
1115      << post_interceptor_->GetRequestsAsString();
1116  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
1117      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
1118      "version=\"0.9\" nextversion=\"1.0\">"
1119      "<event eventtype=\"3\" eventresult=\"0\" "
1120      "errorcat=\"3\" errorcode=\"9\"/>"))
1121      << post_interceptor_->GetRequestsAsString();
1122  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
1123      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1124      "<updatecheck /></app>"))
1125      << post_interceptor_->GetRequestsAsString();
1126  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find(
1127      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" "
1128      "version=\"0.9\" nextversion=\"1.0\">"
1129      "<event eventtype=\"3\" eventresult=\"0\" "
1130      "errorcat=\"3\" errorcode=\"9\"/>"))
1131      << post_interceptor_->GetRequestsAsString();
1132
1133  // Loop once more, but expect no ping because a noupdate response is issued.
1134  // This is necessary to clear out the fire-and-forget ping from the previous
1135  // iteration.
1136  post_interceptor_->Reset();
1137  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1138      "updatecheck"), test_file("updatecheck_reply_noupdate.xml")));
1139
1140  test_configurator()->SetLoopCount(1);
1141  component_updater()->Start();
1142  RunThreads();
1143
1144  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1145  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1146
1147  EXPECT_EQ(1, post_interceptor_->GetHitCount())
1148      << post_interceptor_->GetRequestsAsString();
1149  EXPECT_EQ(1, post_interceptor_->GetCount())
1150      << post_interceptor_->GetRequestsAsString();
1151
1152  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
1153      "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">"
1154      "<updatecheck /></app>"))
1155      << post_interceptor_->GetRequestsAsString();
1156
1157  component_updater()->Stop();
1158}
1159
1160// Verify that we successfully propagate a patcher error.
1161// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect
1162// patching instruction that should fail.
1163TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) {
1164  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1165      "updatecheck"), test_file("updatecheck_diff_reply_1.xml")));
1166  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1167  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1168      "updatecheck"), test_file("updatecheck_diff_reply_2.xml")));
1169  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event")));
1170  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1171      "updatecheck"), test_file("updatecheck_diff_reply_3.xml")));
1172
1173  get_interceptor_->SetResponse(
1174      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"),
1175      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
1176  // This intercept returns a different file than what is specified in the
1177  // update check response and requested in the download. The file that is
1178  // actually dowloaded contains a patching error, an therefore, an error
1179  // is injected at the time of patching.
1180  get_interceptor_->SetResponse(
1181      GURL("http://localhost/download/"
1182           "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"),
1183      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx"));
1184  get_interceptor_->SetResponse(
1185      GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"),
1186      test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
1187
1188  VersionedTestInstaller installer;
1189  CrxComponent com;
1190  RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
1191
1192  test_configurator()->SetLoopCount(3);
1193  component_updater()->Start();
1194  RunThreads();
1195  component_updater()->Stop();
1196
1197  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1198  EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
1199
1200  EXPECT_EQ(5, post_interceptor_->GetHitCount())
1201      << post_interceptor_->GetRequestsAsString();
1202  EXPECT_EQ(5, post_interceptor_->GetCount())
1203      << post_interceptor_->GetRequestsAsString();
1204  EXPECT_EQ(3, get_interceptor_->GetHitCount());
1205
1206  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find(
1207      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">"
1208      "<updatecheck /></app>"))
1209      << post_interceptor_->GetRequestsAsString();
1210  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find(
1211      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1212      "version=\"0.0\" nextversion=\"1.0\">"
1213      "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>"))
1214      << post_interceptor_->GetRequestsAsString();
1215  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[2].find(
1216      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">"
1217      "<updatecheck /><packages><package fp=\"1\"/></packages></app>"))
1218      << post_interceptor_->GetRequestsAsString();
1219  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find(
1220      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" "
1221      "version=\"1.0\" nextversion=\"2.0\">"
1222      "<event eventtype=\"3\" eventresult=\"1\" "
1223      "diffresult=\"0\" differrorcat=\"2\" "
1224      "differrorcode=\"14\" diffextracode1=\"305\" "
1225      "previousfp=\"1\" nextfp=\"22\"/>"))
1226      << post_interceptor_->GetRequestsAsString();
1227  EXPECT_NE(string::npos, post_interceptor_->GetRequests()[4].find(
1228      "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">"
1229      "<updatecheck /><packages><package fp=\"22\"/></packages></app>"))
1230      << post_interceptor_->GetRequestsAsString();
1231}
1232
1233class TestResourceController : public content::ResourceController {
1234 public:
1235  virtual void SetThrottle(content::ResourceThrottle* throttle) {}
1236};
1237
1238content::ResourceThrottle* RequestTestResourceThrottle(
1239    ComponentUpdateService* cus,
1240    TestResourceController* controller,
1241    const char* crx_id) {
1242
1243  net::TestURLRequestContext context;
1244  net::TestURLRequest url_request(
1245      GURL("http://foo.example.com/thing.bin"),
1246      net::DEFAULT_PRIORITY,
1247      NULL,
1248      &context);
1249
1250  content::ResourceThrottle* rt =
1251      cus->GetOnDemandResourceThrottle(&url_request, crx_id);
1252  rt->set_controller_for_testing(controller);
1253  controller->SetThrottle(rt);
1254  return rt;
1255}
1256
1257void RequestAndDeleteResourceThrottle(
1258    ComponentUpdateService* cus, const char* crx_id) {
1259  // By requesting a throttle and deleting it immediately we ensure that we
1260  // hit the case where the component updater tries to use the weak
1261  // pointer to a dead Resource throttle.
1262  class  NoCallResourceController : public TestResourceController {
1263   public:
1264    virtual ~NoCallResourceController() {}
1265    virtual void Cancel() OVERRIDE { CHECK(false); }
1266    virtual void CancelAndIgnore() OVERRIDE { CHECK(false); }
1267    virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); }
1268    virtual void Resume() OVERRIDE { CHECK(false); }
1269  } controller;
1270
1271  delete RequestTestResourceThrottle(cus, &controller, crx_id);
1272}
1273
1274TEST_F(ComponentUpdaterTest, ResourceThrottleDeletedNoUpdate) {
1275  MockComponentObserver observer;
1276  EXPECT_CALL(observer,
1277              OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
1278              .Times(1);
1279  EXPECT_CALL(observer,
1280              OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
1281              .Times(1);
1282  EXPECT_CALL(observer,
1283              OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
1284              .Times(1);
1285
1286  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1287      "updatecheck"), test_file("updatecheck_reply_1.xml")));
1288
1289  TestInstaller installer;
1290  CrxComponent com;
1291  com.observer = &observer;
1292  EXPECT_EQ(ComponentUpdateService::kOk,
1293            RegisterComponent(&com,
1294                              kTestComponent_abag,
1295                              Version("1.1"),
1296                              &installer));
1297  // The following two calls ensure that we don't do an update check via the
1298  // timer, so the only update check should be the on-demand one.
1299  test_configurator()->SetInitialDelay(1000000);
1300  test_configurator()->SetRecheckTime(1000000);
1301  test_configurator()->SetLoopCount(1);
1302  component_updater()->Start();
1303
1304  RunThreadsUntilIdle();
1305
1306  EXPECT_EQ(0, post_interceptor_->GetHitCount());
1307
1308  BrowserThread::PostTask(
1309      BrowserThread::IO,
1310      FROM_HERE,
1311      base::Bind(&RequestAndDeleteResourceThrottle,
1312                 component_updater(),
1313                 "abagagagagagagagagagagagagagagag"));
1314
1315  RunThreads();
1316
1317  EXPECT_EQ(1, post_interceptor_->GetHitCount());
1318  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1319  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
1320
1321  component_updater()->Stop();
1322}
1323
1324class  CancelResourceController: public TestResourceController {
1325  public:
1326  CancelResourceController() : throttle_(NULL), resume_called_(0) {}
1327  virtual ~CancelResourceController() {
1328    // Check that the throttle has been resumed by the time we
1329    // exit the test.
1330    CHECK(resume_called_ == 1);
1331    delete throttle_;
1332  }
1333  virtual void Cancel() OVERRIDE { CHECK(false); }
1334  virtual void CancelAndIgnore() OVERRIDE { CHECK(false); }
1335  virtual void CancelWithError(int error_code) OVERRIDE { CHECK(false); }
1336  virtual void Resume() OVERRIDE {
1337    BrowserThread::PostTask(
1338        BrowserThread::IO,
1339        FROM_HERE,
1340        base::Bind(&CancelResourceController::ResumeCalled,
1341                    base::Unretained(this)));
1342  }
1343  virtual void SetThrottle(content::ResourceThrottle* throttle) OVERRIDE {
1344    throttle_ = throttle;
1345    bool defer = false;
1346    // Initially the throttle is blocked. The CUS needs to run a
1347    // task on the UI thread to  decide if it should unblock.
1348    throttle_->WillStartRequest(&defer);
1349    CHECK(defer);
1350  }
1351
1352  private:
1353  void ResumeCalled() { ++resume_called_; }
1354
1355  content::ResourceThrottle* throttle_;
1356  int resume_called_;
1357};
1358
1359TEST_F(ComponentUpdaterTest, ResourceThrottleLiveNoUpdate) {
1360  MockComponentObserver observer;
1361  EXPECT_CALL(observer,
1362              OnEvent(ComponentObserver::COMPONENT_UPDATER_STARTED, 0))
1363              .Times(1);
1364  EXPECT_CALL(observer,
1365              OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
1366              .Times(1);
1367  EXPECT_CALL(observer,
1368              OnEvent(ComponentObserver::COMPONENT_NOT_UPDATED, 0))
1369              .Times(1);
1370
1371  EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch(
1372      "updatecheck"), test_file("updatecheck_reply_1.xml")));
1373
1374  TestInstaller installer;
1375  CrxComponent com;
1376  com.observer = &observer;
1377  EXPECT_EQ(ComponentUpdateService::kOk,
1378            RegisterComponent(&com,
1379                              kTestComponent_abag,
1380                              Version("1.1"),
1381                              &installer));
1382  // The following two calls ensure that we don't do an update check via the
1383  // timer, so the only update check should be the on-demand one.
1384  test_configurator()->SetInitialDelay(1000000);
1385  test_configurator()->SetRecheckTime(1000000);
1386  test_configurator()->SetLoopCount(1);
1387  component_updater()->Start();
1388
1389  RunThreadsUntilIdle();
1390
1391  EXPECT_EQ(0, post_interceptor_->GetHitCount());
1392
1393  CancelResourceController controller;
1394
1395  BrowserThread::PostTask(
1396      BrowserThread::IO,
1397      FROM_HERE,
1398      base::Bind(base::IgnoreResult(&RequestTestResourceThrottle),
1399                 component_updater(),
1400                 &controller,
1401                 "abagagagagagagagagagagagagagagag"));
1402
1403  RunThreads();
1404
1405  EXPECT_EQ(1, post_interceptor_->GetHitCount());
1406  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
1407  EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
1408
1409  component_updater()->Stop();
1410}
1411
1412
1413}  // namespace component_updater
1414
1415