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

Side by Side Diff: chrome/browser/component_updater/component_updater_service_unittest.cc

Issue 10702188: Fix unit test to allow repeated successful runs by avoiding a function static variable in tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add DEPS file Created 8 years, 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/component_updater/component_updater_service.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/file_path.h"
9 #include "base/file_util.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/message_loop.h"
12 #include "base/path_service.h"
13 #include "base/values.h"
14 #include "chrome/browser/component_updater/component_updater_interceptor.h"
15 #include "chrome/common/chrome_notification_types.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "content/public/browser/notification_observer.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/test/test_browser_thread.h"
20 #include "content/public/test/test_notification_tracker.h"
21 #include "googleurl/src/gurl.h"
22 #include "libxml/globals.h"
23 #include "net/url_request/url_fetcher.h"
24 #include "net/url_request/url_request_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 using content::BrowserThread;
28 using content::TestNotificationTracker;
29
30 namespace {
31 // Overrides some of the component updater behaviors so it is easier to test
32 // and loops faster. In actual usage it takes hours do to a full cycle.
33 class TestConfigurator : public ComponentUpdateService::Configurator {
34 public:
35 TestConfigurator() : times_(1) {
36 }
37
38 virtual int InitialDelay() OVERRIDE { return 0; }
39
40 virtual int NextCheckDelay() OVERRIDE {
41 // This is called when a new full cycle of checking for updates is going
42 // to happen. In test we normally only test one cycle so it is a good
43 // time to break from the test messageloop Run() method so the test can
44 // finish.
45 if (--times_ > 0)
46 return 1;
47
48 MessageLoop::current()->Quit();
49 return 0;
50 }
51
52 virtual int StepDelay() OVERRIDE {
53 return 0;
54 }
55
56 virtual int MinimumReCheckWait() OVERRIDE {
57 return 0;
58 }
59
60 virtual GURL UpdateUrl() OVERRIDE { return GURL("http://localhost/upd"); }
61
62 virtual const char* ExtraRequestParams() OVERRIDE { return "extra=foo"; }
63
64 virtual size_t UrlSizeLimit() OVERRIDE { return 256; }
65
66 virtual net::URLRequestContextGetter* RequestContext() OVERRIDE {
67 return new TestURLRequestContextGetter(
68 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
69 }
70
71 // Don't use the utility process to decode files.
72 virtual bool InProcess() OVERRIDE { return true; }
73
74 virtual void OnEvent(Events event, int extra) OVERRIDE { }
75
76 // Set how many update checks are called, the default value is just once.
77 void SetLoopCount(int times) { times_ = times; }
78
79 private:
80 int times_;
81 };
82
83 class TestInstaller : public ComponentInstaller {
84 public :
85 explicit TestInstaller()
86 : error_(0), install_count_(0) {
87 }
88
89 virtual void OnUpdateError(int error) OVERRIDE {
90 EXPECT_NE(0, error);
91 error_ = error;
92 }
93
94 virtual bool Install(base::DictionaryValue* manifest,
95 const FilePath& unpack_path) OVERRIDE {
96 ++install_count_;
97 delete manifest;
98 return file_util::Delete(unpack_path, true);
99 }
100
101 int error() const { return error_; }
102
103 int install_count() const { return install_count_; }
104
105 private:
106 int error_;
107 int install_count_;
108 };
109
110 // component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and
111 // the RSA public key the following hash:
112 const uint8 jebg_hash[] = {0x94,0x16,0x0b,0x6d,0x41,0x75,0xe9,0xec,0x8e,0xd5,
113 0xfa,0x54,0xb0,0xd2,0xdd,0xa5,0x6e,0x05,0x6b,0xe8,
114 0x73,0x47,0xf6,0xc4,0x11,0x9f,0xbc,0xb3,0x09,0xb3,
115 0x5b,0x40};
116 // component 2 has extension id "abagagagagagagagagagagagagagagag", and
117 // the RSA public key the following hash:
118 const uint8 abag_hash[] = {0x01,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
119 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
120 0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
121 0x06,0x01};
122
123 const char header_ok_reply[] =
124 "HTTP/1.1 200 OK\0"
125 "Content-type: text/html\0"
126 "\0";
127
128 const char expected_crx_url[] =
129 "http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx";
130
131 } // namespace
132
133 // Common fixture for all the component updater tests.
134 class ComponentUpdaterTest : public testing::Test {
135 public:
136 enum TestComponents {
137 kTestComponent_abag,
138 kTestComponent_jebg
139 };
140
141 ComponentUpdaterTest() : component_updater_(NULL), test_config_(NULL) {
142 // The component updater instance under test.
143 test_config_ = new TestConfigurator;
144 component_updater_.reset(ComponentUpdateServiceFactory(test_config_));
145 // The test directory is chrome/test/data/components.
146 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
147 test_data_dir_ = test_data_dir_.AppendASCII("components");
148
149 // Subscribe to all component updater notifications.
150 const int notifications[] = {
151 chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
152 chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
153 chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
154 chrome::NOTIFICATION_COMPONENT_UPDATE_READY
155 };
156
157 for (int ix = 0; ix != arraysize(notifications); ++ix) {
158 notification_tracker_.ListenFor(
159 notifications[ix], content::NotificationService::AllSources());
160 }
161 net::URLFetcher::SetEnableInterceptionForTests(true);
162 }
163
164 ~ComponentUpdaterTest() {
165 net::URLFetcher::SetEnableInterceptionForTests(false);
166 }
167
168 void TearDown() {
169 xmlCleanupGlobals();
170 }
171
172 ComponentUpdateService* component_updater() {
173 return component_updater_.get();
174 }
175
176 // Makes the full path to a component updater test file.
177 const FilePath test_file(const char* file) {
178 return test_data_dir_.AppendASCII(file);
179 }
180
181 TestNotificationTracker& notification_tracker() {
182 return notification_tracker_;
183 }
184
185 TestConfigurator* test_configurator() {
186 return test_config_;
187 }
188
189 void RegisterComponent(CrxComponent* com,
190 TestComponents component,
191 const Version& version) {
192 if (component == kTestComponent_abag) {
193 com->name = "test_abag";
194 com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
195 } else {
196 com->name = "test_jebg";
197 com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash));
198 }
199 com->version = version;
200 TestInstaller* installer = new TestInstaller;
201 com->installer = installer;
202 test_installers_.push_back(installer);
203 component_updater_->RegisterComponent(*com);
204 }
205
206 private:
207 scoped_ptr<ComponentUpdateService> component_updater_;
208 FilePath test_data_dir_;
209 TestNotificationTracker notification_tracker_;
210 TestConfigurator* test_config_;
211 // ComponentInstaller objects to delete after each test.
212 ScopedVector<TestInstaller> test_installers_;
213 };
214
215 // Verify that our test fixture work and the component updater can
216 // be created and destroyed with no side effects.
217 TEST_F(ComponentUpdaterTest, VerifyFixture) {
218 EXPECT_TRUE(component_updater() != NULL);
219 EXPECT_EQ(0ul, notification_tracker().size());
220 }
221
222 // Verify that the component updater can be caught in a quick
223 // start-shutdown situation. Failure of this test will be a crash. Also
224 // if there is no work to do, there are no notifications generated.
225 TEST_F(ComponentUpdaterTest, StartStop) {
226 MessageLoop message_loop;
227 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
228
229 component_updater()->Start();
230 message_loop.RunAllPending();
231 component_updater()->Stop();
232
233 EXPECT_EQ(0ul, notification_tracker().size());
234 }
235
236 // Verify that when the server has no updates, we go back to sleep and
237 // the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications
238 // are generated.
239 TEST_F(ComponentUpdaterTest, CheckCrxSleep) {
240 MessageLoop message_loop;
241 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
242 content::TestBrowserThread file_thread(BrowserThread::FILE);
243 content::TestBrowserThread io_thread(BrowserThread::IO);
244
245 io_thread.StartIOThread();
246 file_thread.Start();
247
248 scoped_refptr<ComponentUpdateInterceptor>
249 interceptor(new ComponentUpdateInterceptor());
250
251 CrxComponent com;
252 RegisterComponent(&com, kTestComponent_abag, Version("1.1"));
253
254 const char expected_update_url[] =
255 "http://localhost/upd?extra=foo&x=id%3D"
256 "abagagagagagagagagagagagagagagag%26v%3D1.1%26uc";
257
258 interceptor->SetResponse(expected_update_url,
259 header_ok_reply,
260 test_file("updatecheck_reply_1.xml"));
261
262 // We loop twice, but there are no updates so we expect two sleep messages.
263 test_configurator()->SetLoopCount(2);
264 component_updater()->Start();
265
266 ASSERT_EQ(1ul, notification_tracker().size());
267 TestNotificationTracker::Event ev1 = notification_tracker().at(0);
268 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type);
269
270 message_loop.Run();
271
272 ASSERT_EQ(3ul, notification_tracker().size());
273 TestNotificationTracker::Event ev2 = notification_tracker().at(1);
274 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
275 TestNotificationTracker::Event ev3 = notification_tracker().at(2);
276 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
277 EXPECT_EQ(2, interceptor->hit_count());
278
279 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
280 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
281
282 component_updater()->Stop();
283
284 // Loop twice again but this case we simulate a server error by returning
285 // an empty file.
286
287 interceptor->SetResponse(expected_update_url,
288 header_ok_reply,
289 test_file("updatecheck_reply_empty"));
290
291 notification_tracker().Reset();
292 test_configurator()->SetLoopCount(2);
293 component_updater()->Start();
294
295 message_loop.Run();
296
297 ASSERT_EQ(3ul, notification_tracker().size());
298 ev1 = notification_tracker().at(0);
299 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type);
300 ev2 = notification_tracker().at(1);
301 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
302 ev3 = notification_tracker().at(2);
303 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
304 EXPECT_EQ(4, interceptor->hit_count());
305
306 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
307 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
308
309 component_updater()->Stop();
310 }
311
312 // Verify that we can check for updates and install one component. Besides
313 // the notifications above NOTIFICATION_COMPONENT_UPDATE_FOUND and
314 // NOTIFICATION_COMPONENT_UPDATE_READY should have been fired. We do two loops
315 // so the second time around there should be nothing left to do.
316 // We also check that only 3 network requests are issued:
317 // 1- manifest check
318 // 2- download crx
319 // 3- second manifest check.
320 TEST_F(ComponentUpdaterTest, InstallCrx) {
321 MessageLoop message_loop;
322 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
323 content::TestBrowserThread file_thread(BrowserThread::FILE);
324 content::TestBrowserThread io_thread(BrowserThread::IO);
325
326 io_thread.StartIOThread();
327 file_thread.Start();
328
329 scoped_refptr<ComponentUpdateInterceptor>
330 interceptor(new ComponentUpdateInterceptor());
331
332 CrxComponent com1;
333 RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"));
334 CrxComponent com2;
335 RegisterComponent(&com2, kTestComponent_abag, Version("2.2"));
336
337 const char expected_update_url_1[] =
338 "http://localhost/upd?extra=foo&x=id%3D"
339 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D"
340 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc";
341
342 const char expected_update_url_2[] =
343 "http://localhost/upd?extra=foo&x=id%3D"
344 "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D"
345 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc";
346
347 interceptor->SetResponse(expected_update_url_1, header_ok_reply,
348 test_file("updatecheck_reply_1.xml"));
349 interceptor->SetResponse(expected_update_url_2, header_ok_reply,
350 test_file("updatecheck_reply_1.xml"));
351 interceptor->SetResponse(expected_crx_url, header_ok_reply,
352 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
353
354 test_configurator()->SetLoopCount(2);
355
356 component_updater()->Start();
357 message_loop.Run();
358
359 EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
360 EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
361 EXPECT_EQ(3, interceptor->hit_count());
362
363 ASSERT_EQ(5ul, notification_tracker().size());
364
365 TestNotificationTracker::Event ev1 = notification_tracker().at(1);
366 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
367
368 TestNotificationTracker::Event ev2 = notification_tracker().at(2);
369 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
370
371 TestNotificationTracker::Event ev3 = notification_tracker().at(3);
372 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
373
374 TestNotificationTracker::Event ev4 = notification_tracker().at(4);
375 EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
376
377 component_updater()->Stop();
378 }
379
380 // This test checks that the "prodversionmin" value is handled correctly. In
381 // particular there should not be an install because the minimum product
382 // version is much higher than of chrome.
383 TEST_F(ComponentUpdaterTest, ProdVersionCheck) {
384 MessageLoop message_loop;
385 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
386 content::TestBrowserThread file_thread(BrowserThread::FILE);
387 content::TestBrowserThread io_thread(BrowserThread::IO);
388
389 io_thread.StartIOThread();
390 file_thread.Start();
391
392 scoped_refptr<ComponentUpdateInterceptor>
393 interceptor(new ComponentUpdateInterceptor());
394
395 CrxComponent com;
396 RegisterComponent(&com, kTestComponent_jebg, Version("0.9"));
397
398 const char expected_update_url[] =
399 "http://localhost/upd?extra=foo&x=id%3D"
400 "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc";
401
402 interceptor->SetResponse(expected_update_url,
403 header_ok_reply,
404 test_file("updatecheck_reply_2.xml"));
405 interceptor->SetResponse(expected_crx_url, header_ok_reply,
406 test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
407
408 test_configurator()->SetLoopCount(1);
409 component_updater()->Start();
410 message_loop.Run();
411
412 EXPECT_EQ(1, interceptor->hit_count());
413 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
414 EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->install_count());
415
416 component_updater()->Stop();
417 }
OLDNEW
« no previous file with comments | « chrome/browser/component_updater/component_installers_unittest.cc ('k') | chrome/browser/component_updater/test/DEPS » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698