Move KernelDeviceOfBootDevice() to utils.

The function to construct the kernel partition block device from
its corresponding boot device uses only string manipulations, and
doesn't operate on the underlying hardware.  This removes the
function from HardwareInterface, in favor of utils.

BUG=None
TEST=unit tests

Change-Id: I94b2c477413c4b484045a696f0ffbc77d9853195
Reviewed-on: https://chromium-review.googlesource.com/174913
Commit-Queue: Richard Barnette <[email protected]>
Tested-by: Richard Barnette <[email protected]>
Reviewed-by: Chris Sosa <[email protected]>
diff --git a/SConstruct b/SConstruct
index 00abca2..485e35e 100644
--- a/SConstruct
+++ b/SConstruct
@@ -317,7 +317,6 @@
                             gpio_mock_file_descriptor.cc
                             gpio_mock_udev_interface.cc
                             graph_utils_unittest.cc
-                            hardware_unittest.cc
                             http_fetcher_unittest.cc
                             metadata_unittest.cc
                             mock_http_fetcher.cc
diff --git a/fake_hardware.cc b/fake_hardware.cc
index 604358d..feb6ec6 100644
--- a/fake_hardware.cc
+++ b/fake_hardware.cc
@@ -8,17 +8,4 @@
 
 namespace chromeos_update_engine {
 
-const string FakeHardware::KernelDeviceOfBootDevice(
-    const string& boot_device) {
-  KernelDevicesMap::iterator it = kernel_devices_.find(boot_device);
-  if (it == kernel_devices_.end())
-    return "";
-  return it->second;
-}
-
-void FakeHardware::SetKernelDeviceOfBootDevice(const string& boot_device,
-                                               const string& kernel_device) {
-  kernel_devices_[boot_device] = kernel_device;
-}
-
 }  // namespace chromeos_update_engine
diff --git a/fake_hardware.h b/fake_hardware.h
index 8b570b2..6394b25 100644
--- a/fake_hardware.h
+++ b/fake_hardware.h
@@ -20,20 +20,14 @@
 
   // HardwareInterface methods.
   virtual const std::string BootDevice() { return boot_device_; }
-  virtual const std::string KernelDeviceOfBootDevice(
-      const std::string& boot_device);
 
   // Setters
   void SetBootDevice(const std::string boot_device) {
     boot_device_ = boot_device;
   }
-  void SetKernelDeviceOfBootDevice(const std::string& boot_device,
-                                   const std::string& kernel_device);
 
  private:
   std::string boot_device_;
-  typedef std::map<std::string, std::string> KernelDevicesMap;
-  KernelDevicesMap kernel_devices_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeHardware);
 };
diff --git a/filesystem_copier_action.cc b/filesystem_copier_action.cc
index 0aeac36..9e43482 100644
--- a/filesystem_copier_action.cc
+++ b/filesystem_copier_action.cc
@@ -90,7 +90,7 @@
   string source = verify_hash_ ? destination : copy_source_;
   if (source.empty()) {
     source = copying_kernel_install_path_ ?
-        system_state_->hardware()->KernelDeviceOfBootDevice(
+        utils::KernelDeviceOfBootDevice(
             system_state_->hardware()->BootDevice()) :
         system_state_->hardware()->BootDevice();
   }
diff --git a/hardware.cc b/hardware.cc
index b330f64..1c0b3a6 100644
--- a/hardware.cc
+++ b/hardware.cc
@@ -29,34 +29,4 @@
   return boot_path;
 }
 
-const string Hardware::KernelDeviceOfBootDevice(
-    const std::string& boot_device) {
-  if (boot_device.empty())
-    return boot_device;
-
-  string ubiblock_prefix("/dev/ubiblock");
-  string ret;
-  char partition_num;
-  if(utils::StringHasPrefix(boot_device, ubiblock_prefix)) {
-    // eg: /dev/ubiblock3_0 becomes /dev/mtdblock2
-    ret = "/dev/mtdblock";
-    partition_num = boot_device[ubiblock_prefix.size()];
-  } else {
-    // eg: /dev/sda3 becomes /dev/sda2
-    // eg: /dev/mmcblk0p3 becomes /dev/mmcblk0p2
-    ret = boot_device.substr(0, boot_device.size() - 1);
-    partition_num = boot_device[boot_device.size() - 1];
-  }
-
-  // Currently this assumes the partition number of the boot device is
-  // 3, 5, or 7, and changes it to 2, 4, or 6, respectively, to
-  // get the kernel device.
-  if (partition_num == '3' || partition_num == '5' || partition_num == '7') {
-    ret.append(1, partition_num - 1);
-    return ret;
-  }
-
-  return "";
-}
-
 }  // namespace chromeos_update_engine
diff --git a/hardware.h b/hardware.h
index 3c42524..cbf8aee 100644
--- a/hardware.h
+++ b/hardware.h
@@ -18,8 +18,6 @@
 
   // HardwareInterface methods.
   virtual const std::string BootDevice();
