1 // 2 // Copyright (C) 2012 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "update_engine/update_attempter.h" 18 19 #include <stdint.h> 20 21 #include <memory> 22 23 #include <base/files/file_util.h> 24 #include <base/message_loop/message_loop.h> 25 #include <brillo/bind_lambda.h> 26 #include <brillo/make_unique_ptr.h> 27 #include <brillo/message_loops/base_message_loop.h> 28 #include <brillo/message_loops/message_loop.h> 29 #include <brillo/message_loops/message_loop_utils.h> 30 #include <gtest/gtest.h> 31 #include <policy/libpolicy.h> 32 #include <policy/mock_device_policy.h> 33 34 #if USE_LIBCROS 35 #include "network_proxy/dbus-proxies.h" 36 #include "network_proxy/dbus-proxy-mocks.h" 37 #endif // USE_LIBCROS 38 #include "update_engine/common/fake_clock.h" 39 #include "update_engine/common/fake_prefs.h" 40 #include "update_engine/common/mock_action.h" 41 #include "update_engine/common/mock_action_processor.h" 42 #include "update_engine/common/mock_http_fetcher.h" 43 #include "update_engine/common/mock_prefs.h" 44 #include "update_engine/common/platform_constants.h" 45 #include "update_engine/common/prefs.h" 46 #include "update_engine/common/test_utils.h" 47 #include "update_engine/common/utils.h" 48 #include "update_engine/fake_system_state.h" 49 #include "update_engine/mock_p2p_manager.h" 50 #include "update_engine/mock_payload_state.h" 51 #include "update_engine/payload_consumer/filesystem_verifier_action.h" 52 #include "update_engine/payload_consumer/install_plan.h" 53 #include "update_engine/payload_consumer/payload_constants.h" 54 #include "update_engine/payload_consumer/postinstall_runner_action.h" 55 56 namespace org { 57 namespace chromium { 58 class NetworkProxyServiceInterfaceProxyMock; 59 } // namespace chromium 60 } // namespace org 61 62 using base::Time; 63 using base::TimeDelta; 64 using org::chromium::NetworkProxyServiceInterfaceProxyInterface; 65 using org::chromium::NetworkProxyServiceInterfaceProxyMock; 66 using std::string; 67 using std::unique_ptr; 68 using testing::DoAll; 69 using testing::InSequence; 70 using testing::Ne; 71 using testing::NiceMock; 72 using testing::Property; 73 using testing::Return; 74 using testing::ReturnPointee; 75 using testing::SaveArg; 76 using testing::SetArgumentPointee; 77 using testing::_; 78 using update_engine::UpdateStatus; 79 80 namespace chromeos_update_engine { 81 82 // Test a subclass rather than the main class directly so that we can mock out 83 // methods within the class. There're explicit unit tests for the mocked out 84 // methods. 85 class UpdateAttempterUnderTest : public UpdateAttempter { 86 public: 87 UpdateAttempterUnderTest( 88 SystemState* system_state, 89 NetworkProxyServiceInterfaceProxyInterface* network_proxy_service_proxy) 90 : UpdateAttempter(system_state, nullptr, network_proxy_service_proxy) {} 91 92 // Wrap the update scheduling method, allowing us to opt out of scheduled 93 // updates for testing purposes. 94 void ScheduleUpdates() override { 95 schedule_updates_called_ = true; 96 if (do_schedule_updates_) { 97 UpdateAttempter::ScheduleUpdates(); 98 } else { 99 LOG(INFO) << "[TEST] Update scheduling disabled."; 100 } 101 } 102 void EnableScheduleUpdates() { do_schedule_updates_ = true; } 103 void DisableScheduleUpdates() { do_schedule_updates_ = false; } 104 105 // Indicates whether ScheduleUpdates() was called. 106 bool schedule_updates_called() const { return schedule_updates_called_; } 107 108 // Need to expose forced_omaha_url_ so we can test it. 109 const string& forced_omaha_url() const { return forced_omaha_url_; } 110 111 private: 112 bool schedule_updates_called_ = false; 113 bool do_schedule_updates_ = true; 114 }; 115 116 class UpdateAttempterTest : public ::testing::Test { 117 protected: 118 UpdateAttempterTest() 119 : certificate_checker_(fake_system_state_.mock_prefs(), 120 &openssl_wrapper_) { 121 // Override system state members. 122 fake_system_state_.set_connection_manager(&mock_connection_manager); 123 fake_system_state_.set_update_attempter(&attempter_); 124 loop_.SetAsCurrent(); 125 126 certificate_checker_.Init(); 127 128 // Finish initializing the attempter. 129 attempter_.Init(); 130 } 131 132 void SetUp() override { 133 EXPECT_NE(nullptr, attempter_.system_state_); 134 EXPECT_EQ(0, attempter_.http_response_code_); 135 EXPECT_EQ(UpdateStatus::IDLE, attempter_.status_); 136 EXPECT_EQ(0.0, attempter_.download_progress_); 137 EXPECT_EQ(0, attempter_.last_checked_time_); 138 EXPECT_EQ("0.0.0.0", attempter_.new_version_); 139 EXPECT_EQ(0, attempter_.new_payload_size_); 140 processor_ = new NiceMock<MockActionProcessor>(); 141 attempter_.processor_.reset(processor_); // Transfers ownership. 142 prefs_ = fake_system_state_.mock_prefs(); 143 144 // Set up store/load semantics of P2P properties via the mock PayloadState. 145 actual_using_p2p_for_downloading_ = false; 146 EXPECT_CALL(*fake_system_state_.mock_payload_state(), 147 SetUsingP2PForDownloading(_)) 148 .WillRepeatedly(SaveArg<0>(&actual_using_p2p_for_downloading_)); 149 EXPECT_CALL(*fake_system_state_.mock_payload_state(), 150 GetUsingP2PForDownloading()) 151 .WillRepeatedly(ReturnPointee(&actual_using_p2p_for_downloading_)); 152 actual_using_p2p_for_sharing_ = false; 153 EXPECT_CALL(*fake_system_state_.mock_payload_state(), 154 SetUsingP2PForSharing(_)) 155 .WillRepeatedly(SaveArg<0>(&actual_using_p2p_for_sharing_)); 156 EXPECT_CALL(*fake_system_state_.mock_payload_state(), 157 GetUsingP2PForDownloading()) 158 .WillRepeatedly(ReturnPointee(&actual_using_p2p_for_sharing_)); 159 } 160 161 public: 162 void ScheduleQuitMainLoop(); 163 164 // Callbacks to run the different tests from the main loop. 165 void UpdateTestStart(); 166 void UpdateTestVerify(); 167 void RollbackTestStart(bool enterprise_rollback, bool valid_slot); 168 void RollbackTestVerify(); 169 void PingOmahaTestStart(); 170 void ReadScatterFactorFromPolicyTestStart(); 171 void DecrementUpdateCheckCountTestStart(); 172 void NoScatteringDoneDuringManualUpdateTestStart(); 173 void P2PNotEnabledStart(); 174 void P2PEnabledStart(); 175 void P2PEnabledInteractiveStart(); 176 void P2PEnabledStartingFailsStart(); 177 void P2PEnabledHousekeepingFailsStart(); 178 179 bool actual_using_p2p_for_downloading() { 180 return actual_using_p2p_for_downloading_; 181 } 182 bool actual_using_p2p_for_sharing() { 183 return actual_using_p2p_for_sharing_; 184 } 185 186 base::MessageLoopForIO base_loop_; 187 brillo::BaseMessageLoop loop_{&base_loop_}; 188 189 FakeSystemState fake_system_state_; 190 #if USE_LIBCROS 191 NetworkProxyServiceInterfaceProxyMock network_proxy_service_proxy_mock_; 192 UpdateAttempterUnderTest attempter_{&fake_system_state_, 193 &network_proxy_service_proxy_mock_}; 194 #else 195 UpdateAttempterUnderTest attempter_{&fake_system_state_, nullptr}; 196 #endif // USE_LIBCROS 197 OpenSSLWrapper openssl_wrapper_; 198 CertificateChecker certificate_checker_; 199 200 NiceMock<MockActionProcessor>* processor_; 201 NiceMock<MockPrefs>* prefs_; // Shortcut to fake_system_state_->mock_prefs(). 202 NiceMock<MockConnectionManager> mock_connection_manager; 203 204 bool actual_using_p2p_for_downloading_; 205 bool actual_using_p2p_for_sharing_; 206 }; 207 208 void UpdateAttempterTest::ScheduleQuitMainLoop() { 209 loop_.PostTask( 210 FROM_HERE, 211 base::Bind([](brillo::BaseMessageLoop* loop) { loop->BreakLoop(); }, 212 base::Unretained(&loop_))); 213 } 214 215 TEST_F(UpdateAttempterTest, ActionCompletedDownloadTest) { 216 unique_ptr<MockHttpFetcher> fetcher(new MockHttpFetcher("", 0, nullptr)); 217 fetcher->FailTransfer(503); // Sets the HTTP response code. 218 DownloadAction action(prefs_, nullptr, nullptr, nullptr, fetcher.release()); 219 EXPECT_CALL(*prefs_, GetInt64(kPrefsDeltaUpdateFailures, _)).Times(0); 220 attempter_.ActionCompleted(nullptr, &action, ErrorCode::kSuccess); 221 EXPECT_EQ(UpdateStatus::FINALIZING, attempter_.status()); 222 ASSERT_EQ(nullptr, attempter_.error_event_.get()); 223 } 224 225 TEST_F(UpdateAttempterTest, ActionCompletedErrorTest) { 226 MockAction action; 227 EXPECT_CALL(action, Type()).WillRepeatedly(Return("MockAction")); 228 attempter_.status_ = UpdateStatus::DOWNLOADING; 229 EXPECT_CALL(*prefs_, GetInt64(kPrefsDeltaUpdateFailures, _)) 230 .WillOnce(Return(false)); 231 attempter_.ActionCompleted(nullptr, &action, ErrorCode::kError); 232 ASSERT_NE(nullptr, attempter_.error_event_.get()); 233 } 234 235 TEST_F(UpdateAttempterTest, ActionCompletedOmahaRequestTest) { 236 unique_ptr<MockHttpFetcher> fetcher(new MockHttpFetcher("", 0, nullptr)); 237 fetcher->FailTransfer(500); // Sets the HTTP response code. 238 OmahaRequestAction action(&fake_system_state_, nullptr, 239 std::move(fetcher), false); 240 ObjectCollectorAction<OmahaResponse> collector_action; 241 BondActions(&action, &collector_action); 242 OmahaResponse response; 243 response.poll_interval = 234; 244 action.SetOutputObject(response); 245 EXPECT_CALL(*prefs_, GetInt64(kPrefsDeltaUpdateFailures, _)).Times(0); 246 attempter_.ActionCompleted(nullptr, &action, ErrorCode::kSuccess); 247 EXPECT_EQ(500, attempter_.http_response_code()); 248 EXPECT_EQ(UpdateStatus::IDLE, attempter_.status()); 249 EXPECT_EQ(234U, attempter_.server_dictated_poll_interval_); 250 ASSERT_TRUE(attempter_.error_event_.get() == nullptr); 251 } 252 253 TEST_F(UpdateAttempterTest, ConstructWithUpdatedMarkerTest) { 254 FakePrefs fake_prefs; 255 string boot_id; 256 EXPECT_TRUE(utils::GetBootId(&boot_id)); 257 fake_prefs.SetString(kPrefsUpdateCompletedOnBootId, boot_id); 258 fake_system_state_.set_prefs(&fake_prefs); 259 attempter_.Init(); 260 EXPECT_EQ(UpdateStatus::UPDATED_NEED_REBOOT, attempter_.status()); 261 } 262 263 TEST_F(UpdateAttempterTest, GetErrorCodeForActionTest) { 264 extern ErrorCode GetErrorCodeForAction(AbstractAction* action, 265 ErrorCode code); 266 EXPECT_EQ(ErrorCode::kSuccess, 267 GetErrorCodeForAction(nullptr, ErrorCode::kSuccess)); 268 269 FakeSystemState fake_system_state; 270 OmahaRequestAction omaha_request_action(&fake_system_state, nullptr, 271 nullptr, false); 272 EXPECT_EQ(ErrorCode::kOmahaRequestError, 273 GetErrorCodeForAction(&omaha_request_action, ErrorCode::kError)); 274 OmahaResponseHandlerAction omaha_response_handler_action(&fake_system_state_); 275 EXPECT_EQ(ErrorCode::kOmahaResponseHandlerError, 276 GetErrorCodeForAction(&omaha_response_handler_action, 277 ErrorCode::kError)); 278 FilesystemVerifierAction filesystem_verifier_action; 279 EXPECT_EQ(ErrorCode::kFilesystemVerifierError, 280 GetErrorCodeForAction(&filesystem_verifier_action, 281 ErrorCode::kError)); 282 PostinstallRunnerAction postinstall_runner_action( 283 fake_system_state.fake_boot_control(), fake_system_state.fake_hardware()); 284 EXPECT_EQ(ErrorCode::kPostinstallRunnerError, 285 GetErrorCodeForAction(&postinstall_runner_action, 286 ErrorCode::kError)); 287 MockAction action_mock; 288 EXPECT_CALL(action_mock, Type()).WillOnce(Return("MockAction")); 289 EXPECT_EQ(ErrorCode::kError, 290 GetErrorCodeForAction(&action_mock, ErrorCode::kError)); 291 } 292 293 TEST_F(UpdateAttempterTest, DisableDeltaUpdateIfNeededTest) { 294 attempter_.omaha_request_params_->set_delta_okay(true); 295 EXPECT_CALL(*prefs_, GetInt64(kPrefsDeltaUpdateFailures, _)) 296 .WillOnce(Return(false)); 297 attempter_.DisableDeltaUpdateIfNeeded(); 298 EXPECT_TRUE(attempter_.omaha_request_params_->delta_okay()); 299 EXPECT_CALL(*prefs_, GetInt64(kPrefsDeltaUpdateFailures, _)) 300 .WillOnce(DoAll( 301 SetArgumentPointee<1>(UpdateAttempter::kMaxDeltaUpdateFailures - 1), 302 Return(true))); 303 attempter_.DisableDeltaUpdateIfNeeded(); 304 EXPECT_TRUE(attempter_.omaha_request_params_->delta_okay()); 305 EXPECT_CALL(*prefs_, GetInt64(kPrefsDeltaUpdateFailures, _)) 306 .WillOnce(DoAll( 307 SetArgumentPointee<1>(UpdateAttempter::kMaxDeltaUpdateFailures), 308 Return(true))); 309 attempter_.DisableDeltaUpdateIfNeeded(); 310 EXPECT_FALSE(attempter_.omaha_request_params_->delta_okay()); 311 EXPECT_CALL(*prefs_, GetInt64(_, _)).Times(0); 312 attempter_.DisableDeltaUpdateIfNeeded(); 313 EXPECT_FALSE(attempter_.omaha_request_params_->delta_okay()); 314 } 315 316 TEST_F(UpdateAttempterTest, MarkDeltaUpdateFailureTest) { 317 EXPECT_CALL(*prefs_, GetInt64(kPrefsDeltaUpdateFailures, _)) 318 .WillOnce(Return(false)) 319 .WillOnce(DoAll(SetArgumentPointee<1>(-1), Return(true))) 320 .WillOnce(DoAll(SetArgumentPointee<1>(1), Return(true))) 321 .WillOnce(DoAll( 322 SetArgumentPointee<1>(UpdateAttempter::kMaxDeltaUpdateFailures), 323 Return(true))); 324 EXPECT_CALL(*prefs_, SetInt64(Ne(kPrefsDeltaUpdateFailures), _)) 325 .WillRepeatedly(Return(true)); 326 EXPECT_CALL(*prefs_, SetInt64(kPrefsDeltaUpdateFailures, 1)).Times(2); 327 EXPECT_CALL(*prefs_, SetInt64(kPrefsDeltaUpdateFailures, 2)); 328 EXPECT_CALL(*prefs_, SetInt64(kPrefsDeltaUpdateFailures, 329 UpdateAttempter::kMaxDeltaUpdateFailures + 1)); 330 for (int i = 0; i < 4; i ++) 331 attempter_.MarkDeltaUpdateFailure(); 332 } 333 334 TEST_F(UpdateAttempterTest, ScheduleErrorEventActionNoEventTest) { 335 EXPECT_CALL(*processor_, EnqueueAction(_)).Times(0); 336 EXPECT_CALL(*processor_, StartProcessing()).Times(0); 337 EXPECT_CALL(*fake_system_state_.mock_payload_state(), UpdateFailed(_)) 338 .Times(0); 339 OmahaResponse response; 340 string url1 = "http://url1"; 341 response.packages.push_back({.payload_urls = {url1, "https://url"}}); 342 EXPECT_CALL(*(fake_system_state_.mock_payload_state()), GetCurrentUrl()) 343 .WillRepeatedly(Return(url1)); 344 fake_system_state_.mock_payload_state()->SetResponse(response); 345 attempter_.ScheduleErrorEventAction(); 346 EXPECT_EQ(url1, fake_system_state_.mock_payload_state()->GetCurrentUrl()); 347 } 348 349 TEST_F(UpdateAttempterTest, ScheduleErrorEventActionTest) { 350 EXPECT_CALL(*processor_, 351 EnqueueAction(Property(&AbstractAction::Type, 352 OmahaRequestAction::StaticType()))); 353 EXPECT_CALL(*processor_, StartProcessing()); 354 ErrorCode err = ErrorCode::kError; 355 EXPECT_CALL(*fake_system_state_.mock_payload_state(), UpdateFailed(err)); 356 attempter_.error_event_.reset(new OmahaEvent(OmahaEvent::kTypeUpdateComplete, 357 OmahaEvent::kResultError, 358 err)); 359 attempter_.ScheduleErrorEventAction(); 360 EXPECT_EQ(UpdateStatus::REPORTING_ERROR_EVENT, attempter_.status()); 361 } 362 363 namespace { 364 // Actions that will be built as part of an update check. 365 const string kUpdateActionTypes[] = { // NOLINT(runtime/string) 366 OmahaRequestAction::StaticType(), 367 OmahaResponseHandlerAction::StaticType(), 368 OmahaRequestAction::StaticType(), 369 DownloadAction::StaticType(), 370 OmahaRequestAction::StaticType(), 371 FilesystemVerifierAction::StaticType(), 372 PostinstallRunnerAction::StaticType(), 373 OmahaRequestAction::StaticType() 374 }; 375 376 // Actions that will be built as part of a user-initiated rollback. 377 const string kRollbackActionTypes[] = { // NOLINT(runtime/string) 378 InstallPlanAction::StaticType(), 379 PostinstallRunnerAction::StaticType(), 380 }; 381 382 } // namespace 383 384 void UpdateAttempterTest::UpdateTestStart() { 385 attempter_.set_http_response_code(200); 386 387 // Expect that the device policy is loaded by the UpdateAttempter at some 388 // point by calling RefreshDevicePolicy. 389 policy::MockDevicePolicy* device_policy = new policy::MockDevicePolicy(); 390 attempter_.policy_provider_.reset(new policy::PolicyProvider(device_policy)); 391 EXPECT_CALL(*device_policy, LoadPolicy()) 392 .Times(testing::AtLeast(1)).WillRepeatedly(Return(true)); 393 394 { 395 InSequence s; 396 for (size_t i = 0; i < arraysize(kUpdateActionTypes); ++i) { 397 EXPECT_CALL(*processor_, 398 EnqueueAction(Property(&AbstractAction::Type, 399 kUpdateActionTypes[i]))); 400 } 401 EXPECT_CALL(*processor_, StartProcessing()); 402 } 403 404 attempter_.Update("", "", "", "", false, false); 405 loop_.PostTask(FROM_HERE, 406 base::Bind(&UpdateAttempterTest::UpdateTestVerify, 407 base::Unretained(this))); 408 } 409 410 void UpdateAttempterTest::UpdateTestVerify() { 411 EXPECT_EQ(0, attempter_.http_response_code()); 412 EXPECT_EQ(&attempter_, processor_->delegate()); 413 EXPECT_EQ(arraysize(kUpdateActionTypes), attempter_.actions_.size()); 414 for (size_t i = 0; i < arraysize(kUpdateActionTypes); ++i) { 415 EXPECT_EQ(kUpdateActionTypes[i], attempter_.actions_[i]->Type()); 416 } 417 EXPECT_EQ(attempter_.response_handler_action_.get(), 418 attempter_.actions_[1].get()); 419 AbstractAction* action_3 = attempter_.actions_[3].get(); 420 ASSERT_NE(nullptr, action_3); 421 ASSERT_EQ(DownloadAction::StaticType(), action_3->Type()); 422 DownloadAction* download_action = static_cast<DownloadAction*>(action_3); 423 EXPECT_EQ(&attempter_, download_action->delegate()); 424 EXPECT_EQ(UpdateStatus::CHECKING_FOR_UPDATE, attempter_.status()); 425 loop_.BreakLoop(); 426 } 427 428 void UpdateAttempterTest::RollbackTestStart( 429 bool enterprise_rollback, bool valid_slot) { 430 // Create a device policy so that we can change settings. 431 policy::MockDevicePolicy* device_policy = new policy::MockDevicePolicy(); 432 attempter_.policy_provider_.reset(new policy::PolicyProvider(device_policy)); 433 434 EXPECT_CALL(*device_policy, LoadPolicy()).WillRepeatedly(Return(true)); 435 fake_system_state_.set_device_policy(device_policy); 436 437 if (valid_slot) { 438 BootControlInterface::Slot rollback_slot = 1; 439 LOG(INFO) << "Test Mark Bootable: " 440 << BootControlInterface::SlotName(rollback_slot); 441 fake_system_state_.fake_boot_control()->SetSlotBootable(rollback_slot, 442 true); 443 } 444 445 bool is_rollback_allowed = false; 446 447 // We only allow rollback on devices that are not enterprise enrolled and 448 // which have a valid slot to rollback to. 449 if (!enterprise_rollback && valid_slot) { 450 is_rollback_allowed = true; 451 } 452 453 if (enterprise_rollback) { 454 // We return an empty owner as this is an enterprise. 455 EXPECT_CALL(*device_policy, GetOwner(_)).WillRepeatedly( 456 DoAll(SetArgumentPointee<0>(string("")), 457 Return(true))); 458 } else { 459 // We return a fake owner as this is an owned consumer device. 460 EXPECT_CALL(*device_policy, GetOwner(_)).WillRepeatedly( 461 DoAll(SetArgumentPointee<0>(string("fake.mail (at) fake.com")), 462 Return(true))); 463 } 464 465 if (is_rollback_allowed) { 466 InSequence s; 467 for (size_t i = 0; i < arraysize(kRollbackActionTypes); ++i) { 468 EXPECT_CALL(*processor_, 469 EnqueueAction(Property(&AbstractAction::Type, 470 kRollbackActionTypes[i]))); 471 } 472 EXPECT_CALL(*processor_, StartProcessing()); 473 474 EXPECT_TRUE(attempter_.Rollback(true)); 475 loop_.PostTask(FROM_HERE, 476 base::Bind(&UpdateAttempterTest::RollbackTestVerify, 477 base::Unretained(this))); 478 } else { 479 EXPECT_FALSE(attempter_.Rollback(true)); 480 loop_.BreakLoop(); 481 } 482 } 483 484 void UpdateAttempterTest::RollbackTestVerify() { 485 // Verifies the actions that were enqueued. 486 EXPECT_EQ(&attempter_, processor_->delegate()); 487 EXPECT_EQ(arraysize(kRollbackActionTypes), attempter_.actions_.size()); 488 for (size_t i = 0; i < arraysize(kRollbackActionTypes); ++i) { 489 EXPECT_EQ(kRollbackActionTypes[i], attempter_.actions_[i]->Type()); 490 } 491 EXPECT_EQ(UpdateStatus::ATTEMPTING_ROLLBACK, attempter_.status()); 492 AbstractAction* action_0 = attempter_.actions_[0].get(); 493 ASSERT_NE(nullptr, action_0); 494 ASSERT_EQ(InstallPlanAction::StaticType(), action_0->Type()); 495 InstallPlanAction* install_plan_action = 496 static_cast<InstallPlanAction*>(action_0); 497 InstallPlan* install_plan = install_plan_action->install_plan(); 498 EXPECT_EQ(0U, install_plan->partitions.size()); 499 EXPECT_EQ(install_plan->powerwash_required, true); 500 loop_.BreakLoop(); 501 } 502 503 TEST_F(UpdateAttempterTest, UpdateTest) { 504 UpdateTestStart(); 505 loop_.Run(); 506 } 507 508 TEST_F(UpdateAttempterTest, RollbackTest) { 509 loop_.PostTask(FROM_HERE, 510 base::Bind(&UpdateAttempterTest::RollbackTestStart, 511 base::Unretained(this), 512 false, true)); 513 loop_.Run(); 514 } 515 516 TEST_F(UpdateAttempterTest, InvalidSlotRollbackTest) { 517 loop_.PostTask(FROM_HERE, 518 base::Bind(&UpdateAttempterTest::RollbackTestStart, 519 base::Unretained(this), 520 false, false)); 521 loop_.Run(); 522 } 523 524 TEST_F(UpdateAttempterTest, EnterpriseRollbackTest) { 525 loop_.PostTask(FROM_HERE, 526 base::Bind(&UpdateAttempterTest::RollbackTestStart, 527 base::Unretained(this), 528 true, true)); 529 loop_.Run(); 530 } 531 532 void UpdateAttempterTest::PingOmahaTestStart() { 533 EXPECT_CALL(*processor_, 534 EnqueueAction(Property(&AbstractAction::Type, 535 OmahaRequestAction::StaticType()))); 536 EXPECT_CALL(*processor_, StartProcessing()); 537 attempter_.PingOmaha(); 538 ScheduleQuitMainLoop(); 539 } 540 541 TEST_F(UpdateAttempterTest, PingOmahaTest) { 542 EXPECT_FALSE(attempter_.waiting_for_scheduled_check_); 543 EXPECT_FALSE(attempter_.schedule_updates_called()); 544 // Disable scheduling of subsequnet checks; we're using the DefaultPolicy in 545 // testing, which is more permissive than we want to handle here. 546 attempter_.DisableScheduleUpdates(); 547 loop_.PostTask(FROM_HERE, 548 base::Bind(&UpdateAttempterTest::PingOmahaTestStart, 549 base::Unretained(this))); 550 brillo::MessageLoopRunMaxIterations(&loop_, 100); 551 EXPECT_EQ(UpdateStatus::UPDATED_NEED_REBOOT, attempter_.status()); 552 EXPECT_TRUE(attempter_.schedule_updates_called()); 553 } 554 555 TEST_F(UpdateAttempterTest, CreatePendingErrorEventTest) { 556 MockAction action; 557 const ErrorCode kCode = ErrorCode::kDownloadTransferError; 558 attempter_.CreatePendingErrorEvent(&action, kCode); 559 ASSERT_NE(nullptr, attempter_.error_event_.get()); 560 EXPECT_EQ(OmahaEvent::kTypeUpdateComplete, attempter_.error_event_->type); 561 EXPECT_EQ(OmahaEvent::kResultError, attempter_.error_event_->result); 562 EXPECT_EQ( 563 static_cast<ErrorCode>(static_cast<int>(kCode) | 564 static_cast<int>(ErrorCode::kTestOmahaUrlFlag)), 565 attempter_.error_event_->error_code); 566 } 567 568 TEST_F(UpdateAttempterTest, CreatePendingErrorEventResumedTest) { 569 OmahaResponseHandlerAction *response_action = 570 new OmahaResponseHandlerAction(&fake_system_state_); 571 response_action->install_plan_.is_resume = true; 572 attempter_.response_handler_action_.reset(response_action); 573 MockAction action; 574 const ErrorCode kCode = ErrorCode::kInstallDeviceOpenError; 575 attempter_.CreatePendingErrorEvent(&action, kCode); 576 ASSERT_NE(nullptr, attempter_.error_event_.get()); 577 EXPECT_EQ(OmahaEvent::kTypeUpdateComplete, attempter_.error_event_->type); 578 EXPECT_EQ(OmahaEvent::kResultError, attempter_.error_event_->result); 579 EXPECT_EQ( 580 static_cast<ErrorCode>( 581 static_cast<int>(kCode) | 582 static_cast<int>(ErrorCode::kResumedFlag) | 583 static_cast<int>(ErrorCode::kTestOmahaUrlFlag)), 584 attempter_.error_event_->error_code); 585 } 586 587 TEST_F(UpdateAttempterTest, P2PNotStartedAtStartupWhenNotEnabled) { 588 MockP2PManager mock_p2p_manager; 589 fake_system_state_.set_p2p_manager(&mock_p2p_manager); 590 mock_p2p_manager.fake().SetP2PEnabled(false); 591 EXPECT_CALL(mock_p2p_manager, EnsureP2PRunning()).Times(0); 592 attempter_.UpdateEngineStarted(); 593 } 594 595 TEST_F(UpdateAttempterTest, P2PNotStartedAtStartupWhenEnabledButNotSharing) { 596 MockP2PManager mock_p2p_manager; 597 fake_system_state_.set_p2p_manager(&mock_p2p_manager); 598 mock_p2p_manager.fake().SetP2PEnabled(true); 599 EXPECT_CALL(mock_p2p_manager, EnsureP2PRunning()).Times(0); 600 attempter_.UpdateEngineStarted(); 601 } 602 603 TEST_F(UpdateAttempterTest, P2PStartedAtStartupWhenEnabledAndSharing) { 604 MockP2PManager mock_p2p_manager; 605 fake_system_state_.set_p2p_manager(&mock_p2p_manager); 606 mock_p2p_manager.fake().SetP2PEnabled(true); 607 mock_p2p_manager.fake().SetCountSharedFilesResult(1); 608 EXPECT_CALL(mock_p2p_manager, EnsureP2PRunning()); 609 attempter_.UpdateEngineStarted(); 610 } 611 612 TEST_F(UpdateAttempterTest, P2PNotEnabled) { 613 loop_.PostTask(FROM_HERE, 614 base::Bind(&UpdateAttempterTest::P2PNotEnabledStart, 615 base::Unretained(this))); 616 loop_.Run(); 617 } 618 619 void UpdateAttempterTest::P2PNotEnabledStart() { 620 // If P2P is not enabled, check that we do not attempt housekeeping 621 // and do not convey that p2p is to be used. 622 MockP2PManager mock_p2p_manager; 623 fake_system_state_.set_p2p_manager(&mock_p2p_manager); 624 mock_p2p_manager.fake().SetP2PEnabled(false); 625 EXPECT_CALL(mock_p2p_manager, PerformHousekeeping()).Times(0); 626 attempter_.Update("", "", "", "", false, false); 627 EXPECT_FALSE(actual_using_p2p_for_downloading_); 628 EXPECT_FALSE(actual_using_p2p_for_sharing()); 629 ScheduleQuitMainLoop(); 630 } 631 632 TEST_F(UpdateAttempterTest, P2PEnabledStartingFails) { 633 loop_.PostTask(FROM_HERE, 634 base::Bind(&UpdateAttempterTest::P2PEnabledStartingFailsStart, 635 base::Unretained(this))); 636 loop_.Run(); 637 } 638 639 void UpdateAttempterTest::P2PEnabledStartingFailsStart() { 640 // If p2p is enabled, but starting it fails ensure we don't do 641 // any housekeeping and do not convey that p2p should be used. 642 MockP2PManager mock_p2p_manager; 643 fake_system_state_.set_p2p_manager(&mock_p2p_manager); 644 mock_p2p_manager.fake().SetP2PEnabled(true); 645 mock_p2p_manager.fake().SetEnsureP2PRunningResult(false); 646 mock_p2p_manager.fake().SetPerformHousekeepingResult(false); 647 EXPECT_CALL(mock_p2p_manager, PerformHousekeeping()).Times(0); 648 attempter_.Update("", "", "", "", false, false); 649 EXPECT_FALSE(actual_using_p2p_for_downloading()); 650 EXPECT_FALSE(actual_using_p2p_for_sharing()); 651 ScheduleQuitMainLoop(); 652 } 653 654 TEST_F(UpdateAttempterTest, P2PEnabledHousekeepingFails) { 655 loop_.PostTask( 656 FROM_HERE, 657 base::Bind(&UpdateAttempterTest::P2PEnabledHousekeepingFailsStart, 658 base::Unretained(this))); 659 loop_.Run(); 660 } 661 662 void UpdateAttempterTest::P2PEnabledHousekeepingFailsStart() { 663 // If p2p is enabled, starting it works but housekeeping fails, ensure 664 // we do not convey p2p is to be used. 665 MockP2PManager mock_p2p_manager; 666 fake_system_state_.set_p2p_manager(&mock_p2p_manager); 667 mock_p2p_manager.fake().SetP2PEnabled(true); 668 mock_p2p_manager.fake().SetEnsureP2PRunningResult(true); 669 mock_p2p_manager.fake().SetPerformHousekeepingResult(false); 670 EXPECT_CALL(mock_p2p_manager, PerformHousekeeping()); 671 attempter_.Update("", "", "", "", false, false); 672 EXPECT_FALSE(actual_using_p2p_for_downloading()); 673 EXPECT_FALSE(actual_using_p2p_for_sharing()); 674 ScheduleQuitMainLoop(); 675 } 676 677 TEST_F(UpdateAttempterTest, P2PEnabled) { 678 loop_.PostTask(FROM_HERE, 679 base::Bind(&UpdateAttempterTest::P2PEnabledStart, 680 base::Unretained(this))); 681 loop_.Run(); 682 } 683 684 void UpdateAttempterTest::P2PEnabledStart() { 685 MockP2PManager mock_p2p_manager; 686 fake_system_state_.set_p2p_manager(&mock_p2p_manager); 687 // If P2P is enabled and starting it works, check that we performed 688 // housekeeping and that we convey p2p should be used. 689 mock_p2p_manager.fake().SetP2PEnabled(true); 690 mock_p2p_manager.fake().SetEnsureP2PRunningResult(true); 691 mock_p2p_manager.fake().SetPerformHousekeepingResult(true); 692 EXPECT_CALL(mock_p2p_manager, PerformHousekeeping()); 693 attempter_.Update("", "", "", "", false, false); 694 EXPECT_TRUE(actual_using_p2p_for_downloading()); 695 EXPECT_TRUE(actual_using_p2p_for_sharing()); 696 ScheduleQuitMainLoop(); 697 } 698 699 TEST_F(UpdateAttempterTest, P2PEnabledInteractive) { 700 loop_.PostTask(FROM_HERE, 701 base::Bind(&UpdateAttempterTest::P2PEnabledInteractiveStart, 702 base::Unretained(this))); 703 loop_.Run(); 704 } 705 706 void UpdateAttempterTest::P2PEnabledInteractiveStart() { 707 MockP2PManager mock_p2p_manager; 708 fake_system_state_.set_p2p_manager(&mock_p2p_manager); 709 // For an interactive check, if P2P is enabled and starting it 710 // works, check that we performed housekeeping and that we convey 711 // p2p should be used for sharing but NOT for downloading. 712 mock_p2p_manager.fake().SetP2PEnabled(true); 713 mock_p2p_manager.fake().SetEnsureP2PRunningResult(true); 714 mock_p2p_manager.fake().SetPerformHousekeepingResult(true); 715 EXPECT_CALL(mock_p2p_manager, PerformHousekeeping()); 716 attempter_.Update("", "", "", "", false, true /* interactive */); 717 EXPECT_FALSE(actual_using_p2p_for_downloading()); 718 EXPECT_TRUE(actual_using_p2p_for_sharing()); 719 ScheduleQuitMainLoop(); 720 } 721 722 TEST_F(UpdateAttempterTest, ReadScatterFactorFromPolicy) { 723 loop_.PostTask( 724 FROM_HERE, 725 base::Bind(&UpdateAttempterTest::ReadScatterFactorFromPolicyTestStart, 726 base::Unretained(this))); 727 loop_.Run(); 728 } 729 730 // Tests that the scatter_factor_in_seconds value is properly fetched 731 // from the device policy. 732 void UpdateAttempterTest::ReadScatterFactorFromPolicyTestStart() { 733 int64_t scatter_factor_in_seconds = 36000; 734 735 policy::MockDevicePolicy* device_policy = new policy::MockDevicePolicy(); 736 attempter_.policy_provider_.reset(new policy::PolicyProvider(device_policy)); 737 738 EXPECT_CALL(*device_policy, LoadPolicy()).WillRepeatedly(Return(true)); 739 fake_system_state_.set_device_policy(device_policy); 740 741 EXPECT_CALL(*device_policy, GetScatterFactorInSeconds(_)) 742 .WillRepeatedly(DoAll( 743 SetArgumentPointee<0>(scatter_factor_in_seconds), 744 Return(true))); 745 746 attempter_.Update("", "", "", "", false, false); 747 EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds()); 748 749 ScheduleQuitMainLoop(); 750 } 751 752 TEST_F(UpdateAttempterTest, DecrementUpdateCheckCountTest) { 753 loop_.PostTask( 754 FROM_HERE, 755 base::Bind(&UpdateAttempterTest::DecrementUpdateCheckCountTestStart, 756 base::Unretained(this))); 757 loop_.Run(); 758 } 759 760 void UpdateAttempterTest::DecrementUpdateCheckCountTestStart() { 761 // Tests that the scatter_factor_in_seconds value is properly fetched 762 // from the device policy and is decremented if value > 0. 763 int64_t initial_value = 5; 764 FakePrefs fake_prefs; 765 attempter_.prefs_ = &fake_prefs; 766 767 fake_system_state_.fake_hardware()->SetIsOOBEComplete(Time::UnixEpoch()); 768 769 EXPECT_TRUE(fake_prefs.SetInt64(kPrefsUpdateCheckCount, initial_value)); 770 771 int64_t scatter_factor_in_seconds = 10; 772 773 policy::MockDevicePolicy* device_policy = new policy::MockDevicePolicy(); 774 attempter_.policy_provider_.reset(new policy::PolicyProvider(device_policy)); 775 776 EXPECT_CALL(*device_policy, LoadPolicy()).WillRepeatedly(Return(true)); 777 fake_system_state_.set_device_policy(device_policy); 778 779 EXPECT_CALL(*device_policy, GetScatterFactorInSeconds(_)) 780 .WillRepeatedly(DoAll( 781 SetArgumentPointee<0>(scatter_factor_in_seconds), 782 Return(true))); 783 784 attempter_.Update("", "", "", "", false, false); 785 EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds()); 786 787 // Make sure the file still exists. 788 EXPECT_TRUE(fake_prefs.Exists(kPrefsUpdateCheckCount)); 789 790 int64_t new_value; 791 EXPECT_TRUE(fake_prefs.GetInt64(kPrefsUpdateCheckCount, &new_value)); 792 EXPECT_EQ(initial_value - 1, new_value); 793 794 EXPECT_TRUE( 795 attempter_.omaha_request_params_->update_check_count_wait_enabled()); 796 797 // However, if the count is already 0, it's not decremented. Test that. 798 initial_value = 0; 799 EXPECT_TRUE(fake_prefs.SetInt64(kPrefsUpdateCheckCount, initial_value)); 800 attempter_.Update("", "", "", "", false, false); 801 EXPECT_TRUE(fake_prefs.Exists(kPrefsUpdateCheckCount)); 802 EXPECT_TRUE(fake_prefs.GetInt64(kPrefsUpdateCheckCount, &new_value)); 803 EXPECT_EQ(initial_value, new_value); 804 805 ScheduleQuitMainLoop(); 806 } 807 808 TEST_F(UpdateAttempterTest, NoScatteringDoneDuringManualUpdateTestStart) { 809 loop_.PostTask(FROM_HERE, base::Bind( 810 &UpdateAttempterTest::NoScatteringDoneDuringManualUpdateTestStart, 811 base::Unretained(this))); 812 loop_.Run(); 813 } 814 815 void UpdateAttempterTest::NoScatteringDoneDuringManualUpdateTestStart() { 816 // Tests that no scattering logic is enabled if the update check 817 // is manually done (as opposed to a scheduled update check) 818 int64_t initial_value = 8; 819 FakePrefs fake_prefs; 820 attempter_.prefs_ = &fake_prefs; 821 822 fake_system_state_.fake_hardware()->SetIsOOBEComplete(Time::UnixEpoch()); 823 fake_system_state_.set_prefs(&fake_prefs); 824 825 EXPECT_TRUE(fake_prefs.SetInt64(kPrefsWallClockWaitPeriod, initial_value)); 826 EXPECT_TRUE(fake_prefs.SetInt64(kPrefsUpdateCheckCount, initial_value)); 827 828 // make sure scatter_factor is non-zero as scattering is disabled 829 // otherwise. 830 int64_t scatter_factor_in_seconds = 50; 831 832 policy::MockDevicePolicy* device_policy = new policy::MockDevicePolicy(); 833 attempter_.policy_provider_.reset(new policy::PolicyProvider(device_policy)); 834 835 EXPECT_CALL(*device_policy, LoadPolicy()).WillRepeatedly(Return(true)); 836 fake_system_state_.set_device_policy(device_policy); 837 838 EXPECT_CALL(*device_policy, GetScatterFactorInSeconds(_)) 839 .WillRepeatedly(DoAll( 840 SetArgumentPointee<0>(scatter_factor_in_seconds), 841 Return(true))); 842 843 // Trigger an interactive check so we can test that scattering is disabled. 844 attempter_.Update("", "", "", "", false, true); 845 EXPECT_EQ(scatter_factor_in_seconds, attempter_.scatter_factor_.InSeconds()); 846 847 // Make sure scattering is disabled for manual (i.e. user initiated) update 848 // checks and all artifacts are removed. 849 EXPECT_FALSE( 850 attempter_.omaha_request_params_->wall_clock_based_wait_enabled()); 851 EXPECT_FALSE(fake_prefs.Exists(kPrefsWallClockWaitPeriod)); 852 EXPECT_EQ(0, attempter_.omaha_request_params_->waiting_period().InSeconds()); 853 EXPECT_FALSE( 854 attempter_.omaha_request_params_->update_check_count_wait_enabled()); 855 EXPECT_FALSE(fake_prefs.Exists(kPrefsUpdateCheckCount)); 856 857 ScheduleQuitMainLoop(); 858 } 859 860 // Checks that we only report daily metrics at most every 24 hours. 861 TEST_F(UpdateAttempterTest, ReportDailyMetrics) { 862 FakeClock fake_clock; 863 FakePrefs fake_prefs; 864 865 fake_system_state_.set_clock(&fake_clock); 866 fake_system_state_.set_prefs(&fake_prefs); 867 868 Time epoch = Time::FromInternalValue(0); 869 fake_clock.SetWallclockTime(epoch); 870 871 // If there is no kPrefsDailyMetricsLastReportedAt state variable, 872 // we should report. 873 EXPECT_TRUE(attempter_.CheckAndReportDailyMetrics()); 874 // We should not report again if no time has passed. 875 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 876 877 // We should not report if only 10 hours has passed. 878 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(10)); 879 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 880 881 // We should not report if only 24 hours - 1 sec has passed. 882 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(24) - 883 TimeDelta::FromSeconds(1)); 884 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 885 886 // We should report if 24 hours has passed. 887 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(24)); 888 EXPECT_TRUE(attempter_.CheckAndReportDailyMetrics()); 889 890 // But then we should not report again.. 891 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 892 893 // .. until another 24 hours has passed 894 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(47)); 895 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 896 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(48)); 897 EXPECT_TRUE(attempter_.CheckAndReportDailyMetrics()); 898 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 899 900 // .. and another 24 hours 901 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(71)); 902 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 903 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(72)); 904 EXPECT_TRUE(attempter_.CheckAndReportDailyMetrics()); 905 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 906 907 // If the span between time of reporting and present time is 908 // negative, we report. This is in order to reset the timestamp and 909 // avoid an edge condition whereby a distant point in the future is 910 // in the state variable resulting in us never ever reporting again. 911 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(71)); 912 EXPECT_TRUE(attempter_.CheckAndReportDailyMetrics()); 913 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 914 915 // In this case we should not update until the clock reads 71 + 24 = 95. 916 // Check that. 917 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(94)); 918 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 919 fake_clock.SetWallclockTime(epoch + TimeDelta::FromHours(95)); 920 EXPECT_TRUE(attempter_.CheckAndReportDailyMetrics()); 921 EXPECT_FALSE(attempter_.CheckAndReportDailyMetrics()); 922 } 923 924 TEST_F(UpdateAttempterTest, BootTimeInUpdateMarkerFile) { 925 FakeClock fake_clock; 926 fake_clock.SetBootTime(Time::FromTimeT(42)); 927 fake_system_state_.set_clock(&fake_clock); 928 FakePrefs fake_prefs; 929 fake_system_state_.set_prefs(&fake_prefs); 930 attempter_.Init(); 931 932 Time boot_time; 933 EXPECT_FALSE(attempter_.GetBootTimeAtUpdate(&boot_time)); 934 935 attempter_.WriteUpdateCompletedMarker(); 936 937 EXPECT_TRUE(attempter_.GetBootTimeAtUpdate(&boot_time)); 938 EXPECT_EQ(boot_time.ToTimeT(), 42); 939 } 940 941 TEST_F(UpdateAttempterTest, AnyUpdateSourceAllowedUnofficial) { 942 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false); 943 EXPECT_TRUE(attempter_.IsAnyUpdateSourceAllowed()); 944 } 945 946 TEST_F(UpdateAttempterTest, AnyUpdateSourceAllowedOfficialDevmode) { 947 fake_system_state_.fake_hardware()->SetIsOfficialBuild(true); 948 fake_system_state_.fake_hardware()->SetAreDevFeaturesEnabled(true); 949 EXPECT_TRUE(attempter_.IsAnyUpdateSourceAllowed()); 950 } 951 952 TEST_F(UpdateAttempterTest, AnyUpdateSourceDisallowedOfficialNormal) { 953 fake_system_state_.fake_hardware()->SetIsOfficialBuild(true); 954 fake_system_state_.fake_hardware()->SetAreDevFeaturesEnabled(false); 955 EXPECT_FALSE(attempter_.IsAnyUpdateSourceAllowed()); 956 } 957 958 TEST_F(UpdateAttempterTest, CheckForUpdateAUTest) { 959 fake_system_state_.fake_hardware()->SetIsOfficialBuild(true); 960 fake_system_state_.fake_hardware()->SetAreDevFeaturesEnabled(false); 961 attempter_.CheckForUpdate("", "autest", true); 962 EXPECT_EQ(constants::kOmahaDefaultAUTestURL, attempter_.forced_omaha_url()); 963 } 964 965 TEST_F(UpdateAttempterTest, CheckForUpdateScheduledAUTest) { 966 fake_system_state_.fake_hardware()->SetIsOfficialBuild(true); 967 fake_system_state_.fake_hardware()->SetAreDevFeaturesEnabled(false); 968 attempter_.CheckForUpdate("", "autest-scheduled", true); 969 EXPECT_EQ(constants::kOmahaDefaultAUTestURL, attempter_.forced_omaha_url()); 970 } 971 972 TEST_F(UpdateAttempterTest, TargetVersionPrefixSetAndReset) { 973 attempter_.CalculateUpdateParams("", "", "", "1234", false, false); 974 EXPECT_EQ("1234", 975 fake_system_state_.request_params()->target_version_prefix()); 976 977 attempter_.CalculateUpdateParams("", "", "", "", false, false); 978 EXPECT_TRUE( 979 fake_system_state_.request_params()->target_version_prefix().empty()); 980 } 981 982 } // namespace chromeos_update_engine 983