OLD | NEW |
| (Empty) |
1 // Copyright 2009-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include "base/scoped_ptr.h" | |
17 #include "omaha/base/app_util.h" | |
18 #include "omaha/base/const_addresses.h" | |
19 #include "omaha/common/config_manager.h" | |
20 #include "omaha/common/web_services_client.h" | |
21 #include "omaha/goopdate/app_bundle_state_busy.h" | |
22 #include "omaha/goopdate/app_manager.h" | |
23 #include "omaha/goopdate/app_state_ready_to_install.h" | |
24 #include "omaha/goopdate/app_state_update_available.h" | |
25 #include "omaha/goopdate/download_manager.h" | |
26 #include "omaha/goopdate/goopdate.h" | |
27 #include "omaha/goopdate/install_manager.h" | |
28 #include "omaha/goopdate/installer_result_info.h" | |
29 #include "omaha/goopdate/model.h" | |
30 #include "omaha/goopdate/resource_manager.h" | |
31 #include "omaha/goopdate/worker.h" | |
32 #include "omaha/goopdate/worker_internal.h" | |
33 #include "omaha/goopdate/worker_metrics.h" | |
34 #include "omaha/testing/unit_test.h" | |
35 | |
36 namespace omaha { | |
37 | |
38 using ::testing::_; | |
39 using ::testing::Return; | |
40 | |
41 namespace { | |
42 | |
43 // TODO(omaha): Change these to invalid IDs once the TODO above | |
44 // UpdateResponse::GetResult is fixed. Until then, invalid IDs cause asserts. | |
45 // Also, the large tests need valid files to download. | |
46 #if 0 | |
47 const TCHAR* const kGuid1 = _T("{8A001254-1003-465e-A970-0748961C5293}"); | |
48 const TCHAR* const kGuid2 = _T("{058ADDBE-BF10-4ba1-93C0-6F4A52C03C7E}"); | |
49 #else | |
50 const TCHAR* const kGuid1 = _T("{ADDE8406-A0F3-4AC2-8878-ADC0BD37BD86}"); | |
51 const TCHAR* const kGuid2 = _T("{D0AB2EBC-931B-4013-9FEB-C9C4C2225C8C}"); | |
52 #endif | |
53 | |
54 // The alphabetical order of these is important for | |
55 // RecordUpdateAvailableUsageStatsTest. | |
56 const TCHAR* const kApp1 = _T("{0C480772-AC73-418f-9603-66303DA4C7AA}"); | |
57 const TCHAR* const kApp2 = _T("{89906BCD-4D12-4c9b-B5BA-8286051CB8D9}"); | |
58 const TCHAR* const kApp3 = _T("{F5A1FE97-CF5A-47b8-8B28-2A72F9A57A45}"); | |
59 | |
60 const uint64 kApp1GuidUpper = 0x0C480772AC73418f; | |
61 const uint64 kApp2GuidUpper = 0x89906BCD4D124c9b; | |
62 | |
63 const TCHAR* const kApp1ClientsKeyPathUser = | |
64 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
65 _T("\\Clients\\{0C480772-AC73-418f-9603-66303DA4C7AA}"); | |
66 const TCHAR* const kApp2ClientsKeyPathUser = | |
67 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
68 _T("\\Clients\\{89906BCD-4D12-4c9b-B5BA-8286051CB8D9}"); | |
69 const TCHAR* const kApp3ClientsKeyPathUser = | |
70 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
71 _T("\\Clients\\{F5A1FE97-CF5A-47b8-8B28-2A72F9A57A45}"); | |
72 | |
73 const TCHAR* const kApp1ClientStateKeyPathUser = | |
74 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
75 _T("\\ClientState\\{0C480772-AC73-418f-9603-66303DA4C7AA}"); | |
76 const TCHAR* const kApp2ClientStateKeyPathUser = | |
77 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
78 _T("\\ClientState\\{89906BCD-4D12-4c9b-B5BA-8286051CB8D9}"); | |
79 const TCHAR* const kApp3ClientStateKeyPathUser = | |
80 _T("HKCU\\Software\\") SHORT_COMPANY_NAME _T("\\") PRODUCT_NAME | |
81 _T("\\ClientState\\{F5A1FE97-CF5A-47b8-8B28-2A72F9A57A45}"); | |
82 | |
83 void SetAppStateUpdateAvailable(App* app) { | |
84 SetAppStateForUnitTest(app, new fsm::AppStateUpdateAvailable); | |
85 } | |
86 | |
87 void SetAppStateReadyToInstall(App* app) { | |
88 SetAppStateForUnitTest(app, new fsm::AppStateReadyToInstall); | |
89 } | |
90 | |
91 class MockWebServicesClient : public WebServicesClientInterface { | |
92 public: | |
93 MOCK_METHOD2(Send, | |
94 HRESULT(const xml::UpdateRequest* update_request, | |
95 xml::UpdateResponse* update_response)); | |
96 MOCK_METHOD2(SendString, | |
97 HRESULT(const CString* request_string, | |
98 xml::UpdateResponse* update_response)); | |
99 MOCK_METHOD0(Cancel, | |
100 void()); | |
101 MOCK_METHOD1(set_proxy_auth_config, | |
102 void(const ProxyAuthConfig& config)); | |
103 MOCK_CONST_METHOD0(is_http_success, | |
104 bool()); | |
105 MOCK_CONST_METHOD0(http_status_code, | |
106 int()); | |
107 MOCK_CONST_METHOD0(http_trace, | |
108 CString()); | |
109 }; | |
110 | |
111 class MockDownloadManager : public DownloadManagerInterface { | |
112 public: | |
113 MOCK_METHOD0(Initialize, | |
114 HRESULT()); | |
115 MOCK_METHOD2(PurgeAppLowerVersions, | |
116 HRESULT(const CString&, const CString&)); | |
117 MOCK_METHOD2(CachePackage, | |
118 HRESULT(const Package*, const CString*)); | |
119 MOCK_METHOD1(DownloadApp, | |
120 HRESULT(App* app)); | |
121 MOCK_METHOD1(DownloadPackage, | |
122 HRESULT(Package* package)); | |
123 MOCK_CONST_METHOD2(GetPackage, | |
124 HRESULT(const Package*, const CString&)); | |
125 MOCK_METHOD1(Cancel, | |
126 void(App* app)); | |
127 MOCK_METHOD0(CancelAll, | |
128 void()); | |
129 MOCK_CONST_METHOD0(IsBusy, | |
130 bool()); | |
131 MOCK_CONST_METHOD1(IsPackageAvailable, | |
132 bool(const Package* package)); // NOLINT | |
133 }; | |
134 | |
135 class MockInstallManager : public InstallManagerInterface { | |
136 public: | |
137 MOCK_METHOD0(Initialize, | |
138 HRESULT()); | |
139 MOCK_CONST_METHOD0(install_working_dir, | |
140 CString()); | |
141 MOCK_METHOD2(InstallApp, | |
142 void(App* app, const CString& dir)); | |
143 }; | |
144 | |
145 ACTION(SimulateDownloadAppStateTransition) { | |
146 UNREFERENCED_ACTION_PARAMETERS; | |
147 arg0->Downloading(); | |
148 arg0->DownloadComplete(); | |
149 // TODO(omaha3): Simulate extract and differential update once implemented. | |
150 arg0->MarkReadyToInstall(); | |
151 return 0; | |
152 } | |
153 | |
154 ACTION(SimulateInstallAppStateTransition) { | |
155 UNREFERENCED_ACTION_PARAMETERS; | |
156 arg0->Installing(); | |
157 | |
158 AppManager& app_manager = *AppManager::Instance(); | |
159 __mutexScope(app_manager.GetRegistryStableStateLock()); | |
160 | |
161 InstallerResultInfo result_info; | |
162 result_info.type = INSTALLER_RESULT_SUCCESS; | |
163 result_info.text = _T("success"); | |
164 arg0->ReportInstallerComplete(result_info); | |
165 } | |
166 | |
167 void WaitForAppToEnterState(const App& app, | |
168 CurrentState expected_state, | |
169 int timeout_sec) { | |
170 const int kPeriodMs = 50; | |
171 const int max_tries = timeout_sec * 1000 / kPeriodMs; | |
172 for (int tries = 0; tries < max_tries; ++tries) { | |
173 if (expected_state == app.state()) { | |
174 break; | |
175 } | |
176 ::Sleep(kPeriodMs); | |
177 } | |
178 EXPECT_EQ(expected_state, app.state()); | |
179 } | |
180 | |
181 // Assumes the caller has verified the bundle is busy. Otherwise, this could | |
182 // return before the bundle enters the busy state. | |
183 void WaitForBundleToBeReady(const AppBundle& app_bundle, int timeout_sec) { | |
184 const int kPeriodMs = 50; | |
185 const int max_tries = timeout_sec * 1000 / kPeriodMs; | |
186 for (int tries = 0; tries < max_tries; ++tries) { | |
187 if (!app_bundle.IsBusy()) { | |
188 return; | |
189 } | |
190 ::Sleep(kPeriodMs); | |
191 } | |
192 ADD_FAILURE() << _T("Timed out waiting for AppBundle to be ready."); | |
193 } | |
194 | |
195 } // namespace | |
196 | |
197 // All tests use a user instance of the Worker. | |
198 | |
199 class WorkerTest : public testing::Test { | |
200 protected: | |
201 WorkerTest() : is_machine_(false), goopdate_(is_machine_), worker_(NULL) {} | |
202 | |
203 virtual void SetUp() { | |
204 worker_ = &Worker::Instance(); | |
205 | |
206 worker_->Initialize(is_machine_); | |
207 | |
208 EXPECT_SUCCEEDED(ResourceManager::Create( | |
209 is_machine_, app_util::GetCurrentModuleDirectory(), _T("en"))); | |
210 } | |
211 | |
212 virtual void TearDown() { | |
213 worker_ = NULL; | |
214 Worker::DeleteInstance(); | |
215 ResourceManager::Delete(); | |
216 } | |
217 | |
218 // Overrides the update check client of the bundle. | |
219 void SetUpdateCheckClient(AppBundle* app_bundle, | |
220 WebServicesClientInterface* web_services_client) { | |
221 app_bundle->update_check_client_.reset(web_services_client); | |
222 } | |
223 | |
224 void SetWorkerDownloadManager(DownloadManagerInterface* download_manager) { | |
225 ASSERT_TRUE(download_manager); | |
226 worker_->download_manager_.reset(download_manager); | |
227 } | |
228 | |
229 void SetWorkerInstallManager(InstallManagerInterface* install_manager) { | |
230 ASSERT_TRUE(install_manager); | |
231 worker_->install_manager_.reset(install_manager); | |
232 } | |
233 | |
234 const bool is_machine_; | |
235 Goopdate goopdate_; | |
236 Worker* worker_; | |
237 | |
238 private: | |
239 DISALLOW_COPY_AND_ASSIGN(WorkerTest); | |
240 }; | |
241 | |
242 class WorkerWithBundleTest : public WorkerTest { | |
243 protected: | |
244 WorkerWithBundleTest() : WorkerTest() {} | |
245 | |
246 virtual void SetUp() { | |
247 WorkerTest::SetUp(); | |
248 | |
249 app_bundle_ = worker_->model()->CreateAppBundle(is_machine_); | |
250 ASSERT_TRUE(app_bundle_.get()); | |
251 | |
252 EXPECT_SUCCEEDED(app_bundle_->put_displayName(CComBSTR(_T("My Bundle")))); | |
253 EXPECT_SUCCEEDED(app_bundle_->put_displayLanguage(CComBSTR(_T("en")))); | |
254 EXPECT_SUCCEEDED(app_bundle_->initialize()); | |
255 | |
256 CString update_check_url; | |
257 ConfigManager::Instance()->GetUpdateCheckUrl(&update_check_url); | |
258 WebServicesClient* web_service_client = new WebServicesClient(is_machine_); | |
259 EXPECT_HRESULT_SUCCEEDED(web_service_client->Initialize(update_check_url, | |
260 HeadersVector(), | |
261 true)); | |
262 SetUpdateCheckClient(app_bundle_.get(), web_service_client); | |
263 } | |
264 | |
265 virtual void TearDown() { | |
266 app_bundle_.reset(); | |
267 | |
268 WorkerTest::TearDown(); | |
269 } | |
270 | |
271 shared_ptr<AppBundle> app_bundle_; | |
272 | |
273 private: | |
274 DISALLOW_COPY_AND_ASSIGN(WorkerWithBundleTest); | |
275 }; | |
276 | |
277 // The EULA is accepted for both apps. | |
278 class WorkerWithTwoAppsTest : public WorkerWithBundleTest { | |
279 protected: | |
280 WorkerWithTwoAppsTest() : WorkerWithBundleTest(), app1_(NULL), app2_(NULL) {} | |
281 | |
282 virtual void SetUp() { | |
283 WorkerWithBundleTest::SetUp(); | |
284 | |
285 EXPECT_SUCCEEDED(app_bundle_->createApp(CComBSTR(kGuid1), &app1_)); | |
286 EXPECT_SUCCEEDED(app_bundle_->createApp(CComBSTR(kGuid2), &app2_)); | |
287 | |
288 EXPECT_SUCCEEDED(app1_->put_isEulaAccepted(VARIANT_TRUE)); | |
289 EXPECT_SUCCEEDED(app2_->put_isEulaAccepted(VARIANT_TRUE)); | |
290 } | |
291 | |
292 virtual void TearDown() { | |
293 WorkerWithBundleTest::TearDown(); | |
294 } | |
295 | |
296 App* app1_; | |
297 App* app2_; | |
298 | |
299 private: | |
300 DISALLOW_COPY_AND_ASSIGN(WorkerWithTwoAppsTest); | |
301 }; | |
302 | |
303 // Mocks the DownloadManager and InstallManager. | |
304 class WorkerMockedManagersTest : public WorkerWithTwoAppsTest { | |
305 protected: | |
306 WorkerMockedManagersTest() | |
307 : WorkerWithTwoAppsTest(), | |
308 mock_web_services_client_(), | |
309 mock_download_manager_(NULL), | |
310 mock_install_manager_(NULL) { | |
311 } | |
312 | |
313 virtual void SetUp() { | |
314 WorkerWithTwoAppsTest::SetUp(); | |
315 | |
316 // By default, no methods should be called on web service client and install | |
317 // manager, so make them StrictMock. Override this behavior for specific | |
318 // methods in the individual test cases. | |
319 mock_web_services_client_ = new testing::StrictMock<MockWebServicesClient>; | |
320 mock_install_manager_ = new testing::StrictMock<MockInstallManager>; | |
321 | |
322 // Some functions will be called on the mock download manager, so make it | |
323 // NiceMock. | |
324 mock_download_manager_ = new testing::NiceMock<MockDownloadManager>; | |
325 | |
326 // The App Bundle takes ownership. | |
327 SetUpdateCheckClient(app_bundle_.get(), mock_web_services_client_); | |
328 | |
329 // The Worker takes ownership of the Manager mocks. | |
330 SetWorkerDownloadManager(mock_download_manager_); | |
331 SetWorkerInstallManager(mock_install_manager_); | |
332 } | |
333 | |
334 virtual void TearDown() { | |
335 WorkerWithTwoAppsTest::TearDown(); | |
336 } | |
337 | |
338 // Pointers used by tests to set behavior. Not owned by this instance. | |
339 MockWebServicesClient* mock_web_services_client_; | |
340 MockDownloadManager* mock_download_manager_; | |
341 MockInstallManager* mock_install_manager_; | |
342 | |
343 private: | |
344 DISALLOW_COPY_AND_ASSIGN(WorkerMockedManagersTest); | |
345 }; | |
346 | |
347 TEST_F(WorkerMockedManagersTest, CheckForUpdateAsync) { | |
348 EXPECT_CALL(*mock_web_services_client_, Send(_, _)) | |
349 .Times(1); | |
350 | |
351 __mutexBlock(worker_->model()->lock()) { | |
352 EXPECT_SUCCEEDED(worker_->CheckForUpdateAsync(app_bundle_.get())); | |
353 | |
354 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app1_->state()); | |
355 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app2_->state()); | |
356 | |
357 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
358 new fsm::AppBundleStateBusy); | |
359 EXPECT_TRUE(app_bundle_->IsBusy()); | |
360 } | |
361 | |
362 // TODO(omaha3): The update check fails because there is not a real response. | |
363 // Fix this. | |
364 WaitForBundleToBeReady(*app_bundle_, 5); | |
365 EXPECT_FALSE(app_bundle_->IsBusy()); | |
366 EXPECT_EQ(STATE_ERROR, app1_->state()); | |
367 EXPECT_EQ(STATE_ERROR, app2_->state()); | |
368 } | |
369 | |
370 TEST_F(WorkerMockedManagersTest, DownloadAsync) { | |
371 SetAppStateUpdateAvailable(app1_); | |
372 SetAppStateUpdateAvailable(app2_); | |
373 | |
374 { | |
375 ::testing::InSequence dummy; | |
376 EXPECT_CALL(*mock_download_manager_, DownloadApp(app1_)) | |
377 .WillOnce(SimulateDownloadAppStateTransition()); | |
378 EXPECT_CALL(*mock_download_manager_, DownloadApp(app2_)) | |
379 .WillOnce(SimulateDownloadAppStateTransition()); | |
380 } | |
381 | |
382 // Holding the lock prevents the state from changing in the other thread, | |
383 // ensuring consistent results. | |
384 __mutexBlock(worker_->model()->lock()) { | |
385 EXPECT_SUCCEEDED(worker_->DownloadAsync(app_bundle_.get())); | |
386 | |
387 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app1_->state()); | |
388 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app2_->state()); | |
389 | |
390 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
391 new fsm::AppBundleStateBusy); | |
392 EXPECT_TRUE(app_bundle_->IsBusy()); | |
393 } | |
394 | |
395 WaitForBundleToBeReady(*app_bundle_, 5); | |
396 EXPECT_EQ(STATE_READY_TO_INSTALL, app1_->state()); | |
397 EXPECT_EQ(STATE_READY_TO_INSTALL, app2_->state()); | |
398 } | |
399 | |
400 TEST_F(WorkerMockedManagersTest, DownloadAndInstallAsync_AlreadyDownloaded) { | |
401 SetAppStateReadyToInstall(app1_); | |
402 SetAppStateReadyToInstall(app2_); | |
403 | |
404 EXPECT_CALL(*mock_install_manager_, install_working_dir()) | |
405 .WillRepeatedly(Return(app_util::GetTempDir())); | |
406 | |
407 { | |
408 ::testing::InSequence dummy; | |
409 EXPECT_CALL(*mock_install_manager_, InstallApp(app1_, _)) | |
410 .WillOnce(SimulateInstallAppStateTransition()); | |
411 EXPECT_CALL(*mock_install_manager_, InstallApp(app2_, _)) | |
412 .WillOnce(SimulateInstallAppStateTransition()); | |
413 } | |
414 | |
415 __mutexBlock(worker_->model()->lock()) { | |
416 EXPECT_SUCCEEDED(worker_->DownloadAndInstallAsync(app_bundle_.get())); | |
417 | |
418 EXPECT_EQ(STATE_WAITING_TO_INSTALL, app1_->state()); | |
419 EXPECT_EQ(STATE_WAITING_TO_INSTALL, app2_->state()); | |
420 | |
421 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
422 new fsm::AppBundleStateBusy); | |
423 EXPECT_TRUE(app_bundle_->IsBusy()); | |
424 } | |
425 | |
426 WaitForBundleToBeReady(*app_bundle_, 5); | |
427 EXPECT_EQ(STATE_INSTALL_COMPLETE, app1_->state()); | |
428 EXPECT_EQ(STATE_INSTALL_COMPLETE, app2_->state()); | |
429 } | |
430 | |
431 TEST_F(WorkerMockedManagersTest, DownloadAndInstallAsync_NotAlreadyDownloaded) { | |
432 SetAppStateUpdateAvailable(app1_); | |
433 SetAppStateUpdateAvailable(app2_); | |
434 | |
435 EXPECT_CALL(*mock_install_manager_, install_working_dir()) | |
436 .WillRepeatedly(Return(app_util::GetTempDir())); | |
437 | |
438 { | |
439 ::testing::InSequence dummy; | |
440 EXPECT_CALL(*mock_download_manager_, DownloadApp(app1_)) | |
441 .WillOnce(SimulateDownloadAppStateTransition()); | |
442 EXPECT_CALL(*mock_install_manager_, InstallApp(app1_, _)) | |
443 .WillOnce(SimulateInstallAppStateTransition()); | |
444 EXPECT_CALL(*mock_download_manager_, DownloadApp(app2_)) | |
445 .WillOnce(SimulateDownloadAppStateTransition()); | |
446 EXPECT_CALL(*mock_install_manager_, InstallApp(app2_, _)) | |
447 .WillOnce(SimulateInstallAppStateTransition()); | |
448 } | |
449 | |
450 __mutexBlock(worker_->model()->lock()) { | |
451 EXPECT_SUCCEEDED(worker_->DownloadAndInstallAsync(app_bundle_.get())); | |
452 | |
453 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app1_->state()); | |
454 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app2_->state()); | |
455 | |
456 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
457 new fsm::AppBundleStateBusy); | |
458 EXPECT_TRUE(app_bundle_->IsBusy()); | |
459 } | |
460 | |
461 WaitForBundleToBeReady(*app_bundle_, 5); | |
462 EXPECT_EQ(STATE_INSTALL_COMPLETE, app1_->state()); | |
463 EXPECT_EQ(STATE_INSTALL_COMPLETE, app2_->state()); | |
464 } | |
465 | |
466 TEST_F(WorkerMockedManagersTest, DownloadAsync_Then_DownloadAndInstallAsync) { | |
467 SetAppStateUpdateAvailable(app1_); | |
468 SetAppStateUpdateAvailable(app2_); | |
469 | |
470 { | |
471 ::testing::InSequence dummy; | |
472 EXPECT_CALL(*mock_download_manager_, DownloadApp(app1_)) | |
473 .WillOnce(SimulateDownloadAppStateTransition()); | |
474 EXPECT_CALL(*mock_download_manager_, DownloadApp(app2_)) | |
475 .WillOnce(SimulateDownloadAppStateTransition()); | |
476 } | |
477 | |
478 __mutexBlock(worker_->model()->lock()) { | |
479 EXPECT_SUCCEEDED(worker_->DownloadAsync(app_bundle_.get())); | |
480 | |
481 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app1_->state()); | |
482 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app2_->state()); | |
483 | |
484 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
485 new fsm::AppBundleStateBusy); | |
486 EXPECT_TRUE(app_bundle_->IsBusy()); | |
487 } | |
488 | |
489 WaitForBundleToBeReady(*app_bundle_, 5); | |
490 EXPECT_EQ(STATE_READY_TO_INSTALL, app1_->state()); | |
491 EXPECT_EQ(STATE_READY_TO_INSTALL, app2_->state()); | |
492 | |
493 EXPECT_CALL(*mock_install_manager_, install_working_dir()) | |
494 .WillRepeatedly(Return(app_util::GetTempDir())); | |
495 | |
496 { | |
497 ::testing::InSequence dummy; | |
498 EXPECT_CALL(*mock_install_manager_, InstallApp(app1_, _)) | |
499 .WillOnce(SimulateInstallAppStateTransition()); | |
500 EXPECT_CALL(*mock_install_manager_, InstallApp(app2_, _)) | |
501 .WillOnce(SimulateInstallAppStateTransition()); | |
502 } | |
503 __mutexBlock(worker_->model()->lock()) { | |
504 EXPECT_SUCCEEDED(worker_->DownloadAndInstallAsync(app_bundle_.get())); | |
505 | |
506 EXPECT_EQ(STATE_WAITING_TO_INSTALL, app1_->state()); | |
507 EXPECT_EQ(STATE_WAITING_TO_INSTALL, app2_->state()); | |
508 | |
509 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
510 new fsm::AppBundleStateBusy); | |
511 EXPECT_TRUE(app_bundle_->IsBusy()); | |
512 } | |
513 | |
514 WaitForBundleToBeReady(*app_bundle_, 5); | |
515 EXPECT_EQ(STATE_INSTALL_COMPLETE, app1_->state()); | |
516 EXPECT_EQ(STATE_INSTALL_COMPLETE, app2_->state()); | |
517 } | |
518 | |
519 TEST_F(WorkerMockedManagersTest, UpdateAllAppsAsync) { | |
520 EXPECT_CALL(*mock_web_services_client_, Send(_, _)) | |
521 .Times(1); | |
522 | |
523 __mutexBlock(worker_->model()->lock()) { | |
524 EXPECT_SUCCEEDED(worker_->UpdateAllAppsAsync(app_bundle_.get())); | |
525 | |
526 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app1_->state()); | |
527 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app2_->state()); | |
528 | |
529 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
530 new fsm::AppBundleStateBusy); | |
531 EXPECT_TRUE(app_bundle_->IsBusy()); | |
532 } | |
533 | |
534 // TODO(omaha3): The update check fails because there is not a real response. | |
535 // Fix this and continue the test, ensuring it gets to install complete. | |
536 WaitForBundleToBeReady(*app_bundle_, 5); | |
537 EXPECT_FALSE(app_bundle_->IsBusy()); | |
538 EXPECT_EQ(STATE_ERROR, app1_->state()); | |
539 EXPECT_EQ(STATE_ERROR, app2_->state()); | |
540 } | |
541 | |
542 // TODO(omaha): Add tests for app already in error state, app failing download | |
543 // or install, all apps failed or failing, etc. | |
544 | |
545 // | |
546 // Large Tests | |
547 // These are large tests because they use threads and access the network. | |
548 // TODO(omaha): Move these to a separate test executable when using Hammer to | |
549 // run tests. | |
550 // | |
551 | |
552 TEST_F(WorkerWithTwoAppsTest, CheckForUpdateAsync_Large) { | |
553 __mutexBlock(worker_->model()->lock()) { | |
554 EXPECT_SUCCEEDED(worker_->CheckForUpdateAsync(app_bundle_.get())); | |
555 | |
556 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app1_->state()); | |
557 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app2_->state()); | |
558 | |
559 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
560 new fsm::AppBundleStateBusy); | |
561 EXPECT_TRUE(app_bundle_->IsBusy()); | |
562 } | |
563 | |
564 WaitForBundleToBeReady(*app_bundle_, 10); | |
565 EXPECT_EQ(STATE_UPDATE_AVAILABLE, app1_->state()); | |
566 EXPECT_EQ(STATE_UPDATE_AVAILABLE, app2_->state()); | |
567 } | |
568 | |
569 TEST_F(WorkerWithTwoAppsTest, | |
570 DownloadAsyncThenDownloadAndInstallAsync_Large) { | |
571 // Update Check: Request then wait for it to complete in the thread pool. | |
572 | |
573 __mutexBlock(worker_->model()->lock()) { | |
574 EXPECT_SUCCEEDED(worker_->CheckForUpdateAsync(app_bundle_.get())); | |
575 | |
576 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app1_->state()); | |
577 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app2_->state()); | |
578 | |
579 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
580 new fsm::AppBundleStateBusy); | |
581 EXPECT_TRUE(app_bundle_->IsBusy()); | |
582 } | |
583 | |
584 WaitForBundleToBeReady(*app_bundle_, 10); | |
585 EXPECT_EQ(STATE_UPDATE_AVAILABLE, app1_->state()); | |
586 EXPECT_EQ(STATE_UPDATE_AVAILABLE, app2_->state()); | |
587 | |
588 // Download: Request then wait for it to complete in the thread pool. | |
589 | |
590 __mutexBlock(worker_->model()->lock()) { | |
591 EXPECT_SUCCEEDED(worker_->DownloadAsync(app_bundle_.get())); | |
592 | |
593 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app1_->state()); | |
594 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app2_->state()); | |
595 | |
596 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
597 new fsm::AppBundleStateBusy); | |
598 EXPECT_TRUE(app_bundle_->IsBusy()); | |
599 } | |
600 | |
601 WaitForBundleToBeReady(*app_bundle_, 25); | |
602 EXPECT_EQ(STATE_READY_TO_INSTALL, app1_->state()); | |
603 EXPECT_EQ(STATE_READY_TO_INSTALL, app2_->state()); | |
604 | |
605 // Install: Request then wait for it to complete in the thread pool. | |
606 | |
607 // TODO(omaha): Make User Foo installer available from production, change | |
608 // GUID(s), and enable the code below. Be sure to uninstall the app when done. | |
609 #if 0 | |
610 | |
611 __mutexBlock(worker_->model()->lock()) { | |
612 EXPECT_SUCCEEDED(worker_->DownloadAndInstallAsync(app_bundle_.get())); | |
613 | |
614 EXPECT_EQ(STATE_WAITING_TO_INSTALL, app1_->state()); | |
615 EXPECT_EQ(STATE_WAITING_TO_INSTALL, app2_->state()); | |
616 | |
617 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
618 new fsm::AppBundleStateBusy); | |
619 EXPECT_TRUE(app_bundle_->IsBusy()); | |
620 } | |
621 | |
622 WaitForBundleToBeReady(*app_bundle_, 10); | |
623 EXPECT_EQ(STATE_INSTALL_COMPLETE, app1_->state()); | |
624 EXPECT_EQ(STATE_INSTALL_COMPLETE, app2_->state()); | |
625 #endif | |
626 } | |
627 | |
628 TEST_F(WorkerWithTwoAppsTest, DownloadAndInstallAsyncWithoutDownload_Large) { | |
629 // Update Check: Request then wait for it to complete in the thread pool. | |
630 | |
631 __mutexBlock(worker_->model()->lock()) { | |
632 EXPECT_SUCCEEDED(worker_->CheckForUpdateAsync(app_bundle_.get())); | |
633 | |
634 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app1_->state()); | |
635 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app2_->state()); | |
636 | |
637 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
638 new fsm::AppBundleStateBusy); | |
639 EXPECT_TRUE(app_bundle_->IsBusy()); | |
640 } | |
641 | |
642 WaitForBundleToBeReady(*app_bundle_, 10); | |
643 EXPECT_EQ(STATE_UPDATE_AVAILABLE, app1_->state()); | |
644 EXPECT_EQ(STATE_UPDATE_AVAILABLE, app2_->state()); | |
645 | |
646 // Download and install: Request then wait for it to complete in thread pool. | |
647 | |
648 // TODO(omaha): Make User Foo installer available from production, change | |
649 // GUID(s), and enable the code below. Be sure to uninstall the app when done. | |
650 #if 0 | |
651 __mutexBlock(worker_->model()->lock()) { | |
652 EXPECT_SUCCEEDED(worker_->DownloadAndInstallAsync(app_bundle_.get())); | |
653 | |
654 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app1_->state()); | |
655 EXPECT_EQ(STATE_WAITING_TO_DOWNLOAD, app2_->state()); | |
656 | |
657 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
658 new fsm::AppBundleStateBusy); | |
659 EXPECT_TRUE(app_bundle_->IsBusy()); | |
660 } | |
661 | |
662 WaitForBundleToBeReady(*app_bundle_, 10); | |
663 EXPECT_EQ(STATE_INSTALL_COMPLETE, app1_->state()); | |
664 EXPECT_EQ(STATE_INSTALL_COMPLETE, app2_->state()); | |
665 #endif | |
666 } | |
667 | |
668 // Also tests cancellation of a bundle during the update check phase. | |
669 TEST_F(WorkerWithTwoAppsTest, UpdateAllAppsAsync_Large) { | |
670 __mutexBlock(worker_->model()->lock()) { | |
671 EXPECT_SUCCEEDED(worker_->UpdateAllAppsAsync(app_bundle_.get())); | |
672 | |
673 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app1_->state()); | |
674 EXPECT_EQ(STATE_WAITING_TO_CHECK_FOR_UPDATE, app2_->state()); | |
675 | |
676 SetAppBundleStateForUnitTest(app_bundle_.get(), | |
677 new fsm::AppBundleStateBusy); | |
678 EXPECT_TRUE(app_bundle_->IsBusy()); | |
679 | |
680 // Stop the bundle to prevent it from actually trying to update app. | |
681 EXPECT_SUCCEEDED(app_bundle_->stop()); | |
682 } | |
683 } | |
684 | |
685 class RecordUpdateAvailableUsageStatsTest : public testing::Test { | |
686 protected: | |
687 RecordUpdateAvailableUsageStatsTest() : is_machine_(false) {} | |
688 | |
689 static void SetUpTestCase() { | |
690 stats_report::g_global_metrics.Initialize(); | |
691 } | |
692 | |
693 static void TearDownTestCase() { | |
694 // The global metrics collection must be uninitialized before the metrics | |
695 // destructors are called. | |
696 stats_report::g_global_metrics.Uninitialize(); | |
697 } | |
698 | |
699 virtual void SetUp() { | |
700 RegKey::DeleteKey(kRegistryHiveOverrideRoot); | |
701 OverrideRegistryHives(kRegistryHiveOverrideRoot); | |
702 | |
703 EXPECT_SUCCEEDED(AppManager::CreateInstance(is_machine_)); | |
704 | |
705 metric_worker_self_update_responses.Set(0); | |
706 metric_worker_self_update_response_time_since_first_ms.Set(0); | |
707 metric_worker_app_max_update_responses_app_high.Set(0); | |
708 metric_worker_app_max_update_responses.Set(0); | |
709 metric_worker_app_max_update_responses_ms_since_first.Set(0); | |
710 | |
711 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE, | |
712 kRegValueProductVersion, | |
713 _T("0.1.0.0"))); | |
714 ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientsKeyPathUser, | |
715 kRegValueProductVersion, | |
716 _T("0.1"))); | |
717 | |
718 ASSERT_SUCCEEDED(RegKey::CreateKey(USER_REG_CLIENT_STATE_GOOPDATE)); | |
719 ASSERT_SUCCEEDED(RegKey::CreateKey(kApp1ClientStateKeyPathUser)); | |
720 } | |
721 | |
722 int GetNumProducts() { | |
723 AppManager& app_manager = *AppManager::Instance(); | |
724 AppIdVector registered_app_ids; | |
725 VERIFY1(SUCCEEDED(app_manager.GetRegisteredApps(®istered_app_ids))); | |
726 return registered_app_ids.size(); | |
727 } | |
728 | |
729 virtual void TearDown() { | |
730 AppManager::DeleteInstance(); | |
731 | |
732 RestoreRegistryHives(); | |
733 RegKey::DeleteKey(kRegistryHiveOverrideRoot); | |
734 } | |
735 | |
736 bool is_machine_; | |
737 }; | |
738 | |
739 TEST_F(RecordUpdateAvailableUsageStatsTest, NoData) { | |
740 ASSERT_EQ(2, GetNumProducts()); | |
741 | |
742 internal::RecordUpdateAvailableUsageStats(); | |
743 | |
744 EXPECT_EQ(0, metric_worker_self_update_responses.value()); | |
745 EXPECT_EQ(0, metric_worker_self_update_response_time_since_first_ms.value()); | |
746 EXPECT_EQ(0, metric_worker_app_max_update_responses_app_high.value()); | |
747 EXPECT_EQ(0, metric_worker_app_max_update_responses.value()); | |
748 EXPECT_EQ(0, metric_worker_app_max_update_responses_ms_since_first.value()); | |
749 } | |
750 | |
751 TEST_F(RecordUpdateAvailableUsageStatsTest, OmahaDataOnly) { | |
752 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENT_STATE_GOOPDATE, | |
753 _T("UpdateAvailableCount"), | |
754 static_cast<DWORD>(123456))); | |
755 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENT_STATE_GOOPDATE, | |
756 _T("UpdateAvailableSince"), | |
757 static_cast<DWORD64>(10))); | |
758 | |
759 ASSERT_EQ(2, GetNumProducts()); | |
760 | |
761 const time64 current_time_100ns(GetCurrent100NSTime()); | |
762 const int64 expected_ms_since_first_update = | |
763 (current_time_100ns - 10) / kMillisecsTo100ns; | |
764 | |
765 internal::RecordUpdateAvailableUsageStats(); | |
766 | |
767 EXPECT_EQ(123456, metric_worker_self_update_responses.value()); | |
768 | |
769 EXPECT_LE(expected_ms_since_first_update, | |
770 metric_worker_self_update_response_time_since_first_ms.value()); | |
771 EXPECT_GT(expected_ms_since_first_update + 10 * kMsPerSec, | |
772 metric_worker_self_update_response_time_since_first_ms.value()); | |
773 | |
774 EXPECT_EQ(0, metric_worker_app_max_update_responses_app_high.value()); | |
775 EXPECT_EQ(0, metric_worker_app_max_update_responses.value()); | |
776 EXPECT_EQ(0, metric_worker_app_max_update_responses_ms_since_first.value()); | |
777 } | |
778 | |
779 TEST_F(RecordUpdateAvailableUsageStatsTest, OneAppOnly) { | |
780 ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientStateKeyPathUser, | |
781 _T("UpdateAvailableCount"), | |
782 static_cast<DWORD>(123456))); | |
783 ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientStateKeyPathUser, | |
784 _T("UpdateAvailableSince"), | |
785 static_cast<DWORD64>(10))); | |
786 | |
787 ASSERT_EQ(2, GetNumProducts()); | |
788 | |
789 const time64 current_time_100ns(GetCurrent100NSTime()); | |
790 const int64 expected_ms_since_first_update = | |
791 (current_time_100ns - 10) / kMillisecsTo100ns; | |
792 | |
793 internal::RecordUpdateAvailableUsageStats(); | |
794 | |
795 EXPECT_EQ(0, metric_worker_self_update_responses.value()); | |
796 EXPECT_EQ(0, metric_worker_self_update_response_time_since_first_ms.value()); | |
797 | |
798 EXPECT_EQ(kApp1GuidUpper, | |
799 metric_worker_app_max_update_responses_app_high.value()); | |
800 EXPECT_EQ(123456, metric_worker_app_max_update_responses.value()); | |
801 EXPECT_LE(expected_ms_since_first_update, | |
802 metric_worker_app_max_update_responses_ms_since_first.value()); | |
803 EXPECT_GT(expected_ms_since_first_update + 10 * kMsPerSec, | |
804 metric_worker_app_max_update_responses_ms_since_first.value()); | |
805 } | |
806 | |
807 // It is important that Omaha's count is the largest. | |
808 // All app data should be from app 2, which has the greatest count, a middle | |
809 // time, and an alphabetically middle GUID | |
810 TEST_F(RecordUpdateAvailableUsageStatsTest, OmahaAndSeveralApps) { | |
811 const DWORD64 kApp2SinceTime = 1000 * kSecsTo100ns; | |
812 | |
813 ASSERT_SUCCEEDED(RegKey::SetValue(kApp2ClientsKeyPathUser, | |
814 kRegValueProductVersion, | |
815 _T("1.2"))); | |
816 ASSERT_SUCCEEDED(RegKey::SetValue(kApp3ClientsKeyPathUser, | |
817 kRegValueProductVersion, | |
818 _T("2.3"))); | |
819 | |
820 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENT_STATE_GOOPDATE, | |
821 _T("UpdateAvailableCount"), | |
822 static_cast<DWORD>(0x99887766))); | |
823 ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENT_STATE_GOOPDATE, | |
824 _T("UpdateAvailableSince"), | |
825 static_cast<DWORD64>(1))); | |
826 | |
827 ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientStateKeyPathUser, | |
828 _T("UpdateAvailableCount"), | |
829 static_cast<DWORD>(1))); | |
830 ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientStateKeyPathUser, | |
831 _T("UpdateAvailableSince"), | |
832 static_cast<DWORD64>(1))); | |
833 | |
834 ASSERT_SUCCEEDED(RegKey::SetValue(kApp2ClientStateKeyPathUser, | |
835 _T("UpdateAvailableCount"), | |
836 static_cast<DWORD>(9876543))); | |
837 ASSERT_SUCCEEDED(RegKey::SetValue(kApp2ClientStateKeyPathUser, | |
838 _T("UpdateAvailableSince"), | |
839 kApp2SinceTime)); | |
840 | |
841 ASSERT_SUCCEEDED(RegKey::SetValue(kApp3ClientStateKeyPathUser, | |
842 _T("UpdateAvailableCount"), | |
843 static_cast<DWORD>(234))); | |
844 ASSERT_SUCCEEDED(RegKey::SetValue(kApp3ClientStateKeyPathUser, | |
845 _T("UpdateAvailableSince"), | |
846 static_cast<DWORD64>(128580000000000000))); | |
847 | |
848 ASSERT_EQ(4, GetNumProducts()); | |
849 | |
850 const time64 current_time_100ns(GetCurrent100NSTime()); | |
851 const int64 goopdate_expected_ms_since_first_update = | |
852 (current_time_100ns - 1) / kMillisecsTo100ns; | |
853 | |
854 const int64 app_expected_ms_since_first_update = | |
855 (current_time_100ns - kApp2SinceTime) / kMillisecsTo100ns; | |
856 | |
857 internal::RecordUpdateAvailableUsageStats(); | |
858 | |
859 EXPECT_EQ(0x99887766, metric_worker_self_update_responses.value()); | |
860 EXPECT_LE(goopdate_expected_ms_since_first_update, | |
861 metric_worker_self_update_response_time_since_first_ms.value()); | |
862 EXPECT_GT(goopdate_expected_ms_since_first_update + 10 * kMsPerSec, | |
863 metric_worker_self_update_response_time_since_first_ms.value()); | |
864 | |
865 EXPECT_EQ(kApp2GuidUpper, | |
866 metric_worker_app_max_update_responses_app_high.value()); | |
867 EXPECT_EQ(9876543, metric_worker_app_max_update_responses.value()); | |
868 EXPECT_LE(app_expected_ms_since_first_update, | |
869 metric_worker_app_max_update_responses_ms_since_first.value()); | |
870 EXPECT_GT(app_expected_ms_since_first_update + 10 * kMsPerSec, | |
871 metric_worker_app_max_update_responses_ms_since_first.value()); | |
872 } | |
873 | |
874 } // namespace omaha | |
OLD | NEW |