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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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(&params);
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