1 // 2 // Copyright (C) 2011 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/omaha_response_handler_action.h" 18 19 #include <memory> 20 #include <string> 21 #include <utility> 22 23 #include <base/files/file_util.h> 24 #include <base/files/scoped_temp_dir.h> 25 #include <brillo/message_loops/fake_message_loop.h> 26 #include <gtest/gtest.h> 27 28 #include "update_engine/common/constants.h" 29 #include "update_engine/common/platform_constants.h" 30 #include "update_engine/common/test_utils.h" 31 #include "update_engine/common/utils.h" 32 #include "update_engine/fake_system_state.h" 33 #include "update_engine/mock_payload_state.h" 34 #include "update_engine/payload_consumer/payload_constants.h" 35 #include "update_engine/update_manager/mock_policy.h" 36 37 using chromeos_update_engine::test_utils::System; 38 using chromeos_update_engine::test_utils::WriteFileString; 39 using chromeos_update_manager::EvalStatus; 40 using chromeos_update_manager::FakeUpdateManager; 41 using chromeos_update_manager::MockPolicy; 42 using std::string; 43 using testing::_; 44 using testing::DoAll; 45 using testing::Return; 46 using testing::SetArgPointee; 47 48 namespace chromeos_update_engine { 49 50 class OmahaResponseHandlerActionProcessorDelegate 51 : public ActionProcessorDelegate { 52 public: 53 OmahaResponseHandlerActionProcessorDelegate() 54 : code_(ErrorCode::kError), code_set_(false) {} 55 void ActionCompleted(ActionProcessor* processor, 56 AbstractAction* action, 57 ErrorCode code) { 58 if (action->Type() == OmahaResponseHandlerAction::StaticType()) { 59 auto response_handler_action = 60 static_cast<OmahaResponseHandlerAction*>(action); 61 code_ = code; 62 code_set_ = true; 63 response_handler_action_install_plan_.reset( 64 new InstallPlan(response_handler_action->install_plan_)); 65 } else if (action->Type() == 66 ObjectCollectorAction<InstallPlan>::StaticType()) { 67 auto collector_action = 68 static_cast<ObjectCollectorAction<InstallPlan>*>(action); 69 collector_action_install_plan_.reset( 70 new InstallPlan(collector_action->object())); 71 } 72 } 73 ErrorCode code_; 74 bool code_set_; 75 std::unique_ptr<InstallPlan> collector_action_install_plan_; 76 std::unique_ptr<InstallPlan> response_handler_action_install_plan_; 77 }; 78 79 class OmahaResponseHandlerActionTest : public ::testing::Test { 80 protected: 81 void SetUp() override { 82 FakeBootControl* fake_boot_control = fake_system_state_.fake_boot_control(); 83 fake_boot_control->SetPartitionDevice(kPartitionNameKernel, 0, "/dev/sdz2"); 84 fake_boot_control->SetPartitionDevice(kPartitionNameRoot, 0, "/dev/sdz3"); 85 fake_boot_control->SetPartitionDevice(kPartitionNameKernel, 1, "/dev/sdz4"); 86 fake_boot_control->SetPartitionDevice(kPartitionNameRoot, 1, "/dev/sdz5"); 87 } 88 89 // Return true iff the OmahaResponseHandlerAction succeeded. 90 // If out is non-null, it's set w/ the response from the action. 91 bool DoTest(const OmahaResponse& in, 92 const string& deadline_file, 93 InstallPlan* out); 94 95 // Delegate passed to the ActionProcessor. 96 OmahaResponseHandlerActionProcessorDelegate delegate_; 97 98 // Captures the action's result code, for tests that need to directly verify 99 // it in non-success cases. 100 ErrorCode action_result_code_; 101 102 FakeSystemState fake_system_state_; 103 // "Hash+" 104 const brillo::Blob expected_hash_ = {0x48, 0x61, 0x73, 0x68, 0x2b}; 105 }; 106 107 namespace { 108 const char* const kLongName = 109 "very_long_name_and_no_slashes-very_long_name_and_no_slashes" 110 "very_long_name_and_no_slashes-very_long_name_and_no_slashes" 111 "very_long_name_and_no_slashes-very_long_name_and_no_slashes" 112 "very_long_name_and_no_slashes-very_long_name_and_no_slashes" 113 "very_long_name_and_no_slashes-very_long_name_and_no_slashes" 114 "very_long_name_and_no_slashes-very_long_name_and_no_slashes" 115 "very_long_name_and_no_slashes-very_long_name_and_no_slashes" 116 "-the_update_a.b.c.d_DELTA_.tgz"; 117 const char* const kBadVersion = "don't update me"; 118 const char* const kPayloadHashHex = "486173682b"; 119 } // namespace 120 121 bool OmahaResponseHandlerActionTest::DoTest(const OmahaResponse& in, 122 const string& test_deadline_file, 123 InstallPlan* out) { 124 brillo::FakeMessageLoop loop(nullptr); 125 loop.SetAsCurrent(); 126 ActionProcessor processor; 127 processor.set_delegate(&delegate_); 128 129 auto feeder_action = std::make_unique<ObjectFeederAction<OmahaResponse>>(); 130 feeder_action->set_obj(in); 131 if (in.update_exists && in.version != kBadVersion) { 132 string expected_hash; 133 for (const auto& package : in.packages) 134 expected_hash += package.hash + ":"; 135 EXPECT_CALL(*(fake_system_state_.mock_prefs()), 136 SetString(kPrefsUpdateCheckResponseHash, expected_hash)) 137 .WillOnce(Return(true)); 138 139 int slot = 140 fake_system_state_.request_params()->is_install() 141 ? fake_system_state_.fake_boot_control()->GetCurrentSlot() 142 : 1 - fake_system_state_.fake_boot_control()->GetCurrentSlot(); 143 string key = kPrefsChannelOnSlotPrefix + std::to_string(slot); 144 EXPECT_CALL(*(fake_system_state_.mock_prefs()), SetString(key, testing::_)) 145 .WillOnce(Return(true)); 146 } 147 148 string current_url = in.packages.size() ? in.packages[0].payload_urls[0] : ""; 149 EXPECT_CALL(*(fake_system_state_.mock_payload_state()), GetCurrentUrl()) 150 .WillRepeatedly(Return(current_url)); 151 152 auto response_handler_action = 153 std::make_unique<OmahaResponseHandlerAction>(&fake_system_state_); 154 if (!test_deadline_file.empty()) 155 response_handler_action->deadline_file_ = test_deadline_file; 156 157 auto collector_action = 158 std::make_unique<ObjectCollectorAction<InstallPlan>>(); 159 160 BondActions(feeder_action.get(), response_handler_action.get()); 161 BondActions(response_handler_action.get(), collector_action.get()); 162 processor.EnqueueAction(std::move(feeder_action)); 163 processor.EnqueueAction(std::move(response_handler_action)); 164 processor.EnqueueAction(std::move(collector_action)); 165 processor.StartProcessing(); 166 EXPECT_TRUE(!processor.IsRunning()) 167 << "Update test to handle non-async actions"; 168 169 if (out && delegate_.collector_action_install_plan_) 170 *out = *delegate_.collector_action_install_plan_; 171 172 EXPECT_TRUE(delegate_.code_set_); 173 action_result_code_ = delegate_.code_; 174 return delegate_.code_ == ErrorCode::kSuccess; 175 } 176 177 TEST_F(OmahaResponseHandlerActionTest, SimpleTest) { 178 test_utils::ScopedTempFile test_deadline_file( 179 "omaha_response_handler_action_unittest-XXXXXX"); 180 { 181 OmahaResponse in; 182 in.update_exists = true; 183 in.version = "a.b.c.d"; 184 in.packages.push_back( 185 {.payload_urls = {"http://foo/the_update_a.b.c.d.tgz"}, 186 .size = 12, 187 .hash = kPayloadHashHex}); 188 in.more_info_url = "http://more/info"; 189 in.prompt = false; 190 in.deadline = "20101020"; 191 InstallPlan install_plan; 192 EXPECT_TRUE(DoTest(in, test_deadline_file.path(), &install_plan)); 193 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 194 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 195 EXPECT_EQ(1U, install_plan.target_slot); 196 string deadline; 197 EXPECT_TRUE(utils::ReadFile(test_deadline_file.path(), &deadline)); 198 EXPECT_EQ("20101020", deadline); 199 struct stat deadline_stat; 200 EXPECT_EQ(0, stat(test_deadline_file.path().c_str(), &deadline_stat)); 201 EXPECT_EQ( 202 static_cast<mode_t>(S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), 203 deadline_stat.st_mode); 204 EXPECT_EQ(in.version, install_plan.version); 205 } 206 { 207 OmahaResponse in; 208 in.update_exists = true; 209 in.version = "a.b.c.d"; 210 in.packages.push_back( 211 {.payload_urls = {"http://foo/the_update_a.b.c.d.tgz"}, 212 .size = 12, 213 .hash = kPayloadHashHex}); 214 in.more_info_url = "http://more/info"; 215 in.prompt = true; 216 InstallPlan install_plan; 217 // Set the other slot as current. 218 fake_system_state_.fake_boot_control()->SetCurrentSlot(1); 219 EXPECT_TRUE(DoTest(in, test_deadline_file.path(), &install_plan)); 220 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 221 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 222 EXPECT_EQ(0U, install_plan.target_slot); 223 string deadline; 224 EXPECT_TRUE(utils::ReadFile(test_deadline_file.path(), &deadline) && 225 deadline.empty()); 226 EXPECT_EQ(in.version, install_plan.version); 227 } 228 { 229 OmahaResponse in; 230 in.update_exists = true; 231 in.version = "a.b.c.d"; 232 in.packages.push_back( 233 {.payload_urls = {kLongName}, .size = 12, .hash = kPayloadHashHex}); 234 in.more_info_url = "http://more/info"; 235 in.prompt = true; 236 in.deadline = "some-deadline"; 237 InstallPlan install_plan; 238 fake_system_state_.fake_boot_control()->SetCurrentSlot(0); 239 // Because rollback happened, the deadline shouldn't be written into the 240 // file. 241 EXPECT_CALL(*(fake_system_state_.mock_payload_state()), 242 GetRollbackHappened()) 243 .WillOnce(Return(true)); 244 EXPECT_TRUE(DoTest(in, test_deadline_file.path(), &install_plan)); 245 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 246 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 247 EXPECT_EQ(1U, install_plan.target_slot); 248 string deadline; 249 EXPECT_TRUE(utils::ReadFile(test_deadline_file.path(), &deadline)); 250 EXPECT_TRUE(deadline.empty()); 251 EXPECT_EQ(in.version, install_plan.version); 252 } 253 { 254 OmahaResponse in; 255 in.update_exists = true; 256 in.version = "a.b.c.d"; 257 in.packages.push_back( 258 {.payload_urls = {kLongName}, .size = 12, .hash = kPayloadHashHex}); 259 in.more_info_url = "http://more/info"; 260 in.prompt = true; 261 in.deadline = "some-deadline"; 262 InstallPlan install_plan; 263 fake_system_state_.fake_boot_control()->SetCurrentSlot(0); 264 EXPECT_CALL(*(fake_system_state_.mock_payload_state()), 265 GetRollbackHappened()) 266 .WillOnce(Return(false)); 267 EXPECT_TRUE(DoTest(in, test_deadline_file.path(), &install_plan)); 268 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 269 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 270 EXPECT_EQ(1U, install_plan.target_slot); 271 string deadline; 272 EXPECT_TRUE(utils::ReadFile(test_deadline_file.path(), &deadline)); 273 EXPECT_EQ("some-deadline", deadline); 274 EXPECT_EQ(in.version, install_plan.version); 275 } 276 } 277 278 TEST_F(OmahaResponseHandlerActionTest, NoUpdatesTest) { 279 OmahaResponse in; 280 in.update_exists = false; 281 InstallPlan install_plan; 282 EXPECT_FALSE(DoTest(in, "", &install_plan)); 283 EXPECT_TRUE(install_plan.partitions.empty()); 284 } 285 286 TEST_F(OmahaResponseHandlerActionTest, InstallTest) { 287 OmahaResponse in; 288 in.update_exists = true; 289 in.version = "a.b.c.d"; 290 in.packages.push_back( 291 {.payload_urls = {kLongName}, .size = 1, .hash = kPayloadHashHex}); 292 in.packages.push_back( 293 {.payload_urls = {kLongName}, .size = 2, .hash = kPayloadHashHex}); 294 in.more_info_url = "http://more/info"; 295 296 OmahaRequestParams params(&fake_system_state_); 297 params.set_is_install(true); 298 299 fake_system_state_.set_request_params(¶ms); 300 InstallPlan install_plan; 301 EXPECT_TRUE(DoTest(in, "", &install_plan)); 302 EXPECT_EQ(install_plan.source_slot, UINT_MAX); 303 } 304 305 TEST_F(OmahaResponseHandlerActionTest, MultiPackageTest) { 306 OmahaResponse in; 307 in.update_exists = true; 308 in.version = "a.b.c.d"; 309 in.packages.push_back({.payload_urls = {"http://package/1"}, 310 .size = 1, 311 .hash = kPayloadHashHex}); 312 in.packages.push_back({.payload_urls = {"http://package/2"}, 313 .size = 2, 314 .hash = kPayloadHashHex}); 315 in.more_info_url = "http://more/info"; 316 InstallPlan install_plan; 317 EXPECT_TRUE(DoTest(in, "", &install_plan)); 318 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 319 EXPECT_EQ(2u, install_plan.payloads.size()); 320 EXPECT_EQ(in.packages[0].size, install_plan.payloads[0].size); 321 EXPECT_EQ(in.packages[1].size, install_plan.payloads[1].size); 322 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 323 EXPECT_EQ(expected_hash_, install_plan.payloads[1].hash); 324 EXPECT_EQ(in.version, install_plan.version); 325 } 326 327 TEST_F(OmahaResponseHandlerActionTest, HashChecksForHttpTest) { 328 OmahaResponse in; 329 in.update_exists = true; 330 in.version = "a.b.c.d"; 331 in.packages.push_back( 332 {.payload_urls = {"http://test.should/need/hash.checks.signed"}, 333 .size = 12, 334 .hash = kPayloadHashHex}); 335 in.more_info_url = "http://more/info"; 336 // Hash checks are always skipped for non-official update URLs. 337 EXPECT_CALL(*(fake_system_state_.mock_request_params()), 338 IsUpdateUrlOfficial()) 339 .WillRepeatedly(Return(true)); 340 InstallPlan install_plan; 341 EXPECT_TRUE(DoTest(in, "", &install_plan)); 342 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 343 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 344 EXPECT_TRUE(install_plan.hash_checks_mandatory); 345 EXPECT_EQ(in.version, install_plan.version); 346 } 347 348 TEST_F(OmahaResponseHandlerActionTest, HashChecksForUnofficialUpdateUrl) { 349 OmahaResponse in; 350 in.update_exists = true; 351 in.version = "a.b.c.d"; 352 in.packages.push_back( 353 {.payload_urls = {"http://url.normally/needs/hash.checks.signed"}, 354 .size = 12, 355 .hash = kPayloadHashHex}); 356 in.more_info_url = "http://more/info"; 357 EXPECT_CALL(*(fake_system_state_.mock_request_params()), 358 IsUpdateUrlOfficial()) 359 .WillRepeatedly(Return(false)); 360 InstallPlan install_plan; 361 EXPECT_TRUE(DoTest(in, "", &install_plan)); 362 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 363 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 364 EXPECT_FALSE(install_plan.hash_checks_mandatory); 365 EXPECT_EQ(in.version, install_plan.version); 366 } 367 368 TEST_F(OmahaResponseHandlerActionTest, 369 HashChecksForOfficialUrlUnofficialBuildTest) { 370 // Official URLs for unofficial builds (dev/test images) don't require hash. 371 OmahaResponse in; 372 in.update_exists = true; 373 in.version = "a.b.c.d"; 374 in.packages.push_back( 375 {.payload_urls = {"http://url.normally/needs/hash.checks.signed"}, 376 .size = 12, 377 .hash = kPayloadHashHex}); 378 in.more_info_url = "http://more/info"; 379 EXPECT_CALL(*(fake_system_state_.mock_request_params()), 380 IsUpdateUrlOfficial()) 381 .WillRepeatedly(Return(true)); 382 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false); 383 InstallPlan install_plan; 384 EXPECT_TRUE(DoTest(in, "", &install_plan)); 385 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 386 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 387 EXPECT_FALSE(install_plan.hash_checks_mandatory); 388 EXPECT_EQ(in.version, install_plan.version); 389 } 390 391 TEST_F(OmahaResponseHandlerActionTest, HashChecksForHttpsTest) { 392 OmahaResponse in; 393 in.update_exists = true; 394 in.version = "a.b.c.d"; 395 in.packages.push_back( 396 {.payload_urls = {"https://test.should/need/hash.checks.signed"}, 397 .size = 12, 398 .hash = kPayloadHashHex}); 399 in.more_info_url = "http://more/info"; 400 EXPECT_CALL(*(fake_system_state_.mock_request_params()), 401 IsUpdateUrlOfficial()) 402 .WillRepeatedly(Return(true)); 403 InstallPlan install_plan; 404 EXPECT_TRUE(DoTest(in, "", &install_plan)); 405 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 406 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 407 EXPECT_TRUE(install_plan.hash_checks_mandatory); 408 EXPECT_EQ(in.version, install_plan.version); 409 } 410 411 TEST_F(OmahaResponseHandlerActionTest, HashChecksForBothHttpAndHttpsTest) { 412 OmahaResponse in; 413 in.update_exists = true; 414 in.version = "a.b.c.d"; 415 in.packages.push_back( 416 {.payload_urls = {"http://test.should.still/need/hash.checks", 417 "https://test.should.still/need/hash.checks"}, 418 .size = 12, 419 .hash = kPayloadHashHex}); 420 in.more_info_url = "http://more/info"; 421 EXPECT_CALL(*(fake_system_state_.mock_request_params()), 422 IsUpdateUrlOfficial()) 423 .WillRepeatedly(Return(true)); 424 InstallPlan install_plan; 425 EXPECT_TRUE(DoTest(in, "", &install_plan)); 426 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 427 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 428 EXPECT_TRUE(install_plan.hash_checks_mandatory); 429 EXPECT_EQ(in.version, install_plan.version); 430 } 431 432 TEST_F(OmahaResponseHandlerActionTest, ChangeToMoreStableChannelTest) { 433 OmahaResponse in; 434 in.update_exists = true; 435 in.version = "a.b.c.d"; 436 in.packages.push_back({.payload_urls = {"https://MoreStableChannelTest"}, 437 .size = 1, 438 .hash = kPayloadHashHex}); 439 in.more_info_url = "http://more/info"; 440 441 // Create a uniquely named test directory. 442 base::ScopedTempDir tempdir; 443 ASSERT_TRUE(tempdir.CreateUniqueTempDir()); 444 445 OmahaRequestParams params(&fake_system_state_); 446 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false); 447 params.set_root(tempdir.GetPath().value()); 448 params.set_current_channel("canary-channel"); 449 // The ImageProperties in Android uses prefs to store MutableImageProperties. 450 #ifdef __ANDROID__ 451 EXPECT_CALL(*fake_system_state_.mock_prefs(), SetBoolean(_, true)) 452 .WillOnce(Return(true)); 453 #endif // __ANDROID__ 454 EXPECT_TRUE(params.SetTargetChannel("stable-channel", true, nullptr)); 455 params.UpdateDownloadChannel(); 456 EXPECT_TRUE(params.ShouldPowerwash()); 457 458 fake_system_state_.set_request_params(¶ms); 459 InstallPlan install_plan; 460 EXPECT_TRUE(DoTest(in, "", &install_plan)); 461 EXPECT_TRUE(install_plan.powerwash_required); 462 } 463 464 TEST_F(OmahaResponseHandlerActionTest, ChangeToLessStableChannelTest) { 465 OmahaResponse in; 466 in.update_exists = true; 467 in.version = "a.b.c.d"; 468 in.packages.push_back({.payload_urls = {"https://LessStableChannelTest"}, 469 .size = 15, 470 .hash = kPayloadHashHex}); 471 in.more_info_url = "http://more/info"; 472 473 // Create a uniquely named test directory. 474 base::ScopedTempDir tempdir; 475 ASSERT_TRUE(tempdir.CreateUniqueTempDir()); 476 477 OmahaRequestParams params(&fake_system_state_); 478 fake_system_state_.fake_hardware()->SetIsOfficialBuild(false); 479 params.set_root(tempdir.GetPath().value()); 480 params.set_current_channel("stable-channel"); 481 // The ImageProperties in Android uses prefs to store MutableImageProperties. 482 #ifdef __ANDROID__ 483 EXPECT_CALL(*fake_system_state_.mock_prefs(), SetBoolean(_, false)) 484 .WillOnce(Return(true)); 485 #endif // __ANDROID__ 486 EXPECT_TRUE(params.SetTargetChannel("canary-channel", false, nullptr)); 487 params.UpdateDownloadChannel(); 488 EXPECT_FALSE(params.ShouldPowerwash()); 489 490 fake_system_state_.set_request_params(¶ms); 491 InstallPlan install_plan; 492 EXPECT_TRUE(DoTest(in, "", &install_plan)); 493 EXPECT_FALSE(install_plan.powerwash_required); 494 } 495 496 TEST_F(OmahaResponseHandlerActionTest, P2PUrlIsUsedAndHashChecksMandatory) { 497 OmahaResponse in; 498 in.update_exists = true; 499 in.version = "a.b.c.d"; 500 in.packages.push_back( 501 {.payload_urls = {"https://would.not/cause/hash/checks"}, 502 .size = 12, 503 .hash = kPayloadHashHex}); 504 in.more_info_url = "http://more/info"; 505 506 OmahaRequestParams params(&fake_system_state_); 507 // We're using a real OmahaRequestParams object here so we can't mock 508 // IsUpdateUrlOfficial(), but setting the update URL to the AutoUpdate test 509 // server will cause IsUpdateUrlOfficial() to return true. 510 params.set_update_url(constants::kOmahaDefaultAUTestURL); 511 fake_system_state_.set_request_params(¶ms); 512 513 EXPECT_CALL(*fake_system_state_.mock_payload_state(), 514 SetUsingP2PForDownloading(true)); 515 516 string p2p_url = "http://9.8.7.6/p2p"; 517 EXPECT_CALL(*fake_system_state_.mock_payload_state(), GetP2PUrl()) 518 .WillRepeatedly(Return(p2p_url)); 519 EXPECT_CALL(*fake_system_state_.mock_payload_state(), 520 GetUsingP2PForDownloading()) 521 .WillRepeatedly(Return(true)); 522 523 InstallPlan install_plan; 524 EXPECT_TRUE(DoTest(in, "", &install_plan)); 525 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 526 EXPECT_EQ(p2p_url, install_plan.download_url); 527 EXPECT_TRUE(install_plan.hash_checks_mandatory); 528 } 529 530 TEST_F(OmahaResponseHandlerActionTest, RollbackTest) { 531 OmahaResponse in; 532 in.update_exists = true; 533 in.packages.push_back({.payload_urls = {"https://RollbackTest"}, 534 .size = 1, 535 .hash = kPayloadHashHex}); 536 in.is_rollback = true; 537 in.rollback_key_version.kernel = 1; 538 in.rollback_key_version.kernel = 2; 539 in.rollback_key_version.firmware_key = 3; 540 in.rollback_key_version.firmware = 4; 541 542 fake_system_state_.fake_hardware()->SetMinKernelKeyVersion(0x00010002); 543 fake_system_state_.fake_hardware()->SetMinFirmwareKeyVersion(0x00030004); 544 545 OmahaRequestParams params(&fake_system_state_); 546 params.set_rollback_allowed(true); 547 548 fake_system_state_.set_request_params(¶ms); 549 InstallPlan install_plan; 550 EXPECT_TRUE(DoTest(in, "", &install_plan)); 551 EXPECT_TRUE(install_plan.is_rollback); 552 } 553 554 TEST_F(OmahaResponseHandlerActionTest, RollbackKernelVersionErrorTest) { 555 OmahaResponse in; 556 in.update_exists = true; 557 in.packages.push_back({.payload_urls = {"https://RollbackTest"}, 558 .size = 1, 559 .hash = kPayloadHashHex}); 560 in.is_rollback = true; 561 in.rollback_key_version.kernel_key = 1; 562 in.rollback_key_version.kernel = 1; // This is lower than the minimum. 563 in.rollback_key_version.firmware_key = 3; 564 in.rollback_key_version.firmware = 4; 565 566 fake_system_state_.fake_hardware()->SetMinKernelKeyVersion(0x00010002); 567 fake_system_state_.fake_hardware()->SetMinFirmwareKeyVersion(0x00030004); 568 569 OmahaRequestParams params(&fake_system_state_); 570 params.set_rollback_allowed(true); 571 572 fake_system_state_.set_request_params(¶ms); 573 InstallPlan install_plan; 574 EXPECT_FALSE(DoTest(in, "", &install_plan)); 575 } 576 577 TEST_F(OmahaResponseHandlerActionTest, RollbackFirmwareVersionErrorTest) { 578 OmahaResponse in; 579 in.update_exists = true; 580 in.packages.push_back({.payload_urls = {"https://RollbackTest"}, 581 .size = 1, 582 .hash = kPayloadHashHex}); 583 in.is_rollback = true; 584 in.rollback_key_version.kernel_key = 1; 585 in.rollback_key_version.kernel = 2; 586 in.rollback_key_version.firmware_key = 3; 587 in.rollback_key_version.firmware = 3; // This is lower than the minimum. 588 589 fake_system_state_.fake_hardware()->SetMinKernelKeyVersion(0x00010002); 590 fake_system_state_.fake_hardware()->SetMinFirmwareKeyVersion(0x00030004); 591 592 OmahaRequestParams params(&fake_system_state_); 593 params.set_rollback_allowed(true); 594 595 fake_system_state_.set_request_params(¶ms); 596 InstallPlan install_plan; 597 EXPECT_FALSE(DoTest(in, "", &install_plan)); 598 } 599 600 TEST_F(OmahaResponseHandlerActionTest, RollbackNotRollbackTest) { 601 OmahaResponse in; 602 in.update_exists = true; 603 in.packages.push_back({.payload_urls = {"https://RollbackTest"}, 604 .size = 1, 605 .hash = kPayloadHashHex}); 606 in.is_rollback = false; 607 608 OmahaRequestParams params(&fake_system_state_); 609 params.set_rollback_allowed(true); 610 611 fake_system_state_.set_request_params(¶ms); 612 InstallPlan install_plan; 613 EXPECT_TRUE(DoTest(in, "", &install_plan)); 614 EXPECT_FALSE(install_plan.is_rollback); 615 } 616 617 TEST_F(OmahaResponseHandlerActionTest, RollbackNotAllowedTest) { 618 OmahaResponse in; 619 in.update_exists = true; 620 in.packages.push_back({.payload_urls = {"https://RollbackTest"}, 621 .size = 1, 622 .hash = kPayloadHashHex}); 623 in.is_rollback = true; 624 625 OmahaRequestParams params(&fake_system_state_); 626 params.set_rollback_allowed(false); 627 628 fake_system_state_.set_request_params(¶ms); 629 InstallPlan install_plan; 630 EXPECT_FALSE(DoTest(in, "", &install_plan)); 631 } 632 633 TEST_F(OmahaResponseHandlerActionTest, SystemVersionTest) { 634 OmahaResponse in; 635 in.update_exists = true; 636 in.version = "a.b.c.d"; 637 in.system_version = "b.c.d.e"; 638 in.packages.push_back({.payload_urls = {"http://package/1"}, 639 .size = 1, 640 .hash = kPayloadHashHex}); 641 in.packages.push_back({.payload_urls = {"http://package/2"}, 642 .size = 2, 643 .hash = kPayloadHashHex}); 644 in.more_info_url = "http://more/info"; 645 InstallPlan install_plan; 646 EXPECT_TRUE(DoTest(in, "", &install_plan)); 647 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 648 EXPECT_EQ(2u, install_plan.payloads.size()); 649 EXPECT_EQ(in.packages[0].size, install_plan.payloads[0].size); 650 EXPECT_EQ(in.packages[1].size, install_plan.payloads[1].size); 651 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 652 EXPECT_EQ(expected_hash_, install_plan.payloads[1].hash); 653 EXPECT_EQ(in.version, install_plan.version); 654 EXPECT_EQ(in.system_version, install_plan.system_version); 655 } 656 657 TEST_F(OmahaResponseHandlerActionTest, TestDeferredByPolicy) { 658 OmahaResponse in; 659 in.update_exists = true; 660 in.version = "a.b.c.d"; 661 in.packages.push_back({.payload_urls = {"http://foo/the_update_a.b.c.d.tgz"}, 662 .size = 12, 663 .hash = kPayloadHashHex}); 664 // Setup the UpdateManager to disallow the update. 665 FakeClock fake_clock; 666 MockPolicy* mock_policy = new MockPolicy(&fake_clock); 667 FakeUpdateManager* fake_update_manager = 668 fake_system_state_.fake_update_manager(); 669 fake_update_manager->set_policy(mock_policy); 670 EXPECT_CALL(*mock_policy, UpdateCanBeApplied(_, _, _, _, _)) 671 .WillOnce( 672 DoAll(SetArgPointee<3>(ErrorCode::kOmahaUpdateDeferredPerPolicy), 673 Return(EvalStatus::kSucceeded))); 674 // Perform the Action. It should "fail" with kOmahaUpdateDeferredPerPolicy. 675 InstallPlan install_plan; 676 EXPECT_FALSE(DoTest(in, "", &install_plan)); 677 EXPECT_EQ(ErrorCode::kOmahaUpdateDeferredPerPolicy, action_result_code_); 678 // Verify that DoTest() didn't set the output install plan. 679 EXPECT_EQ("", install_plan.version); 680 // Now verify the InstallPlan that was generated. 681 install_plan = *delegate_.response_handler_action_install_plan_; 682 EXPECT_EQ(in.packages[0].payload_urls[0], install_plan.download_url); 683 EXPECT_EQ(expected_hash_, install_plan.payloads[0].hash); 684 EXPECT_EQ(1U, install_plan.target_slot); 685 EXPECT_EQ(in.version, install_plan.version); 686 } 687 688 } // namespace chromeos_update_engine 689