Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Unified Diff: chrome/browser/component_updater/test/component_updater_service_unittest.cc

Issue 15908002: Differential updates for components. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Addressed most of the feedback so far. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/component_updater/test/component_updater_service_unittest.cc
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.cc b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
index 080b1d28c43ff8b1028384ef90934da81e286968..1771a6c866463974a5794b81fe105636c1c4a0af 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/component_updater/component_updater_service.h"
-
#include <list>
#include <utility>
@@ -13,7 +11,12 @@
#include "base/memory/scoped_vector.h"
#include "base/message_loop.h"
#include "base/path_service.h"
+#include "base/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
#include "base/values.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/test/component_patcher_mock.h"
+#include "chrome/browser/component_updater/test/test_installer.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/browser/notification_observer.h"
@@ -23,7 +26,11 @@
#include "content/test/net/url_request_prepackaged_interceptor.h"
#include "googleurl/src/gurl.h"
#include "libxml/globals.h"
+#include "net/base/upload_bytes_element_reader.h"
#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_filter.h"
+#include "net/url_request/url_request_simple_job.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -31,98 +38,72 @@ using content::BrowserThread;
using content::TestNotificationTracker;
namespace {
-// Overrides some of the component updater behaviors so it is easier to test
-// and loops faster. In actual usage it takes hours do to a full cycle.
+
+// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and
+// the RSA public key the following hash:
+const uint8 jebg_hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec,
+ 0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5,
+ 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4,
+ 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40};
+// component 2 has extension id "abagagagagagagagagagagagagagagag", and
+// the RSA public key the following hash:
+const uint8 abag_hash[] = {0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01};
+// component 3 has extension id "ihfokbkgjpifnbbojhneepfflplebdkc", and
+// the RSA public key the following hash:
+const uint8 ihfo_hash[] = {0x87, 0x5e, 0xa1, 0xa6, 0x9f, 0x85, 0xd1, 0x1e,
+ 0x97, 0xd4, 0x4f, 0x55, 0xbf, 0xb4, 0x13, 0xa2,
+ 0xe7, 0xc5, 0xc8, 0xf5, 0x60, 0x19, 0x78, 0x1b,
+ 0x6d, 0xe9, 0x4c, 0xeb, 0x96, 0x05, 0x42, 0x17};
+
class TestConfigurator : public ComponentUpdateService::Configurator {
public:
- TestConfigurator()
- : times_(1), recheck_time_(0), ondemand_time_(0), cus_(NULL) {
- }
+ TestConfigurator();
- virtual int InitialDelay() OVERRIDE { return 0; }
+ virtual int InitialDelay() OVERRIDE;
typedef std::pair<CrxComponent*, int> CheckAtLoopCount;
- virtual int NextCheckDelay() OVERRIDE {
- // This is called when a new full cycle of checking for updates is going
- // to happen. In test we normally only test one cycle so it is a good
- // time to break from the test messageloop Run() method so the test can
- // finish.
- if (--times_ <= 0) {
- base::MessageLoop::current()->Quit();
- return 0;
+ virtual int NextCheckDelay() OVERRIDE;
- }
+ virtual int StepDelay() OVERRIDE;
- // Look for checks to issue in the middle of the loop.
- for (std::list<CheckAtLoopCount>::iterator
- i = components_to_check_.begin();
- i != components_to_check_.end(); ) {
- if (i->second == times_) {
- cus_->CheckForUpdateSoon(*i->first);
- i = components_to_check_.erase(i);
- } else {
- ++i;
- }
- }
- return 1;
- }
+ virtual int MinimumReCheckWait() OVERRIDE;
- virtual int StepDelay() OVERRIDE {
- return 0;
- }
+ virtual int OnDemandDelay() OVERRIDE;
- virtual int MinimumReCheckWait() OVERRIDE {
- return recheck_time_;
- }
+ virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE;
- virtual int OnDemandDelay() OVERRIDE {
- return ondemand_time_;
- }
+ virtual GURL PingUrl() OVERRIDE;
- virtual GURL UpdateUrl(CrxComponent::UrlSource source) OVERRIDE {
- switch (source) {
- case CrxComponent::BANDAID:
- return GURL("http://localhost/upd");
- case CrxComponent::CWS_PUBLIC:
- return GURL("http://localhost/cws");
- default:
- return GURL("http://wronghost/bad");
- };
- }
+ virtual const char* ExtraRequestParams() OVERRIDE;
- virtual const char* ExtraRequestParams() OVERRIDE { return "extra=foo"; }
+ virtual size_t UrlSizeLimit() OVERRIDE;
- virtual size_t UrlSizeLimit() OVERRIDE { return 256; }
-
- virtual net::URLRequestContextGetter* RequestContext() OVERRIDE {
- return new net::TestURLRequestContextGetter(
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
- }
+ virtual net::URLRequestContextGetter* RequestContext() OVERRIDE;
// Don't use the utility process to decode files.
- virtual bool InProcess() OVERRIDE { return true; }
+ virtual bool InProcess() OVERRIDE;
- virtual void OnEvent(Events event, int extra) OVERRIDE { }
+ virtual void OnEvent(Events event, int extra) OVERRIDE;
- // Set how many update checks are called, the default value is just once.
- void SetLoopCount(int times) { times_ = times; }
+ virtual ComponentPatcher* CreateComponentPatcher() OVERRIDE;
- void SetRecheckTime(int seconds) {
- recheck_time_ = seconds;
- }
+ virtual bool PingsEnabled() const OVERRIDE;
- void SetOnDemandTime(int seconds) {
- ondemand_time_ = seconds;
- }
+ virtual bool DeltasEnabled() const OVERRIDE;
- void AddComponentToCheck(CrxComponent* com, int at_loop_iter) {
- components_to_check_.push_back(std::make_pair(com, at_loop_iter));
- }
+ void SetLoopCount(int times);
- void SetComponentUpdateService(ComponentUpdateService* cus) {
- cus_ = cus;
- }
+ void SetRecheckTime(int seconds);
+
+ void SetOnDemandTime(int seconds);
+
+ void AddComponentToCheck(CrxComponent* com, int at_loop_iter);
+
+ void SetComponentUpdateService(ComponentUpdateService* cus);
private:
int times_;
@@ -133,132 +114,387 @@ class TestConfigurator : public ComponentUpdateService::Configurator {
ComponentUpdateService* cus_;
};
-class TestInstaller : public ComponentInstaller {
- public :
- explicit TestInstaller()
- : error_(0), install_count_(0) {
- }
+class ComponentUpdaterTest : public testing::Test {
+ public:
+ enum TestComponents {
+ kTestComponent_abag,
+ kTestComponent_jebg,
+ kTestComponent_ihfo,
+ };
- virtual void OnUpdateError(int error) OVERRIDE {
- EXPECT_NE(0, error);
- error_ = error;
- }
+ ComponentUpdaterTest();
- virtual bool Install(const base::DictionaryValue& manifest,
- const base::FilePath& unpack_path) OVERRIDE {
- ++install_count_;
- return file_util::Delete(unpack_path, true);
- }
+ virtual ~ComponentUpdaterTest();
+
+ virtual void TearDown();
+
+ ComponentUpdateService* component_updater();
- int error() const { return error_; }
+ // Makes the full path to a component updater test file.
+ const base::FilePath test_file(const char* file);
+
+ TestNotificationTracker& notification_tracker();
+
+ TestConfigurator* test_configurator();
- int install_count() const { return install_count_; }
+ ComponentUpdateService::Status RegisterComponent(CrxComponent* com,
+ TestComponents component,
+ const Version& version,
+ TestInstaller* installer);
private:
- int error_;
- int install_count_;
+ scoped_ptr<ComponentUpdateService> component_updater_;
+ base::FilePath test_data_dir_;
+ TestNotificationTracker notification_tracker_;
+ TestConfigurator* test_config_;
};
-// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and
-// the RSA public key the following hash:
-const uint8 jebg_hash[] = {0x94,0x16,0x0b,0x6d,0x41,0x75,0xe9,0xec,0x8e,0xd5,
- 0xfa,0x54,0xb0,0xd2,0xdd,0xa5,0x6e,0x05,0x6b,0xe8,
- 0x73,0x47,0xf6,0xc4,0x11,0x9f,0xbc,0xb3,0x09,0xb3,
- 0x5b,0x40};
-// component 2 has extension id "abagagagagagagagagagagagagagagag", and
-// the RSA public key the following hash:
-const uint8 abag_hash[] = {0x01,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
- 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
- 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
- 0x06,0x01};
-
const char expected_crx_url[] =
"http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx";
-} // namespace
-
-// Common fixture for all the component updater tests.
-class ComponentUpdaterTest : public testing::Test {
+class PingChecker {
public:
- enum TestComponents {
- kTestComponent_abag,
- kTestComponent_jebg
- };
+ explicit PingChecker(const std::map<std::string, std::string>& attributes);
- ComponentUpdaterTest() : test_config_(NULL) {
- // The component updater instance under test.
- test_config_ = new TestConfigurator;
- component_updater_.reset(ComponentUpdateServiceFactory(test_config_));
- test_config_->SetComponentUpdateService(component_updater_.get());
- // The test directory is chrome/test/data/components.
- PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
- test_data_dir_ = test_data_dir_.AppendASCII("components");
-
- // Subscribe to all component updater notifications.
- const int notifications[] = {
- chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
- chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
- chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
- chrome::NOTIFICATION_COMPONENT_UPDATE_READY
- };
-
- for (int ix = 0; ix != arraysize(notifications); ++ix) {
- notification_tracker_.ListenFor(
- notifications[ix], content::NotificationService::AllSources());
- }
- net::URLFetcher::SetEnableInterceptionForTests(true);
- }
+ virtual ~PingChecker();
- virtual ~ComponentUpdaterTest() {
- net::URLFetcher::SetEnableInterceptionForTests(false);
- }
+ void Trial(net::URLRequest* request);
- virtual void TearDown() {
- xmlCleanupGlobals();
+ int NumHits() const {
+ return num_hits_;
}
-
- ComponentUpdateService* component_updater() {
- return component_updater_.get();
+ int NumMisses() const {
+ return num_misses_;
}
- // Makes the full path to a component updater test file.
- const base::FilePath test_file(const char* file) {
- return test_data_dir_.AppendASCII(file);
+ private:
+ int num_hits_;
+ int num_misses_;
+ const std::map<std::string, std::string> attributes_;
+ virtual bool Test(net::URLRequest* request);
+};
+
+PingChecker::PingChecker(const std::map<std::string, std::string>& attributes)
+ : num_hits_(0), num_misses_(0), attributes_(attributes) {
+}
+
+PingChecker::~PingChecker() {}
+
+void PingChecker::Trial(net::URLRequest* request) {
+ if (Test(request))
+ ++num_hits_;
+ else
+ ++num_misses_;
+}
+
+bool PingChecker::Test(net::URLRequest* request) {
+ if (request->has_upload()) {
+ const net::UploadDataStream* stream = request->get_upload();
+ const net::UploadBytesElementReader* reader =
+ stream->element_readers()[0]->AsBytesReader();
+ int size = reader->length();
+ scoped_refptr <net::IOBuffer> buffer = new net::IOBuffer(size);
+ std::string data(reader->bytes());
+ // For now, we assume that there is only one ping per POST.
+ std::string::size_type start = data.find("<o:event");
+ if (start != std::string::npos) {
+ std::string::size_type end = data.find(">", start);
+ if (end != std::string::npos) {
+ std::string ping = data.substr(start, end - start);
+ std::map<std::string, std::string>::const_iterator iter;
+ for (iter = attributes_.begin(); iter != attributes_.end(); ++iter) {
+ // does the ping contain the specified attribute/value?
+ if (ping.find(std::string(" ") + (iter->first) +
+ std::string("=") + (iter->second)) == string::npos) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
}
+ return false;
+}
+
+class URLRequestPostInterceptor {
+ public:
+ explicit URLRequestPostInterceptor(PingChecker* counter);
+ virtual ~URLRequestPostInterceptor();
+
+ private:
+ class Delegate;
+
+ // After creation, |delegate_| lives on the IO thread, and a task to delete it
+ // is posted from ~URLRequestPostInterceptor().
+ Delegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestPostInterceptor);
+};
+
+class URLRequestPostInterceptor::Delegate
+ : public net::URLRequestJobFactory::ProtocolHandler {
+ public:
+ explicit Delegate(PingChecker* counter);
+ virtual ~Delegate() {}
+
+ void Register();
+
+ void Unregister();
+
+ private:
+ PingChecker* counter_;
- TestNotificationTracker& notification_tracker() {
- return notification_tracker_;
+ virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE;
+};
+
+class URLRequestPingMockJob : public net::URLRequestSimpleJob {
+ public:
+ URLRequestPingMockJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate);
+
+ protected:
+ virtual int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data,
+ const net::CompletionCallback& callback) const OVERRIDE;
+
+ private:
+ virtual ~URLRequestPingMockJob() {}
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestPingMockJob);
+};
+
+URLRequestPostInterceptor::URLRequestPostInterceptor(
+ PingChecker* counter) : delegate_(new Delegate(counter)) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&Delegate::Register,
+ base::Unretained(delegate_)));
+}
+
+URLRequestPostInterceptor::~URLRequestPostInterceptor() {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&Delegate::Unregister,
+ base::Unretained(delegate_)));
+}
+
+URLRequestPostInterceptor::Delegate::Delegate(
+ PingChecker* counter) : counter_(counter) {
+}
+
+void URLRequestPostInterceptor::Delegate::Register() {
+ net::URLRequestFilter::GetInstance()->AddHostnameProtocolHandler(
+ "http", "localhost2",
+ scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(this));
+}
+
+void URLRequestPostInterceptor::Delegate::Unregister() {
+ net::URLRequestFilter::GetInstance()->
+ RemoveHostnameHandler("http", "localhost2");
+}
+
+net::URLRequestJob* URLRequestPostInterceptor::Delegate::MaybeCreateJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (request->has_upload()) {
+ counter_->Trial(request);
+ return new URLRequestPingMockJob(request, network_delegate);
}
+ return NULL;
+}
+
+URLRequestPingMockJob::URLRequestPingMockJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate)
+ : net::URLRequestSimpleJob(request, network_delegate) {
+}
+
+int URLRequestPingMockJob::GetData(
+ std::string* mime_type,
+ std::string* charset,
+ std::string* data,
+ const net::CompletionCallback& callback) const {
+ mime_type->assign("text/plain");
+ charset->assign("US-ASCII");
+ data->assign(""); // There is no reason to have a response body in this test.
+ return net::OK;
+}
+
+} // namespace
+
+TestConfigurator::TestConfigurator()
+ : times_(1), recheck_time_(0), ondemand_time_(0), cus_(NULL) {
+}
+
+int TestConfigurator::InitialDelay() { return 0; }
- TestConfigurator* test_configurator() {
- return test_config_;
+int TestConfigurator::NextCheckDelay() {
+ // This is called when a new full cycle of checking for updates is going
+ // to happen. In test we normally only test one cycle so it is a good
+ // time to break from the test messageloop Run() method so the test can
+ // finish.
+ if (--times_ <= 0) {
+ base::MessageLoop::current()->Quit();
+ return 0;
}
- ComponentUpdateService::Status RegisterComponent(CrxComponent* com,
- TestComponents component,
- const Version& version) {
- if (component == kTestComponent_abag) {
- com->name = "test_abag";
- com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
+ // Look for checks to issue in the middle of the loop.
+ for (std::list<CheckAtLoopCount>::iterator
+ i = components_to_check_.begin();
+ i != components_to_check_.end(); ) {
+ if (i->second == times_) {
+ cus_->CheckForUpdateSoon(*i->first);
+ i = components_to_check_.erase(i);
} else {
- com->name = "test_jebg";
- com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
+ ++i;
}
- com->version = version;
- TestInstaller* installer = new TestInstaller;
- com->installer = installer;
- test_installers_.push_back(installer);
- return component_updater_->RegisterComponent(*com);
}
+ return 1;
+}
- private:
- scoped_ptr<ComponentUpdateService> component_updater_;
- base::FilePath test_data_dir_;
- TestNotificationTracker notification_tracker_;
- TestConfigurator* test_config_;
- // ComponentInstaller objects to delete after each test.
- ScopedVector<TestInstaller> test_installers_;
-};
+int TestConfigurator::StepDelay() {
+ return 0;
+}
+
+int TestConfigurator::MinimumReCheckWait() {
+ return recheck_time_;
+}
+
+int TestConfigurator::OnDemandDelay() {
+ return ondemand_time_;
+}
+
+GURL TestConfigurator::UpdateUrl(CrxComponent::UrlSource source) {
+ switch (source) {
+ case CrxComponent::BANDAID:
+ return GURL("http://localhost/upd");
+ case CrxComponent::CWS_PUBLIC:
+ return GURL("http://localhost/cws");
+ default:
+ return GURL("http://wronghost/bad");
+ };
+}
+
+GURL TestConfigurator::PingUrl() {
+ return GURL("http://localhost2/ping");
+}
+
+const char* TestConfigurator::ExtraRequestParams() { return "extra=foo"; }
+
+size_t TestConfigurator::UrlSizeLimit() { return 256; }
+
+net::URLRequestContextGetter* TestConfigurator::RequestContext() {
+ return new net::TestURLRequestContextGetter(
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
+}
+
+// Don't use the utility process to decode files.
+bool TestConfigurator::InProcess() { return true; }
+
+void TestConfigurator::OnEvent(Events event, int extra) { }
+
+ComponentPatcher* TestConfigurator::CreateComponentPatcher() {
+ return new MockComponentPatcher();
+}
+
+bool TestConfigurator::PingsEnabled() const {
+ return true;
+}
+
+bool TestConfigurator::DeltasEnabled() const {
+ return true;
+}
+
+// Set how many update checks are called, the default value is just once.
+void TestConfigurator::SetLoopCount(int times) { times_ = times; }
+
+void TestConfigurator::SetRecheckTime(int seconds) {
+ recheck_time_ = seconds;
+}
+
+void TestConfigurator::SetOnDemandTime(int seconds) {
+ ondemand_time_ = seconds;
+}
+
+void TestConfigurator::AddComponentToCheck(CrxComponent* com,
+ int at_loop_iter) {
+ components_to_check_.push_back(std::make_pair(com, at_loop_iter));
+}
+
+void TestConfigurator::SetComponentUpdateService(ComponentUpdateService* cus) {
+ cus_ = cus;
+}
+
+ComponentUpdaterTest::ComponentUpdaterTest() : test_config_(NULL) {
+ // The component updater instance under test.
+ test_config_ = new TestConfigurator;
+ component_updater_.reset(ComponentUpdateServiceFactory(test_config_));
+ test_config_->SetComponentUpdateService(component_updater_.get());
+ // The test directory is chrome/test/data/components.
+ PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
+ test_data_dir_ = test_data_dir_.AppendASCII("components");
+
+ // Subscribe to all component updater notifications.
+ const int notifications[] = {
+ chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
+ chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
+ chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
+ chrome::NOTIFICATION_COMPONENT_UPDATE_READY
+ };
+
+ for (int ix = 0; ix != arraysize(notifications); ++ix) {
+ notification_tracker_.ListenFor(
+ notifications[ix], content::NotificationService::AllSources());
+ }
+ net::URLFetcher::SetEnableInterceptionForTests(true);
+}
+
+ComponentUpdaterTest::~ComponentUpdaterTest() {
+ net::URLFetcher::SetEnableInterceptionForTests(false);
+}
+
+void ComponentUpdaterTest::TearDown() {
+ xmlCleanupGlobals();
+}
+
+ComponentUpdateService* ComponentUpdaterTest::component_updater() {
+ return component_updater_.get();
+}
+
+ // Makes the full path to a component updater test file.
+const base::FilePath ComponentUpdaterTest::test_file(const char* file) {
+ return test_data_dir_.AppendASCII(file);
+}
+
+TestNotificationTracker& ComponentUpdaterTest::notification_tracker() {
+ return notification_tracker_;
+}
+
+TestConfigurator* ComponentUpdaterTest::test_configurator() {
+ return test_config_;
+}
+
+ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent(
+ CrxComponent* com,
+ TestComponents component,
+ const Version& version,
+ TestInstaller* installer) {
+ if (component == kTestComponent_abag) {
+ com->name = "test_abag";
+ com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
+ } else if (component == kTestComponent_jebg) {
+ com->name = "test_jebg";
+ com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
+ } else {
+ com->name = "test_ihfo";
+ com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash));
+ }
+ com->version = version;
+ com->installer = installer;
+ return component_updater_->RegisterComponent(*com);
+}
// Verify that our test fixture work and the component updater can
// be created and destroyed with no side effects.
@@ -295,13 +531,17 @@ TEST_F(ComponentUpdaterTest, CheckCrxSleep) {
content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+ TestInstaller installer;
CrxComponent com;
EXPECT_EQ(ComponentUpdateService::kOk,
- RegisterComponent(&com, kTestComponent_abag, Version("1.1")));
+ RegisterComponent(&com,
+ kTestComponent_abag,
+ Version("1.1"),
+ &installer));
const GURL expected_update_url(
- "http://localhost/upd?extra=foo&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D1.1%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D1.1%26fp%3D%26uc");
interceptor.SetResponse(expected_update_url,
test_file("updatecheck_reply_1.xml"));
@@ -359,7 +599,7 @@ TEST_F(ComponentUpdaterTest, CheckCrxSleep) {
// the notifications above NOTIFICATION_COMPONENT_UPDATE_FOUND and
// NOTIFICATION_COMPONENT_UPDATE_READY should have been fired. We do two loops
// so the second time around there should be nothing left to do.
-// We also check that only 3 network requests are issued:
+// We also check that only 3 non-ping network requests are issued:
// 1- manifest check
// 2- download crx
// 3- second manifest check.
@@ -372,22 +612,32 @@ TEST_F(ComponentUpdaterTest, InstallCrx) {
io_thread.StartIOThread();
file_thread.Start();
+ std::map<std::string, std::string> map;
+ map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
+ map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
+ map.insert(std::pair<std::string, std::string>("previousversion",
+ "\"0.9\""));
+ map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+ TestInstaller installer1;
CrxComponent com1;
- RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"));
+ RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
+ TestInstaller installer2;
CrxComponent com2;
- RegisterComponent(&com2, kTestComponent_abag, Version("2.2"));
+ RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
const GURL expected_update_url_1(
- "http://localhost/upd?extra=foo&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
const GURL expected_update_url_2(
- "http://localhost/upd?extra=foo&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc");
interceptor.SetResponse(expected_update_url_1,
test_file("updatecheck_reply_1.xml"));
@@ -407,6 +657,8 @@ TEST_F(ComponentUpdaterTest, InstallCrx) {
EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
EXPECT_EQ(3, interceptor.GetHitCount());
+ EXPECT_EQ(1, ping_checker.NumHits());
+ EXPECT_EQ(0, ping_checker.NumMisses());
ASSERT_EQ(5ul, notification_tracker().size());
@@ -437,21 +689,31 @@ TEST_F(ComponentUpdaterTest, InstallCrxTwoSources) {
io_thread.StartIOThread();
file_thread.Start();
+ std::map<std::string, std::string> map;
+ map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
+ map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
+ map.insert(std::pair<std::string, std::string>("previousversion",
+ "\"0.9\""));
+ map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+ TestInstaller installer1;
CrxComponent com1;
- RegisterComponent(&com1, kTestComponent_abag, Version("2.2"));
+ RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1);
+ TestInstaller installer2;
CrxComponent com2;
com2.source = CrxComponent::CWS_PUBLIC;
- RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"));
+ RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2);
const GURL expected_update_url_1(
"http://localhost/upd?extra=foo&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+ "abagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
const GURL expected_update_url_2(
"http://localhost/cws?extra=foo&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc");
+ "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
interceptor.SetResponse(expected_update_url_1,
test_file("updatecheck_reply_3.xml"));
@@ -475,6 +737,8 @@ TEST_F(ComponentUpdaterTest, InstallCrxTwoSources) {
EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
EXPECT_EQ(1, static_cast<TestInstaller*>(com2.installer)->install_count());
+ EXPECT_EQ(1, ping_checker.NumHits());
+ EXPECT_EQ(0, ping_checker.NumMisses());
EXPECT_EQ(3, interceptor.GetHitCount());
ASSERT_EQ(6ul, notification_tracker().size());
@@ -509,14 +773,18 @@ TEST_F(ComponentUpdaterTest, ProdVersionCheck) {
io_thread.StartIOThread();
file_thread.Start();
+ std::map<std::string, std::string> map;
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+ TestInstaller installer;
CrxComponent com;
- RegisterComponent(&com, kTestComponent_jebg, Version("0.9"));
+ RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
const GURL expected_update_url(
"http://localhost/upd?extra=foo&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc");
+ "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
interceptor.SetResponse(expected_update_url,
test_file("updatecheck_reply_2.xml"));
@@ -527,6 +795,8 @@ TEST_F(ComponentUpdaterTest, ProdVersionCheck) {
component_updater()->Start();
message_loop.Run();
+ EXPECT_EQ(0, ping_checker.NumHits());
+ EXPECT_EQ(0, ping_checker.NumMisses());
EXPECT_EQ(1, interceptor.GetHitCount());
EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
@@ -549,22 +819,32 @@ TEST_F(ComponentUpdaterTest, CheckForUpdateSoon) {
io_thread.StartIOThread();
file_thread.Start();
+ std::map<std::string, std::string> map;
+ map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
+ map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
+ map.insert(std::pair<std::string, std::string>("previousversion",
+ "\"0.9\""));
+ map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+ TestInstaller installer1;
CrxComponent com1;
- RegisterComponent(&com1, kTestComponent_abag, Version("2.2"));
+ RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), &installer1);
+ TestInstaller installer2;
CrxComponent com2;
- RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"));
+ RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), &installer2);
const GURL expected_update_url_1(
- "http://localhost/upd?extra=foo&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
const GURL expected_update_url_2(
- "http://localhost/upd?extra=foo&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
interceptor.SetResponse(expected_update_url_1,
test_file("updatecheck_reply_empty"));
@@ -613,9 +893,9 @@ TEST_F(ComponentUpdaterTest, CheckForUpdateSoon) {
// Test a few error cases. NOTE: We don't have callbacks for
// when the updates failed yet.
const GURL expected_update_url_3(
- "http://localhost/upd?extra=foo&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
// No update: error from no server response
interceptor.SetResponse(expected_update_url_3,
@@ -646,6 +926,8 @@ TEST_F(ComponentUpdaterTest, CheckForUpdateSoon) {
message_loop.Run();
+ EXPECT_EQ(1, ping_checker.NumHits());
+ EXPECT_EQ(0, ping_checker.NumMisses());
ASSERT_EQ(2ul, notification_tracker().size());
ev0 = notification_tracker().at(0);
EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
@@ -665,23 +947,33 @@ TEST_F(ComponentUpdaterTest, CheckReRegistration) {
io_thread.StartIOThread();
file_thread.Start();
+ std::map<std::string, std::string> map;
+ map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
+ map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
+ map.insert(std::pair<std::string, std::string>("previousversion",
+ "\"0.9\""));
+ map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+ TestInstaller installer1;
CrxComponent com1;
- RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"));
+ RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), &installer1);
+ TestInstaller installer2;
CrxComponent com2;
- RegisterComponent(&com2, kTestComponent_abag, Version("2.2"));
+ RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), &installer2);
// Start with 0.9, and update to 1.0
const GURL expected_update_url_1(
- "http://localhost/upd?extra=foo&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
const GURL expected_update_url_2(
- "http://localhost/upd?extra=foo&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26fp%3D%26uc");
interceptor.SetResponse(expected_update_url_1,
test_file("updatecheck_reply_1.xml"));
@@ -702,6 +994,8 @@ TEST_F(ComponentUpdaterTest, CheckReRegistration) {
EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
+ EXPECT_EQ(1, ping_checker.NumHits());
+ EXPECT_EQ(0, ping_checker.NumMisses());
EXPECT_EQ(3, interceptor.GetHitCount());
ASSERT_EQ(5ul, notification_tracker().size());
@@ -722,16 +1016,20 @@ TEST_F(ComponentUpdaterTest, CheckReRegistration) {
EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
// Now re-register, pretending to be an even newer version (2.2)
+ TestInstaller installer3;
component_updater()->Stop();
EXPECT_EQ(ComponentUpdateService::kReplaced,
- RegisterComponent(&com1, kTestComponent_jebg, Version("2.2")));
+ RegisterComponent(&com1,
+ kTestComponent_jebg,
+ Version("2.2"),
+ &installer3));
// Check that we send out 2.2 as our version.
// Interceptor's hit count should go up by 1.
const GURL expected_update_url_3(
- "http://localhost/upd?extra=foo&x=id%3D"
- "jebgalgnebhfojomionfpkfelancnnkf%26v%3D2.2%26uc&x=id%3D"
- "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D2.2%26fp%3D%26uc"
+ "&x=id%3Dabagagagagagagagagagagagagagagag%26v%3D2.2%26fp%3D%26uc");
interceptor.SetResponse(expected_update_url_3,
test_file("updatecheck_reply_1.xml"));
@@ -753,8 +1051,7 @@ TEST_F(ComponentUpdaterTest, CheckReRegistration) {
EXPECT_EQ(4, interceptor.GetHitCount());
- // The test harness's Register() function creates a new installer,
- // so the counts go back to 0.
+ // We created a new installer, so the counts go back to 0.
EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
@@ -762,3 +1059,289 @@ TEST_F(ComponentUpdaterTest, CheckReRegistration) {
component_updater()->Stop();
}
+
+// Verify that we can download and install a component and a differential
+// update to that component. We do three loops; the final loop should do
+// nothing.
+// We also check that exactly 5 non-ping network requests are issued:
+// 1- update check (response: v1 available)
+// 2- download crx (v1)
+// 3- update check (response: v2 available)
+// 4- download differential crx (v1 to v2)
+// 5- update check (response: no further update available)
+// There should be two pings, one for each update. The second will bear a
+// diffresult=1, while the first will not.
+TEST_F(ComponentUpdaterTest, DifferentialUpdate) {
+ base::MessageLoop message_loop;
+ content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
+ content::TestBrowserThread file_thread(BrowserThread::FILE);
+ content::TestBrowserThread io_thread(BrowserThread::IO);
+
+ io_thread.StartIOThread();
+ file_thread.Start();
+
+ std::map<std::string, std::string> map;
+ map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
+ map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
+ map.insert(std::pair<std::string, std::string>("diffresult", "\"1\""));
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
+ content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+
+ VersionedTestInstaller installer;
+ CrxComponent com;
+ RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
+
+ const GURL expected_update_url_0(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D0.0%26fp%3D%26uc");
+ const GURL expected_update_url_1(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D1%26uc");
+ const GURL expected_update_url_2(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
+ const GURL expected_crx_url_1(
+ "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
+ const GURL expected_crx_url_1_diff_2(
+ "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
+
+ interceptor.SetResponse(expected_update_url_0,
+ test_file("updatecheck_diff_reply_1.xml"));
+ interceptor.SetResponse(expected_update_url_1,
+ test_file("updatecheck_diff_reply_2.xml"));
+ interceptor.SetResponse(expected_update_url_2,
+ test_file("updatecheck_diff_reply_3.xml"));
+ interceptor.SetResponse(expected_crx_url_1,
+ test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
+ interceptor.SetResponse(
+ expected_crx_url_1_diff_2,
+ test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
+
+ test_configurator()->SetLoopCount(3);
+
+ component_updater()->Start();
+ message_loop.Run();
+
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
+ EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
+
+ EXPECT_EQ(1, ping_checker.NumHits());
+ EXPECT_EQ(1, ping_checker.NumMisses());
+ EXPECT_EQ(5, interceptor.GetHitCount());
+
+ component_updater()->Stop();
+}
+
+// Verify that component installation falls back to downloading and installing
+// a full update if the differential update fails (in this case, because the
+// installer does not know about the existing files). We do two loops; the final
+// loop should do nothing.
+// We also check that exactly 4 non-ping network requests are issued:
+// 1- update check (loop 1)
+// 2- download differential crx
+// 3- download full crx
+// 4- update check (loop 2 - no update available)
+// There should be one ping for the first attempted update.
+TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) {
+ base::MessageLoop message_loop;
+ content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
+ content::TestBrowserThread file_thread(BrowserThread::FILE);
+ content::TestBrowserThread io_thread(BrowserThread::IO);
+
+ io_thread.StartIOThread();
+ file_thread.Start();
+
+ std::map<std::string, std::string> map;
+ map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
+ map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
+ map.insert(std::pair<std::string, std::string>("diffresult", "\"0\""));
+ map.insert(std::pair<std::string, std::string>("differrorcode", "\"16\""));
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
+ content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+
+ TestInstaller installer;
+ CrxComponent com;
+ RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), &installer);
+
+ const GURL expected_update_url_1(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D%26uc");
+ const GURL expected_update_url_2(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
+ const GURL expected_crx_url_1(
+ "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
+ const GURL expected_crx_url_1_diff_2(
+ "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
+ const GURL expected_crx_url_2(
+ "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx");
+
+ interceptor.SetResponse(expected_update_url_1,
+ test_file("updatecheck_diff_reply_2.xml"));
+ interceptor.SetResponse(expected_update_url_2,
+ test_file("updatecheck_diff_reply_3.xml"));
+ interceptor.SetResponse(expected_crx_url_1,
+ test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
+ interceptor.SetResponse(
+ expected_crx_url_1_diff_2,
+ test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"));
+ interceptor.SetResponse(expected_crx_url_2,
+ test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
+
+ test_configurator()->SetLoopCount(2);
+
+ component_updater()->Start();
+ message_loop.Run();
+
+ // A failed differential update does not count as a failed install.
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
+ EXPECT_EQ(1, static_cast<TestInstaller*>(com.installer)->install_count());
+
+ EXPECT_EQ(1, ping_checker.NumHits());
+ EXPECT_EQ(0, ping_checker.NumMisses());
+ EXPECT_EQ(4, interceptor.GetHitCount());
+
+ component_updater()->Stop();
+}
+
+// Verify that a failed installation causes an install failure ping.
+TEST_F(ComponentUpdaterTest, CheckFailedInstallPing) {
+ base::MessageLoop message_loop;
+ content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
+ content::TestBrowserThread file_thread(BrowserThread::FILE);
+ content::TestBrowserThread io_thread(BrowserThread::IO);
+
+ io_thread.StartIOThread();
+ file_thread.Start();
+
+ std::map<std::string, std::string> map;
+ map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
+ map.insert(std::pair<std::string, std::string>("eventresult", "\"0\""));
+ map.insert(std::pair<std::string, std::string>("errorcode", "\"9\""));
+ map.insert(std::pair<std::string, std::string>("previousversion",
+ "\"0.9\""));
+ map.insert(std::pair<std::string, std::string>("nextversion", "\"1.0\""));
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
+ content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+
+ // This test installer reports installation failure.
+ class : public TestInstaller {
+ virtual bool Install(const base::DictionaryValue& manifest,
+ const base::FilePath& unpack_path) OVERRIDE {
+ ++install_count_;
+ file_util::Delete(unpack_path, true);
+ return false;
+ }
+ } installer;
+
+ CrxComponent com;
+ RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), &installer);
+
+ // Start with 0.9, and attempt update to 1.0
+ const GURL expected_update_url_1(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Djebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26fp%3D%26uc");
+
+ interceptor.SetResponse(expected_update_url_1,
+ test_file("updatecheck_reply_1.xml"));
+ interceptor.SetResponse(GURL(expected_crx_url),
+ test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
+
+ // Loop twice to issue two checks: (1) with original 0.9 version
+ // and (2), which should retry with 0.9.
+ test_configurator()->SetLoopCount(2);
+ component_updater()->Start();
+ message_loop.Run();
+
+ // Loop once more, but expect no ping because a noupdate response is issued.
+ // This is necessary to clear out the fire-and-forget ping from the previous
+ // iteration.
+ interceptor.SetResponse(expected_update_url_1,
+ test_file("updatecheck_reply_noupdate.xml"));
+ test_configurator()->SetLoopCount(1);
+ component_updater()->Start();
+ message_loop.Run();
+
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
+ EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
+
+ EXPECT_EQ(2, ping_checker.NumHits());
+ EXPECT_EQ(0, ping_checker.NumMisses());
+ EXPECT_EQ(5, interceptor.GetHitCount());
+
+ component_updater()->Stop();
+}
+
+// Verify that we successfully propagate a patcher error.
+// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect
+// patching instruction that should fail.
+TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) {
+ base::MessageLoop message_loop;
+ content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
+ content::TestBrowserThread file_thread(BrowserThread::FILE);
+ content::TestBrowserThread io_thread(BrowserThread::IO);
+
+ io_thread.StartIOThread();
+ file_thread.Start();
+
+ std::map<std::string, std::string> map;
+ map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
+ map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
+ map.insert(std::pair<std::string, std::string>("diffresult", "\"0\""));
+ map.insert(std::pair<std::string, std::string>("differrorcode", "\"14\""));
+ map.insert(std::pair<std::string, std::string>("diffextracode1", "\"305\""));
+ PingChecker ping_checker(map);
+ URLRequestPostInterceptor post_interceptor(&ping_checker);
+ content::URLLocalHostRequestPrepackagedInterceptor interceptor;
+
+ VersionedTestInstaller installer;
+ CrxComponent com;
+ RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), &installer);
+
+ const GURL expected_update_url_0(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D0.0%26fp%3D%26uc");
+ const GURL expected_update_url_1(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D1.0%26fp%3D1%26uc");
+ const GURL expected_update_url_2(
+ "http://localhost/upd?extra=foo"
+ "&x=id%3Dihfokbkgjpifnbbojhneepfflplebdkc%26v%3D2.0%26fp%3Df22%26uc");
+ const GURL expected_crx_url_1(
+ "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx");
+ const GURL expected_crx_url_1_diff_2(
+ "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx");
+ const GURL expected_crx_url_2(
+ "http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx");
+
+ interceptor.SetResponse(expected_update_url_0,
+ test_file("updatecheck_diff_reply_1.xml"));
+ interceptor.SetResponse(expected_update_url_1,
+ test_file("updatecheck_diff_reply_2.xml"));
+ interceptor.SetResponse(expected_update_url_2,
+ test_file("updatecheck_diff_reply_3.xml"));
+ interceptor.SetResponse(expected_crx_url_1,
+ test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"));
+ interceptor.SetResponse(
+ expected_crx_url_1_diff_2,
+ test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx"));
+ interceptor.SetResponse(expected_crx_url_2,
+ test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"));
+
+ test_configurator()->SetLoopCount(3);
+
+ component_updater()->Start();
+ message_loop.Run();
+
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
+ EXPECT_EQ(2, static_cast<TestInstaller*>(com.installer)->install_count());
+
+ EXPECT_EQ(1, ping_checker.NumHits());
+ EXPECT_EQ(1, ping_checker.NumMisses());
+ EXPECT_EQ(6, interceptor.GetHitCount());
+
+ component_updater()->Stop();
+}

Powered by Google App Engine
This is Rietveld 408576698