update_engine: Store and test kern/fw versions as 4 values

- Refactors the handling of _firmware_version and _kernel_version
  attributes to split as 4x 16 bit values.
- Based on discussion, we are trying to avoid using the client
  specific version format in the network protocol.
- Each of firmware and kernel versions will be stored separately
  as uint16_t rather than combined as a uint32_t.
- In the Omaha response the two fields of each version type will
  be encoded as key_version.version
- Adds tests for the actual parsing of the response.

BUG=chromium:840432
TEST=cros_run_unit_tests --board=samus --packages update_engine

Change-Id: I4da02e3f4715a132db7e96e55c30139fff6fe6ea
Reviewed-on: https://chromium-review.googlesource.com/1123106
Commit-Ready: Marton Hunyady <[email protected]>
Tested-by: Zentaro Kavanagh <[email protected]>
Reviewed-by: Amin Hassani <[email protected]>
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index 7c9fe41..21aecb2 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -84,6 +84,16 @@
 // This is a helper struct to allow unit tests build an update response with the
 // values they care about.
 struct FakeUpdateResponse {
+  string GetRollbackVersionAttributes() const {
+    return (rollback ? " _rollback=\"true\"" : "") +
+           (!rollback_firmware_version.empty()
+                ? " _firmware_version=\"" + rollback_firmware_version + "\""
+                : "") +
+           (!rollback_kernel_version.empty()
+                ? " _kernel_version=\"" + rollback_kernel_version + "\""
+                : "");
+  }
+
   string GetNoUpdateResponse() const {
     string entity_str;
     if (include_entity)
@@ -121,8 +131,8 @@
                       "\" cohortname=\"" + cohortname + "\" "
                 : "") +
            " status=\"ok\">"
-           "<ping status=\"ok\"/><updatecheck status=\"ok\">"
-           "<urls><url codebase=\"" +
+           "<ping status=\"ok\"/><updatecheck status=\"ok\"" +
+           GetRollbackVersionAttributes() + ">" + "<urls><url codebase=\"" +
            codebase +
            "\"/></urls>"
            "<manifest version=\"" +
@@ -220,6 +230,13 @@
   bool multi_app_no_update = false;
   // Whether to include more than one package in an app.
   bool multi_package = false;
+
+  // Whether the payload is a rollback.
+  bool rollback = false;
+  // The verified boot firmware key version for the rollback image.
+  string rollback_firmware_version = "";
+  // The verified boot kernel key version for the rollback image.
+  string rollback_kernel_version = "";
 };
 
 }  // namespace
@@ -292,7 +309,8 @@
 
   void TestRollbackCheck(bool is_consumer_device,
                          int rollback_allowed_milestones,
-                         bool is_policy_loaded);
+                         bool is_policy_loaded,
+                         OmahaResponse* out_response);
 
   // Runs and checks a ping test. |ping_only| indicates whether it should send
   // only a ping or also an updatecheck.
@@ -493,8 +511,8 @@
 
 void OmahaRequestActionTest::TestRollbackCheck(bool is_consumer_device,
                                                int rollback_allowed_milestones,
-                                               bool is_policy_loaded) {
-  OmahaResponse response;
+                                               bool is_policy_loaded,
+                                               OmahaResponse* out_response) {
   fake_update_response_.deadline = "20101020";
   ASSERT_TRUE(TestUpdateCheck(fake_update_response_.GetUpdateResponse(),
                               -1,
@@ -506,9 +524,9 @@
                               metrics::CheckResult::kUpdateAvailable,
                               metrics::CheckReaction::kUpdating,
                               metrics::DownloadErrorCode::kUnset,
-                              &response,
+                              out_response,
                               nullptr));
-  ASSERT_TRUE(response.update_exists);
+  ASSERT_TRUE(out_response->update_exists);
 }
 
 // Tests Event requests -- they should always succeed. |out_post_data|
@@ -2822,9 +2840,11 @@
       ReportKeyVersionMetrics(min_kernel_version, min_kernel_version, true))
       .Times(1);
 
+  OmahaResponse response;
   TestRollbackCheck(false /* is_consumer_device */,
                     3 /* rollback_allowed_milestones */,
-                    false /* is_policy_loaded */);
+                    false /* is_policy_loaded */,
+                    &response);
 
   // Verify kernel_max_rollforward was set to the current minimum
   // kernel key version. This has the effect of freezing roll
@@ -2854,9 +2874,11 @@
       ReportKeyVersionMetrics(min_kernel_version, kRollforwardInfinity, true))
       .Times(1);
 
+  OmahaResponse response;
   TestRollbackCheck(true /* is_consumer_device */,
                     3 /* rollback_allowed_milestones */,
-                    false /* is_policy_loaded */);
+                    false /* is_policy_loaded */,
+                    &response);
 
   // Verify that with rollback disabled that kernel_max_rollforward
   // was set to logical infinity. This is the expected behavior for
@@ -2885,9 +2907,11 @@
       ReportKeyVersionMetrics(min_kernel_version, min_kernel_version, true))
       .Times(1);
 
+  OmahaResponse response;
   TestRollbackCheck(false /* is_consumer_device */,
                     allowed_milestones,
-                    true /* is_policy_loaded */);
+                    true /* is_policy_loaded */,
+                    &response);
 
   // Verify that with rollback enabled that kernel_max_rollforward
   // was set to the current minimum kernel key version. This has
@@ -2917,9 +2941,11 @@
       ReportKeyVersionMetrics(min_kernel_version, kRollforwardInfinity, true))
       .Times(1);
 
+  OmahaResponse response;
   TestRollbackCheck(false /* is_consumer_device */,
                     allowed_milestones,
-                    true /* is_policy_loaded */);
+                    true /* is_policy_loaded */,
+                    &response);
 
   // Verify that with rollback disabled that kernel_max_rollforward
   // was set to logical infinity.
@@ -2927,4 +2953,30 @@
   EXPECT_EQ(kRollforwardInfinity, fake_hw->GetMaxKernelKeyRollforward());
 }
 
+TEST_F(OmahaRequestActionTest, RollbackResponseParsedNoEntries) {
+  OmahaResponse response;
+  fake_update_response_.rollback = true;
+  TestRollbackCheck(false /* is_consumer_device */,
+                    4 /* rollback_allowed_milestones */,
+                    true /* is_policy_loaded */,
+                    &response);
+  EXPECT_TRUE(response.is_rollback);
+}
+
+TEST_F(OmahaRequestActionTest, RollbackResponseValidVersionsParsed) {
+  OmahaResponse response;
+  fake_update_response_.rollback_firmware_version = "1.2";
+  fake_update_response_.rollback_kernel_version = "3.4";
+  fake_update_response_.rollback = true;
+  TestRollbackCheck(false /* is_consumer_device */,
+                    4 /* rollback_allowed_milestones */,
+                    true /* is_policy_loaded */,
+                    &response);
+  EXPECT_TRUE(response.is_rollback);
+  EXPECT_EQ(1, response.rollback_key_version.firmware_key);
+  EXPECT_EQ(2, response.rollback_key_version.firmware);
+  EXPECT_EQ(3, response.rollback_key_version.kernel_key);
+  EXPECT_EQ(4, response.rollback_key_version.kernel);
+}
+
 }  // namespace chromeos_update_engine