-  virtual const std::string KernelDeviceOfBootDevice(
-      const std::string& boot_device);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(Hardware);
diff --git a/hardware_interface.h b/hardware_interface.h
index 98773d9..2329f64 100644
--- a/hardware_interface.h
+++ b/hardware_interface.h
@@ -22,16 +22,6 @@
   // or something with equivalent funcionality to interpret those.
   virtual const std::string BootDevice() = 0;
 
-  // Returns the kernel device associated with the given boot device,
-  // for example, this function returns "/dev/sda2" if |boot_device| is
-  // "/dev/sda3".
-  // To obtain the current booted kernel device, the suggested calling
-  // convention is KernelDeviceOfBootDevice(BootDevice()).
-  // This function works by doing string modification on |boot_device|.
-  // Returns empty string on failure.
-  virtual const std::string KernelDeviceOfBootDevice(
-      const std::string& boot_device) = 0;
-
   // TODO(deymo): Move other hardware-dependant functions to this interface:
   // GetECVersion, GetFirmwareVersion, GetHardwareClass, IsNormalBootMode and
   // IsOfficialBuild.
diff --git a/hardware_unittest.cc b/hardware_unittest.cc
deleted file mode 100644
index 2b52b91..0000000
--- a/hardware_unittest.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "update_engine/test_utils.h"
-#include "update_engine/hardware.h"
-
-using std::string;
-using std::vector;
-
-namespace chromeos_update_engine {
-
-class HardwareTest : public ::testing::Test {
- protected:
-  void SetUp() {
-  }
-  void TearDown() {
-  }
-
-  // Hardware object under test.
-  Hardware hwut_;
-};
-
-TEST_F(HardwareTest, BootDeviceTest) {
-  // Pretty lame test...
-  EXPECT_FALSE(hwut_.BootDevice().empty());
-}
-
-TEST_F(HardwareTest, KernelDeviceOfBootDevice) {
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("foo"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/sda0"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/sda1"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/sda2"));
-  EXPECT_EQ("/dev/sda2", hwut_.KernelDeviceOfBootDevice("/dev/sda3"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/sda4"));
-  EXPECT_EQ("/dev/sda4", hwut_.KernelDeviceOfBootDevice("/dev/sda5"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/sda6"));
-  EXPECT_EQ("/dev/sda6", hwut_.KernelDeviceOfBootDevice("/dev/sda7"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/sda8"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/sda9"));
-
-  EXPECT_EQ("/dev/mmcblk0p2", hwut_.KernelDeviceOfBootDevice("/dev/mmcblk0p3"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/mmcblk0p4"));
-
-  EXPECT_EQ("/dev/ubi2", hwut_.KernelDeviceOfBootDevice("/dev/ubi3"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/ubi4"));
-
-  EXPECT_EQ("/dev/mtdblock2",
-            hwut_.KernelDeviceOfBootDevice("/dev/ubiblock3_0"));
-  EXPECT_EQ("/dev/mtdblock4",
-            hwut_.KernelDeviceOfBootDevice("/dev/ubiblock5_0"));
-  EXPECT_EQ("/dev/mtdblock6",
-            hwut_.KernelDeviceOfBootDevice("/dev/ubiblock7_0"));
-  EXPECT_EQ("", hwut_.KernelDeviceOfBootDevice("/dev/ubiblock4_0"));
-}
-
-}  // namespace chromeos_update_engine
diff --git a/omaha_response_handler_action.cc b/omaha_response_handler_action.cc
index 3cf78d3..7921634 100644
--- a/omaha_response_handler_action.cc
+++ b/omaha_response_handler_action.cc
@@ -109,8 +109,7 @@
           system_state_->hardware()->BootDevice()),
       &install_plan_.install_path));
   install_plan_.kernel_install_path =
-      system_state_->hardware()->KernelDeviceOfBootDevice(
-          install_plan_.install_path);
+      utils::KernelDeviceOfBootDevice(install_plan_.install_path);
 
   if (params->to_more_stable_channel() && params->is_powerwash_allowed())
     install_plan_.powerwash_required = true;
diff --git a/payload_state_unittest.cc b/payload_state_unittest.cc
index b4dfc6d..ab59331 100644
--- a/payload_state_unittest.cc
+++ b/payload_state_unittest.cc
@@ -1367,7 +1367,6 @@
   mock_system_state.set_prefs(&prefs);
 
   fake_hardware.SetBootDevice("/dev/sda3");
-  fake_hardware.SetKernelDeviceOfBootDevice("/dev/sda3", "/dev/sda2");
   mock_system_state.set_hardware(&fake_hardware);
 
   EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
@@ -1418,8 +1417,6 @@
   prefs.Init(FilePath(temp_dir));
   mock_system_state.set_prefs(&prefs);
 
-  fake_hardware.SetKernelDeviceOfBootDevice("/dev/sda3", "/dev/sda2");
-  fake_hardware.SetKernelDeviceOfBootDevice("/dev/sda5", "/dev/sda4");
   fake_hardware.SetBootDevice("/dev/sda3");
   mock_system_state.set_hardware(&fake_hardware);
 
diff --git a/update_attempter.cc b/update_attempter.cc
index af76dff..34cd575 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -36,6 +36,7 @@
 #include "update_engine/subprocess.h"
 #include "update_engine/system_state.h"
 #include "update_engine/update_check_scheduler.h"
+#include "update_engine/utils.h"
 
 using base::TimeDelta;
 using base::TimeTicks;
@@ -720,8 +721,7 @@
   }
 
   install_plan.kernel_install_path =
-      system_state_->hardware()->KernelDeviceOfBootDevice(
-          install_plan.install_path);
+      utils::KernelDeviceOfBootDevice(install_plan.install_path);
   install_plan.powerwash_required = powerwash;
   if (powerwash) {
     // Enterprise-enrolled devices have an empty owner in their device policy.
diff --git a/utils.cc b/utils.cc
index 7a304ee..5d32466 100644
--- a/utils.cc
+++ b/utils.cc
@@ -149,6 +149,36 @@
 }
 
 
+const string KernelDeviceOfBootDevice(const std::string& boot_device) {
+  if (boot_device.empty())
+    return boot_device;
+
+  string ubiblock_prefix("/dev/ubiblock");
+  string ret;
+  char partition_num;
+  if (StringHasPrefix(boot_device, ubiblock_prefix)) {
+    // eg: /dev/ubiblock3_0 becomes /dev/mtdblock2
+    ret = "/dev/mtdblock";
+    partition_num = boot_device[ubiblock_prefix.size()];
+  } else {
+    // eg: /dev/sda3 becomes /dev/sda2
+    // eg: /dev/mmcblk0p3 becomes /dev/mmcblk0p2
+    ret = boot_device.substr(0, boot_device.size() - 1);
+    partition_num = boot_device[boot_device.size() - 1];
+  }
+
+  // Currently this assumes the partition number of the boot device is
+  // 3, 5, or 7, and changes it to 2, 4, or 6, respectively, to
+  // get the kernel device.
+  if (partition_num == '3' || partition_num == '5' || partition_num == '7') {
+    ret.append(1, partition_num - 1);
+    return ret;
+  }
+
+  return "";
+}
+
+
 bool WriteFile(const char* path, const char* data, int data_len) {
   DirectFileWriter writer;
   TEST_AND_RETURN_FALSE_ERRNO(0 == writer.Open(path,
diff --git a/utils.h b/utils.h
index 30c2ccd..318333e 100644
--- a/utils.h
+++ b/utils.h
@@ -70,6 +70,11 @@
 // custom chrome os ec.
 std::string GetECVersion();
 
+// Given the name of the block device of a boot partition, return the
+// name of the associated kernel partition (e.g. given "/dev/sda3",
+// return "/dev/sda2").
+const std::string KernelDeviceOfBootDevice(const std::string& boot_device);
+
 // Writes the data passed to path. The file at path will be overwritten if it
 // exists. Returns true on success, false otherwise.
 bool WriteFile(const char* path, const char* data, int data_len);
diff --git a/utils_unittest.cc b/utils_unittest.cc
index c9afbe0..28ce197 100644
--- a/utils_unittest.cc
+++ b/utils_unittest.cc
@@ -50,6 +50,37 @@
   EXPECT_EQ("", utils::ParseECVersion("b=1231a fw_version a=fasd2"));
 }
 
+
+TEST(UtilsTest, KernelDeviceOfBootDevice) {
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("foo"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/sda0"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/sda1"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/sda2"));
+  EXPECT_EQ("/dev/sda2", utils::KernelDeviceOfBootDevice("/dev/sda3"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/sda4"));
+  EXPECT_EQ("/dev/sda4", utils::KernelDeviceOfBootDevice("/dev/sda5"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/sda6"));
+  EXPECT_EQ("/dev/sda6", utils::KernelDeviceOfBootDevice("/dev/sda7"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/sda8"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/sda9"));
+
+  EXPECT_EQ("/dev/mmcblk0p2",
+            utils::KernelDeviceOfBootDevice("/dev/mmcblk0p3"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/mmcblk0p4"));
+
+  EXPECT_EQ("/dev/ubi2", utils::KernelDeviceOfBootDevice("/dev/ubi3"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/ubi4"));
+
+  EXPECT_EQ("/dev/mtdblock2",
+            utils::KernelDeviceOfBootDevice("/dev/ubiblock3_0"));
+  EXPECT_EQ("/dev/mtdblock4",
+            utils::KernelDeviceOfBootDevice("/dev/ubiblock5_0"));
+  EXPECT_EQ("/dev/mtdblock6",
+            utils::KernelDeviceOfBootDevice("/dev/ubiblock7_0"));
+  EXPECT_EQ("", utils::KernelDeviceOfBootDevice("/dev/ubiblock4_0"));
+}
+
+
 TEST(UtilsTest, NormalizePathTest) {
   EXPECT_EQ("", utils::NormalizePath("", false));
   EXPECT_EQ("", utils::NormalizePath("", true));