update_engine: Move test-only utils to test_utils.{h,cc}.

utils.{h,cc} contains a collections of basic or small functions used
in different parts of the codebase. The test_utils.{h,cc} instead
contains functions only required during testing split out to a
separated file to be reused in different tests.

This CL moves without changes some functions defined in utils.h that
were only used during unittests. Two other basic functions were replaced
by the same function already present in base/ (StringHasSuffix and
StringHasPrefix). The functions in test_utils.h now have their own
namespace chromeos_update_engine::test_utils so is clear they come
from the test_utils file, in the same way the ones from utils are
in their own namespace.

Some othe minor linter fixes included here.

BUG=chromium:351429
TEST=Unittest still pass.

Change-Id: I73ab72a14158cb21c8e1f404cbc728423bc8f34f
Reviewed-on: https://chromium-review.googlesource.com/229021
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/bzip_extent_writer_unittest.cc b/bzip_extent_writer_unittest.cc
index fb4d90b..96121d4 100644
--- a/bzip_extent_writer_unittest.cc
+++ b/bzip_extent_writer_unittest.cc
@@ -90,12 +90,13 @@
   extents.push_back(extent);
 
   vector<char> decompressed_data(kDecompressedLength);
-  FillWithData(&decompressed_data);
+  test_utils::FillWithData(&decompressed_data);
 
-  EXPECT_TRUE(WriteFileVector(decompressed_path, decompressed_data));
+  EXPECT_TRUE(test_utils::WriteFileVector(
+      decompressed_path, decompressed_data));
 
-  EXPECT_EQ(0, System(string("cat ") + decompressed_path + "|bzip2>" +
-                      compressed_path));
+  EXPECT_EQ(0, test_utils::System(
+      string("cat ") + decompressed_path + "|bzip2>" + compressed_path));
 
   vector<char> compressed_data;
   EXPECT_TRUE(utils::ReadFile(compressed_path, &compressed_data));
@@ -113,13 +114,13 @@
   EXPECT_TRUE(bzip_writer.End());
 
   // Check that the const input has not been clobbered.
-  ExpectVectorsEq(original_compressed_data, compressed_data);
+  test_utils::ExpectVectorsEq(original_compressed_data, compressed_data);
 
   vector<char> output(kDecompressedLength + 1);
   ssize_t bytes_read = pread(fd(), &output[0], output.size(), 0);
   EXPECT_EQ(kDecompressedLength, bytes_read);
   output.resize(kDecompressedLength);
-  ExpectVectorsEq(decompressed_data, output);
+  test_utils::ExpectVectorsEq(decompressed_data, output);
 
   unlink(decompressed_path.c_str());
   unlink(compressed_path.c_str());
diff --git a/connection_manager_unittest.cc b/connection_manager_unittest.cc
index 05c700f..576d24d 100644
--- a/connection_manager_unittest.cc
+++ b/connection_manager_unittest.cc
@@ -104,7 +104,7 @@
   GHashTable* manager_hash_table = g_hash_table_new_full(
       g_str_hash, g_str_equal,
       nullptr,  // no key_destroy_func because keys are static.
-      GValueFree);  // value_destroy_func
+      test_utils::GValueFree);  // value_destroy_func
   g_hash_table_insert(manager_hash_table,
                       const_cast<char*>("Services"),
                       array_as_value);
@@ -135,21 +135,23 @@
   GHashTable* service_hash_table = g_hash_table_new_full(
       g_str_hash, g_str_equal,
       nullptr,  // no key_destroy_func because keys are static.
-      GValueFree);  // value_destroy_func
-  GValue* service_type_value = GValueNewString(service_type);
+      test_utils::GValueFree);  // value_destroy_func
+  GValue* service_type_value = test_utils::GValueNewString(service_type);
   g_hash_table_insert(service_hash_table,
                       const_cast<char*>("Type"),
                       service_type_value);
 
   if (physical_technology) {
-    GValue* physical_technology_value = GValueNewString(physical_technology);
+    GValue* physical_technology_value =
+        test_utils::GValueNewString(physical_technology);
     g_hash_table_insert(service_hash_table,
                         const_cast<char*>("PhysicalTechnology"),
                         physical_technology_value);
   }
 
   if (service_tethering) {
-    GValue* service_tethering_value = GValueNewString(service_tethering);
+    GValue* service_tethering_value =
+        test_utils::GValueNewString(service_tethering);
     g_hash_table_insert(service_hash_table,
                         const_cast<char*>("Tethering"),
                         service_tethering_value);
diff --git a/delta_performer_unittest.cc b/delta_performer_unittest.cc
index 78cf981..aaa2278 100644
--- a/delta_performer_unittest.cc
+++ b/delta_performer_unittest.cc
@@ -36,6 +36,9 @@
 using std::vector;
 using testing::Return;
 using testing::_;
+using test_utils::kRandomString;
+using test_utils::ScopedLoopMounter;
+using test_utils::System;
 
 extern const char* kUnittestPrivateKeyPath;
 extern const char* kUnittestPublicKeyPath;
@@ -223,7 +226,7 @@
   vector<char> hash;
   ASSERT_TRUE(utils::ReadFile(hash_file, &hash));
   ASSERT_TRUE(PayloadVerifier::PadRSA2048SHA256Hash(&hash));
-  ASSERT_TRUE(WriteFileVector(hash_file, hash));
+  ASSERT_TRUE(test_utils::WriteFileVector(hash_file, hash));
 
   string sig_file;
   ASSERT_TRUE(utils::MakeTempFile("signature.XXXXXX", &sig_file, nullptr));
@@ -280,7 +283,7 @@
                               DeltaState *state) {
   EXPECT_TRUE(utils::MakeTempFile("a_img.XXXXXX", &state->a_img, nullptr));
   EXPECT_TRUE(utils::MakeTempFile("b_img.XXXXXX", &state->b_img, nullptr));
-  CreateExtImageAtPath(state->a_img, nullptr);
+  test_utils::CreateExtImageAtPath(state->a_img, nullptr);
 
   state->image_size = static_cast<int>(utils::FileSize(state->a_img));
 
@@ -338,9 +341,9 @@
                                            a_mnt.c_str()), 16 * 1024));
 
     EXPECT_EQ(0,
-              system(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
-                                     " bs=1 seek=4096 count=1",
-                                     a_mnt.c_str()).c_str()));
+              System(base::StringPrintf("dd if=/dev/zero of=%s/move-semi-sparse"
+                                        " bs=1 seek=4096 count=1",
+                                        a_mnt.c_str()).c_str()));
 
     // Write 1 MiB of 0xff to try to catch the case where writing a bsdiff
     // patch fails to zero out the final block.
@@ -356,7 +359,7 @@
                                base::FilePath(state->b_img)));
     old_image_info = new_image_info;
   } else {
-    CreateExtImageAtPath(state->b_img, nullptr);
+    test_utils::CreateExtImageAtPath(state->b_img, nullptr);
     EXPECT_EQ(0, System(base::StringPrintf(
         "dd if=/dev/zero of=%s seek=%d bs=1 count=1",
         state->b_img.c_str(),
@@ -367,17 +370,17 @@
     string b_mnt;
     ScopedLoopMounter b_mounter(state->b_img, &b_mnt, 0);
 
-    EXPECT_EQ(0, system(base::StringPrintf("cp %s/hello %s/hello2",
+    EXPECT_EQ(0, System(base::StringPrintf("cp %s/hello %s/hello2",
                                            b_mnt.c_str(),
                                            b_mnt.c_str()).c_str()));
-    EXPECT_EQ(0, system(base::StringPrintf("rm %s/hello",
+    EXPECT_EQ(0, System(base::StringPrintf("rm %s/hello",
                                            b_mnt.c_str()).c_str()));
-    EXPECT_EQ(0, system(base::StringPrintf("mv %s/hello2 %s/hello",
+    EXPECT_EQ(0, System(base::StringPrintf("mv %s/hello2 %s/hello",
                                            b_mnt.c_str(),
                                            b_mnt.c_str()).c_str()));
-    EXPECT_EQ(0, system(base::StringPrintf("echo foo > %s/foo",
+    EXPECT_EQ(0, System(base::StringPrintf("echo foo > %s/foo",
                                            b_mnt.c_str()).c_str()));
-    EXPECT_EQ(0, system(base::StringPrintf("touch %s/emptyfile",
+    EXPECT_EQ(0, System(base::StringPrintf("touch %s/emptyfile",
                                            b_mnt.c_str()).c_str()));
     EXPECT_TRUE(WriteSparseFile(base::StringPrintf("%s/fullsparse",
                                                    b_mnt.c_str()),
@@ -393,24 +396,24 @@
                                   "%s/move-from-sparse", b_mnt.c_str())),
                               zeros.data(), zeros.size()));
 
-    EXPECT_EQ(0, system(base::StringPrintf("dd if=/dev/zero "
+    EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
                                            "of=%s/move-semi-sparse "
                                            "bs=1 seek=4096 count=1",
                                            b_mnt.c_str()).c_str()));
 
-    EXPECT_EQ(0, system(base::StringPrintf("dd if=/dev/zero "
+    EXPECT_EQ(0, System(base::StringPrintf("dd if=/dev/zero "
                                            "of=%s/partsparse bs=1 "
                                            "seek=4096 count=1",
                                            b_mnt.c_str()).c_str()));
-    EXPECT_EQ(0, system(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
+    EXPECT_EQ(0, System(base::StringPrintf("cp %s/srchardlink0 %s/tmp && "
                                            "mv %s/tmp %s/srchardlink1",
                                            b_mnt.c_str(),
                                            b_mnt.c_str(),
                                            b_mnt.c_str(),
                                            b_mnt.c_str()).c_str()));
-    EXPECT_EQ(0, system(base::StringPrintf("rm %s/boguslink && "
-                                     "echo foobar > %s/boguslink",
-                                     b_mnt.c_str(), b_mnt.c_str()).c_str()));
+    EXPECT_EQ(0, System(
+        base::StringPrintf("rm %s/boguslink && echo foobar > %s/boguslink",
+                           b_mnt.c_str(), b_mnt.c_str()).c_str()));
 
     vector<char> hardtocompress;
     while (hardtocompress.size() < 3 * kBlockSize) {
@@ -436,8 +439,8 @@
 
   state->old_kernel_data.resize(kDefaultKernelSize);
   state->new_kernel_data.resize(state->old_kernel_data.size());
-  FillWithData(&state->old_kernel_data);
-  FillWithData(&state->new_kernel_data);
+  test_utils::FillWithData(&state->old_kernel_data);
+  test_utils::FillWithData(&state->new_kernel_data);
 
   // change the new kernel data
   strcpy(&state->new_kernel_data[0], kNewDataString);  // NOLINT(runtime/printf)
@@ -1329,7 +1332,7 @@
   EXPECT_FALSE(performer->GetPublicKeyFromResponse(&key_path));
 
   delete performer;
-  EXPECT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
+  EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
 }
 
 }  // namespace chromeos_update_engine
diff --git a/download_action_unittest.cc b/download_action_unittest.cc
index d27f963..e7c8f02 100644
--- a/download_action_unittest.cc
+++ b/download_action_unittest.cc
@@ -39,6 +39,7 @@
 using testing::InSequence;
 using testing::Return;
 using testing::_;
+using test_utils::ScopedTempFile;
 
 class DownloadActionTest : public ::testing::Test { };
 
@@ -560,7 +561,7 @@
 };
 
 TEST_F(P2PDownloadActionTest, IsWrittenTo) {
-  if (!utils::IsXAttrSupported(FilePath("/tmp"))) {
+  if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) {
     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
                  << "Please update your system to support this feature.";
     return;
@@ -581,7 +582,7 @@
 }
 
 TEST_F(P2PDownloadActionTest, DeleteIfHoleExists) {
-  if (!utils::IsXAttrSupported(FilePath("/tmp"))) {
+  if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) {
     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
                  << "Please update your system to support this feature.";
     return;
@@ -597,7 +598,7 @@
 }
 
 TEST_F(P2PDownloadActionTest, CanAppend) {
-  if (!utils::IsXAttrSupported(FilePath("/tmp"))) {
+  if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) {
     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
                  << "Please update your system to support this feature.";
     return;
@@ -632,7 +633,7 @@
 }
 
 TEST_F(P2PDownloadActionTest, DeletePartialP2PFileIfResumingWithoutP2P) {
-  if (!utils::IsXAttrSupported(FilePath("/tmp"))) {
+  if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) {
     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
                  << "Please update your system to support this feature.";
     return;
diff --git a/extent_writer_unittest.cc b/extent_writer_unittest.cc
index a1b254d..c3118fd 100644
--- a/extent_writer_unittest.cc
+++ b/extent_writer_unittest.cc
@@ -18,6 +18,7 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
+using chromeos_update_engine::test_utils::ExpectVectorsEq;
 using std::min;
 using std::string;
 using std::vector;
@@ -121,7 +122,7 @@
   extents.push_back(extent);
 
   vector<char> data(kBlockSize * 3);
-  FillWithData(&data);
+  test_utils::FillWithData(&data);
 
   DirectExtentWriter direct_writer;
   EXPECT_TRUE(direct_writer.Init(fd(), extents, kBlockSize));
@@ -172,7 +173,7 @@
   extents.push_back(extent);
 
   vector<char> data(kBlockSize * 2);
-  FillWithData(&data);
+  test_utils::FillWithData(&data);
 
   DirectExtentWriter direct_writer;
   ZeroPadExtentWriter zero_pad_writer(&direct_writer);
@@ -220,7 +221,7 @@
   const int on_disk_count = 2;
 
   vector<char> data(17);
-  FillWithData(&data);
+  test_utils::FillWithData(&data);
 
   DirectExtentWriter direct_writer;
   EXPECT_TRUE(direct_writer.Init(fd(), extents, kBlockSize));
diff --git a/fake_p2p_manager_configuration.h b/fake_p2p_manager_configuration.h
index 0645d7a..206fc57 100644
--- a/fake_p2p_manager_configuration.h
+++ b/fake_p2p_manager_configuration.h
@@ -6,6 +6,7 @@
 #define UPDATE_ENGINE_FAKE_P2P_MANAGER_CONFIGURATION_H_
 
 #include "update_engine/p2p_manager.h"
+#include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
 #include <string>
@@ -32,7 +33,7 @@
   }
 
   ~FakeP2PManagerConfiguration() {
-    if (p2p_dir_.size() > 0 && !utils::RecursiveUnlinkDir(p2p_dir_)) {
+    if (p2p_dir_.size() > 0 && !test_utils::RecursiveUnlinkDir(p2p_dir_)) {
       PLOG(ERROR) << "Unable to unlink files and directory in " << p2p_dir_;
     }
   }
diff --git a/filesystem_copier_action_unittest.cc b/filesystem_copier_action_unittest.cc
index 131feb8..c551adf 100644
--- a/filesystem_copier_action_unittest.cc
+++ b/filesystem_copier_action_unittest.cc
@@ -143,15 +143,15 @@
   // Make random data for a, zero filled data for b.
   const size_t kLoopFileSize = 10 * 1024 * 1024 + 512;
   vector<char> a_loop_data(kLoopFileSize);
-  FillWithData(&a_loop_data);
+  test_utils::FillWithData(&a_loop_data);
   vector<char> b_loop_data(run_out_of_space ?
                            (kLoopFileSize - 1) :
                            kLoopFileSize,
                            '\0');  // Fill with 0s
 
   // Write data to disk
-  if (!(WriteFileVector(a_loop_file, a_loop_data) &&
-        WriteFileVector(b_loop_file, b_loop_data))) {
+  if (!(test_utils::WriteFileVector(a_loop_file, a_loop_data) &&
+        test_utils::WriteFileVector(b_loop_file, b_loop_data))) {
     ADD_FAILURE();
     return false;
   }
@@ -160,8 +160,8 @@
   string a_dev;
   string b_dev;
 
-  ScopedLoopbackDeviceBinder a_dev_releaser(a_loop_file, &a_dev);
-  ScopedLoopbackDeviceBinder b_dev_releaser(b_loop_file, &b_dev);
+  test_utils::ScopedLoopbackDeviceBinder a_dev_releaser(a_loop_file, &a_dev);
+  test_utils::ScopedLoopbackDeviceBinder b_dev_releaser(b_loop_file, &b_dev);
   if (!(a_dev_releaser.is_bound() && b_dev_releaser.is_bound())) {
     ADD_FAILURE();
     return false;
@@ -262,7 +262,8 @@
     ADD_FAILURE();
     return false;
   }
-  const bool is_a_file_reading_eq = ExpectVectorsEq(a_loop_data, a_out);
+  const bool is_a_file_reading_eq =
+      test_utils::ExpectVectorsEq(a_loop_data, a_out);
   EXPECT_TRUE(is_a_file_reading_eq);
   success = success && is_a_file_reading_eq;
   if (!verify_hash) {
@@ -271,7 +272,7 @@
       ADD_FAILURE();
       return false;
     }
-    const bool is_b_file_reading_eq = ExpectVectorsEq(a_out, b_out);
+    const bool is_b_file_reading_eq = test_utils::ExpectVectorsEq(a_out, b_out);
     EXPECT_TRUE(is_b_file_reading_eq);
     success = success && is_b_file_reading_eq;
   }
@@ -408,9 +409,9 @@
   string img;
   EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &img, nullptr));
   ScopedPathUnlinker img_unlinker(img);
-  CreateExtImageAtPath(img, nullptr);
+  test_utils::CreateExtImageAtPath(img, nullptr);
   // Extend the "partition" holding the file system from 10MiB to 20MiB.
-  EXPECT_EQ(0, System(base::StringPrintf(
+  EXPECT_EQ(0, test_utils::System(base::StringPrintf(
       "dd if=/dev/zero of=%s seek=20971519 bs=1 count=1",
       img.c_str())));
   EXPECT_EQ(20 * 1024 * 1024, utils::FileSize(img));
diff --git a/libcurl_http_fetcher.cc b/libcurl_http_fetcher.cc
index 42e9e42..a7f6490 100644
--- a/libcurl_http_fetcher.cc
+++ b/libcurl_http_fetcher.cc
@@ -14,7 +14,6 @@
 
 #include "update_engine/certificate_checker.h"
 #include "update_engine/hardware_interface.h"
-#include "update_engine/utils.h"
 
 using std::make_pair;
 using std::max;
@@ -38,21 +37,21 @@
 
 bool LibcurlHttpFetcher::GetProxyType(const string& proxy,
                                       curl_proxytype* out_type) {
-  if (utils::StringHasPrefix(proxy, "socks5://") ||
-      utils::StringHasPrefix(proxy, "socks://")) {
+  if (StartsWithASCII(proxy, "socks5://", true) ||
+      StartsWithASCII(proxy, "socks://", true)) {
     *out_type = CURLPROXY_SOCKS5_HOSTNAME;
     return true;
   }
-  if (utils::StringHasPrefix(proxy, "socks4://")) {
+  if (StartsWithASCII(proxy, "socks4://", true)) {
     *out_type = CURLPROXY_SOCKS4A;
     return true;
   }
-  if (utils::StringHasPrefix(proxy, "http://") ||
-      utils::StringHasPrefix(proxy, "https://")) {
+  if (StartsWithASCII(proxy, "http://", true) ||
+      StartsWithASCII(proxy, "https://", true)) {
     *out_type = CURLPROXY_HTTP;
     return true;
   }
-  if (utils::StringHasPrefix(proxy, kNoProxy)) {
+  if (StartsWithASCII(proxy, kNoProxy, true)) {
     // known failure case. don't log.
     return false;
   }
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index bcdee84..227dde7 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -30,6 +30,8 @@
 
 using base::Time;
 using base::TimeDelta;
+using chromeos_update_engine::test_utils::System;
+using chromeos_update_engine::test_utils::WriteFileString;
 using std::string;
 using std::vector;
 using testing::AllOf;
@@ -1832,7 +1834,7 @@
       "version=\"0.0.0.0\" from_version=\"1.2.3.4\" "
       "track=\"stable-channel\" from_track=\"canary-channel\" "));
 
-  ASSERT_TRUE(utils::RecursiveUnlinkDir(test_dir));
+  ASSERT_TRUE(test_utils::RecursiveUnlinkDir(test_dir));
 }
 
 TEST_F(OmahaRequestActionTest, TestChangingToLessStableChannel) {
diff --git a/omaha_request_params_unittest.cc b/omaha_request_params_unittest.cc
index c4e84ad..6458d3a 100644
--- a/omaha_request_params_unittest.cc
+++ b/omaha_request_params_unittest.cc
@@ -17,6 +17,8 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
+using chromeos_update_engine::test_utils::System;
+using chromeos_update_engine::test_utils::WriteFileString;
 using std::string;
 
 namespace chromeos_update_engine {
diff --git a/omaha_response_handler_action_unittest.cc b/omaha_response_handler_action_unittest.cc
index 49b5c13..418383a 100644
--- a/omaha_response_handler_action_unittest.cc
+++ b/omaha_response_handler_action_unittest.cc
@@ -13,6 +13,8 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
+using chromeos_update_engine::test_utils::System;
+using chromeos_update_engine::test_utils::WriteFileString;
 using std::string;
 using testing::Return;
 
@@ -286,7 +288,7 @@
                            &install_plan));
   EXPECT_TRUE(install_plan.powerwash_required);
 
-  ASSERT_TRUE(utils::RecursiveUnlinkDir(test_dir));
+  ASSERT_TRUE(test_utils::RecursiveUnlinkDir(test_dir));
 }
 
 TEST_F(OmahaResponseHandlerActionTest, ChangeToLessStableChannelTest) {
@@ -330,7 +332,7 @@
                            &install_plan));
   EXPECT_FALSE(install_plan.powerwash_required);
 
-  ASSERT_TRUE(utils::RecursiveUnlinkDir(test_dir));
+  ASSERT_TRUE(test_utils::RecursiveUnlinkDir(test_dir));
 }
 
 TEST_F(OmahaResponseHandlerActionTest, P2PUrlIsUsedAndHashChecksMandatory) {
diff --git a/p2p_manager_unittest.cc b/p2p_manager_unittest.cc
index a790289..12b6709 100644
--- a/p2p_manager_unittest.cc
+++ b/p2p_manager_unittest.cc
@@ -30,6 +30,7 @@
 #include "update_engine/utils.h"
 
 using base::TimeDelta;
+using chromeos_update_engine::test_utils::System;
 using std::string;
 using std::unique_ptr;
 using testing::DoAll;
@@ -82,7 +83,7 @@
   EXPECT_CALL(*mock_policy_, P2PEnabledChanged(_, _, _, _, false));
 
   EXPECT_FALSE(manager_->IsP2PEnabled());
-  RunGMainLoopMaxIterations(100);
+  test_utils::RunGMainLoopMaxIterations(100);
   EXPECT_FALSE(manager_->IsP2PEnabled());
 }
 
@@ -97,7 +98,7 @@
   EXPECT_CALL(*mock_policy_, P2PEnabledChanged(_, _, _, _, false));
 
   EXPECT_TRUE(manager_->IsP2PEnabled());
-  RunGMainLoopMaxIterations(100);
+  test_utils::RunGMainLoopMaxIterations(100);
   EXPECT_FALSE(manager_->IsP2PEnabled());
 }
 
@@ -180,7 +181,7 @@
   // flakiness) since the epoch and then we put two files before that
   // date and three files after.
   time_t cutoff_time = 1000000000;
-  base::TimeDelta age_limit = base::TimeDelta::FromDays(5);
+  TimeDelta age_limit = TimeDelta::FromDays(5);
 
   // Set the clock just so files with a timestamp before |cutoff_time|
   // will be deleted at housekeeping.
@@ -209,7 +210,7 @@
     //                       cutoff_time
     //
     base::Time file_date = base::Time::FromTimeT(cutoff_time) +
-      (n - 2)*base::TimeDelta::FromDays(1) + base::TimeDelta::FromHours(12);
+      (n - 2)*TimeDelta::FromDays(1) + TimeDelta::FromHours(12);
 
     // The touch(1) command expects input like this
     // --date="2004-02-27 14:19:13.489392193 +0530"
@@ -346,7 +347,7 @@
 
 // Check that sharing a *new* file works.
 TEST_F(P2PManagerTest, ShareFile) {
-  if (!utils::IsXAttrSupported(base::FilePath("/tmp"))) {
+  if (!test_utils::IsXAttrSupported(base::FilePath("/tmp"))) {
     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
                  << "Please update your system to support this feature.";
     return;
@@ -367,7 +368,7 @@
 
 // Check that making a shared file visible, does what is expected.
 TEST_F(P2PManagerTest, MakeFileVisible) {
-  if (!utils::IsXAttrSupported(base::FilePath("/tmp"))) {
+  if (!test_utils::IsXAttrSupported(base::FilePath("/tmp"))) {
     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
                  << "Please update your system to support this feature.";
     return;
@@ -392,7 +393,7 @@
 
 // Check that we return the right values for existing files in P2P_DIR.
 TEST_F(P2PManagerTest, ExistingFiles) {
-  if (!utils::IsXAttrSupported(base::FilePath("/tmp"))) {
+  if (!test_utils::IsXAttrSupported(base::FilePath("/tmp"))) {
     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
                  << "Please update your system to support this feature.";
     return;
diff --git a/payload_generator/delta_diff_generator_unittest.cc b/payload_generator/delta_diff_generator_unittest.cc
index c1bee61..c6cd65d 100644
--- a/payload_generator/delta_diff_generator_unittest.cc
+++ b/payload_generator/delta_diff_generator_unittest.cc
@@ -32,6 +32,9 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
+using chromeos_update_engine::test_utils::FillWithData;
+using chromeos_update_engine::test_utils::kRandomString;
+using chromeos_update_engine::test_utils::WriteFileVector;
 using std::set;
 using std::string;
 using std::stringstream;
diff --git a/payload_generator/filesystem_iterator.cc b/payload_generator/filesystem_iterator.cc
index 9646092..073b7a3 100644
--- a/payload_generator/filesystem_iterator.cc
+++ b/payload_generator/filesystem_iterator.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include <base/logging.h>
+#include <base/strings/string_util.h>
 
 #include "update_engine/utils.h"
 
@@ -107,7 +108,7 @@
   IncrementInternal();
   for (set<string>::const_iterator it = excl_prefixes_.begin();
        it != excl_prefixes_.end(); ++it) {
-    if (utils::StringHasPrefix(GetPartialPath(), *it)) {
+    if (StartsWithASCII(GetPartialPath(), *it, true)) {
       Increment();
       break;
     }
diff --git a/payload_generator/filesystem_iterator_unittest.cc b/payload_generator/filesystem_iterator_unittest.cc
index 047c8a4..16f2c6d 100644
--- a/payload_generator/filesystem_iterator_unittest.cc
+++ b/payload_generator/filesystem_iterator_unittest.cc
@@ -19,6 +19,7 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
+using chromeos_update_engine::test_utils::System;
 using std::set;
 using std::string;
 using std::vector;
@@ -69,8 +70,8 @@
   const string sub_image_mount_point = main_image_mount_point + "/some_dir/mnt";
 
   vector<string> expected_paths_vector;
-  CreateExtImageAtPath(main_image, &expected_paths_vector);
-  CreateExtImageAtPath(sub_image, nullptr);
+  test_utils::CreateExtImageAtPath(main_image, &expected_paths_vector);
+  test_utils::CreateExtImageAtPath(sub_image, nullptr);
   ASSERT_EQ(0, System(string("mount -o loop ") + main_image + " " +
                       main_image_mount_point));
   ASSERT_EQ(0, System(string("mount -o loop ") + sub_image + " " +
@@ -80,7 +81,7 @@
     *it = main_image_mount_point + *it;
   set<string> expected_paths(expected_paths_vector.begin(),
                              expected_paths_vector.end());
-  VerifyAllPaths(main_image_mount_point, expected_paths);
+  test_utils::VerifyAllPaths(main_image_mount_point, expected_paths);
 
   EXPECT_TRUE(utils::UnmountFilesystem(sub_image_mount_point));
   EXPECT_TRUE(utils::UnmountFilesystem(main_image_mount_point));
diff --git a/payload_generator/full_update_generator_unittest.cc b/payload_generator/full_update_generator_unittest.cc
index 7cb2d7a..559a110 100644
--- a/payload_generator/full_update_generator_unittest.cc
+++ b/payload_generator/full_update_generator_unittest.cc
@@ -10,6 +10,7 @@
 #include "update_engine/payload_generator/full_update_generator.h"
 #include "update_engine/test_utils.h"
 
+using chromeos_update_engine::test_utils::FillWithData;
 using std::string;
 using std::vector;
 
@@ -37,14 +38,14 @@
                                   &new_root_path,
                                   nullptr));
   ScopedPathUnlinker new_root_path_unlinker(new_root_path);
-  EXPECT_TRUE(WriteFileVector(new_root_path, new_root));
+  EXPECT_TRUE(test_utils::WriteFileVector(new_root_path, new_root));
 
   string new_kern_path;
   EXPECT_TRUE(utils::MakeTempFile("NewFullUpdateTest_K.XXXXXX",
                                   &new_kern_path,
                                   nullptr));
   ScopedPathUnlinker new_kern_path_unlinker(new_kern_path);
-  EXPECT_TRUE(WriteFileVector(new_kern_path, new_kern));
+  EXPECT_TRUE(test_utils::WriteFileVector(new_kern_path, new_kern));
 
   string out_blobs_path;
   int out_blobs_fd;
diff --git a/payload_generator/metadata_unittest.cc b/payload_generator/metadata_unittest.cc
index 93b0917..2ffb338 100644
--- a/payload_generator/metadata_unittest.cc
+++ b/payload_generator/metadata_unittest.cc
@@ -20,6 +20,7 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
+using chromeos_update_engine::test_utils::CreateEmptyExtImageAtPath;
 using std::string;
 using std::vector;
 
@@ -80,13 +81,15 @@
   // Create a file large enough to create an indirect block
   {
     string a_img_mnt;
-    ScopedLoopMounter a_img_mount(a_img, &a_img_mnt, 0);
-    System(base::StringPrintf("dd if=/dev/zero of=%s/test_file bs=%d count=%d",
-                              a_img_mnt.c_str(), block_size,
-                              EXT2_NDIR_BLOCKS + 1));
+    test_utils::ScopedLoopMounter a_img_mount(a_img, &a_img_mnt, 0);
+    test_utils::System(
+        base::StringPrintf("dd if=/dev/zero of=%s/test_file bs=%d count=%d",
+                           a_img_mnt.c_str(), block_size,
+                           EXT2_NDIR_BLOCKS + 1));
   }
 
-  System(base::StringPrintf("cp %s %s", a_img.c_str(), b_img.c_str()));
+  test_utils::System(
+      base::StringPrintf("cp %s %s", a_img.c_str(), b_img.c_str()));
 
   int fd = open(data_file.c_str(), O_RDWR | O_CREAT, S_IRWXU);
   EXPECT_NE(fd, -1);
diff --git a/postinstall_runner_action_unittest.cc b/postinstall_runner_action_unittest.cc
index 9dd493d..15169e4 100644
--- a/postinstall_runner_action_unittest.cc
+++ b/postinstall_runner_action_unittest.cc
@@ -21,6 +21,8 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
+using chromeos_update_engine::test_utils::System;
+using chromeos_update_engine::test_utils::WriteFileString;
 using std::string;
 using std::unique_ptr;
 using std::vector;
@@ -123,12 +125,12 @@
   ASSERT_TRUE(utils::MakeTempDirectory(
           "postinstall_runner_action_unittest-XXXXXX",
           &cwd));
-  ASSERT_EQ(0, Chdir(cwd));
+  ASSERT_EQ(0, test_utils::Chdir(cwd));
 
   // Create a 10MiB sparse file to be used as image; format it as ext2.
-  ASSERT_EQ(0, system(
+  ASSERT_EQ(0, System(
           "dd if=/dev/zero of=image.dat seek=10485759 bs=1 count=1"));
-  ASSERT_EQ(0, system("mkfs.ext2 -F image.dat"));
+  ASSERT_EQ(0, System("mkfs.ext2 -F image.dat"));
 
   // Create a uniquely named image mount point, mount the image.
   ASSERT_EQ(0, System(string("mkdir -p ") + kStatefulPartition));
@@ -159,10 +161,10 @@
   // get a loop device we can use for the install device
   string dev = "/dev/null";
 
-  unique_ptr<ScopedLoopbackDeviceBinder> loop_releaser;
+  unique_ptr<test_utils::ScopedLoopbackDeviceBinder> loop_releaser;
   if (do_losetup) {
-    loop_releaser.reset(new ScopedLoopbackDeviceBinder(cwd + "/image.dat",
-                                                       &dev));
+    loop_releaser.reset(new test_utils::ScopedLoopbackDeviceBinder(
+            cwd + "/image.dat", &dev));
   }
 
   // We use a test-specific powerwash marker file, to avoid race conditions.
@@ -227,7 +229,7 @@
   ASSERT_EQ(0, System(string("rm -fr ") + mountpoint));
 
   // Remove the temporary work directory.
-  ASSERT_EQ(0, Chdir(orig_cwd));
+  ASSERT_EQ(0, test_utils::Chdir(orig_cwd));
   ASSERT_EQ(0, System(string("rm -fr ") + cwd));
 }
 
diff --git a/subprocess_unittest.cc b/subprocess_unittest.cc
index 9ef3e0b..7fafd9e 100644
--- a/subprocess_unittest.cc
+++ b/subprocess_unittest.cc
@@ -182,7 +182,7 @@
   if (cancel_test_data->spawned && !Subprocess::Get().SubprocessInFlight()) {
     // tear down the sub process
     printf("tear down time\n");
-    int status = System(
+    int status = test_utils::System(
         base::StringPrintf("wget -O /dev/null http://127.0.0.1:%d/quitquitquit",
                            local_server_port));
     EXPECT_NE(-1, status) << "system() failed";
diff --git a/test_utils.cc b/test_utils.cc
index 4a49fb2..bd55ccb 100644
--- a/test_utils.cc
+++ b/test_utils.cc
@@ -4,6 +4,7 @@
 
 #include "update_engine/test_utils.h"
 
+#include <attr/xattr.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,8 +31,81 @@
 
 namespace chromeos_update_engine {
 
+namespace test_utils {
+
 const char* const kMountPathTemplate = "UpdateEngineTests_mnt-XXXXXX";
 
+const unsigned char kRandomString[] = {
+  0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
+  0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
+  0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
+  0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
+  0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
+  0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
+  0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
+  0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
+  0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
+  0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
+  0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
+  0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
+  0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
+  0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
+  0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
+  0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
+  0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
+  0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
+  0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
+  0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
+  0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
+  0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
+  0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
+  0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
+  0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
+  0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
+  0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
+  0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
+  0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
+  0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
+  0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
+  0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
+  0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
+  0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
+  0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
+  0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
+  0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
+  0xbe, 0x9f, 0xa3, 0x5d,
+};
+
+bool IsXAttrSupported(const base::FilePath& dir_path) {
+  char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
+
+  int fd = mkstemp(path);
+  if (fd == -1) {
+    PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
+    free(path);
+    return false;
+  }
+
+  if (unlink(path) != 0) {
+    PLOG(ERROR) << "Error unlinking temporary file " << path;
+    close(fd);
+    free(path);
+    return false;
+  }
+
+  int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
+  if (xattr_res != 0) {
+    if (errno == ENOTSUP) {
+      // Leave it to call-sites to warn about non-support.
+    } else {
+      PLOG(ERROR) << "Error setting xattr on " << path;
+    }
+  }
+  close(fd);
+  free(path);
+  return xattr_res == 0;
+}
+
 bool WriteFileVector(const string& path, const vector<char>& data) {
   return utils::WriteFile(path.c_str(), &data[0], data.size());
 }
@@ -159,26 +233,26 @@
     string path = iter.GetFullPath();
     EXPECT_TRUE(expected_paths.find(path) != expected_paths.end()) << path;
     EXPECT_EQ(1, expected_paths.erase(path));
-    if (utils::StringHasSuffix(path, "/hi") ||
-        utils::StringHasSuffix(path, "/hello") ||
-        utils::StringHasSuffix(path, "/test") ||
-        utils::StringHasSuffix(path, "/testlink")) {
+    if (EndsWith(path, "/hi", true) ||
+        EndsWith(path, "/hello", true) ||
+        EndsWith(path, "/test", true) ||
+        EndsWith(path, "/testlink", true)) {
       EXPECT_TRUE(S_ISREG(iter.GetStat().st_mode));
-      if (utils::StringHasSuffix(path, "/test"))
+      if (EndsWith(path, "/test", true))
         test_ino = iter.GetStat().st_ino;
-      else if (utils::StringHasSuffix(path, "/testlink"))
+      else if (EndsWith(path, "/testlink", true))
         testlink_ino = iter.GetStat().st_ino;
-    } else if (utils::StringHasSuffix(path, "/some_dir") ||
-               utils::StringHasSuffix(path, "/empty_dir") ||
-               utils::StringHasSuffix(path, "/mnt") ||
-               utils::StringHasSuffix(path, "/lost+found") ||
+    } else if (EndsWith(path, "/some_dir", true) ||
+               EndsWith(path, "/empty_dir", true) ||
+               EndsWith(path, "/mnt", true) ||
+               EndsWith(path, "/lost+found", true) ||
                parent == path) {
       EXPECT_TRUE(S_ISDIR(iter.GetStat().st_mode));
-    } else if (utils::StringHasSuffix(path, "/fifo")) {
+    } else if (EndsWith(path, "/fifo", true)) {
       EXPECT_TRUE(S_ISFIFO(iter.GetStat().st_mode));
-    } else if (utils::StringHasSuffix(path, "/cdev")) {
+    } else if (EndsWith(path, "/cdev", true)) {
       EXPECT_TRUE(S_ISCHR(iter.GetStat().st_mode));
-    } else if (utils::StringHasSuffix(path, "/sym")) {
+    } else if (EndsWith(path, "/sym", true)) {
       EXPECT_TRUE(S_ISLNK(iter.GetStat().st_mode));
     } else {
       LOG(INFO) << "got non hardcoded path: " << path;
@@ -209,6 +283,63 @@
   unmounter_.reset(new ScopedFilesystemUnmounter(*mnt_path));
 }
 
+namespace {
+class ScopedDirCloser {
+ public:
+  explicit ScopedDirCloser(DIR** dir) : dir_(dir) {}
+  ~ScopedDirCloser() {
+    if (dir_ && *dir_) {
+      int r = closedir(*dir_);
+      TEST_AND_RETURN_ERRNO(r == 0);
+      *dir_ = nullptr;
+      dir_ = nullptr;
+    }
+  }
+ private:
+  DIR** dir_;
+};
+}  // namespace
+
+bool RecursiveUnlinkDir(const string& path) {
+  struct stat stbuf;
+  int r = lstat(path.c_str(), &stbuf);
+  TEST_AND_RETURN_FALSE_ERRNO((r == 0) || (errno == ENOENT));
+  if ((r < 0) && (errno == ENOENT))
+    // path request is missing. that's fine.
+    return true;
+  if (!S_ISDIR(stbuf.st_mode)) {
+    TEST_AND_RETURN_FALSE_ERRNO((unlink(path.c_str()) == 0) ||
+                                (errno == ENOENT));
+    // success or path disappeared before we could unlink.
+    return true;
+  }
+  {
+    // We have a dir, unlink all children, then delete dir
+    DIR *dir = opendir(path.c_str());
+    TEST_AND_RETURN_FALSE_ERRNO(dir);
+    ScopedDirCloser dir_closer(&dir);
+    struct dirent dir_entry;
+    struct dirent *dir_entry_p;
+    int err = 0;
+    while ((err = readdir_r(dir, &dir_entry, &dir_entry_p)) == 0) {
+      if (dir_entry_p == nullptr) {
+        // end of stream reached
+        break;
+      }
+      // Skip . and ..
+      if (!strcmp(dir_entry_p->d_name, ".") ||
+          !strcmp(dir_entry_p->d_name, ".."))
+        continue;
+      TEST_AND_RETURN_FALSE(RecursiveUnlinkDir(path + "/" +
+                                               dir_entry_p->d_name));
+    }
+    TEST_AND_RETURN_FALSE(err == 0);
+  }
+  // unlink dir
+  TEST_AND_RETURN_FALSE_ERRNO((rmdir(path.c_str()) == 0) || (errno == ENOENT));
+  return true;
+}
+
 static gboolean RunGMainLoopOnTimeout(gpointer user_data) {
   bool* timeout = static_cast<bool*>(user_data);
   *timeout = true;
@@ -252,4 +383,5 @@
   g_free(gval);
 }
 
+}  // namespace test_utils
 }  // namespace chromeos_update_engine
diff --git a/test_utils.h b/test_utils.h
index 73f29c6..379eb5f 100644
--- a/test_utils.h
+++ b/test_utils.h
@@ -25,6 +25,11 @@
 // These are some handy functions for unittests.
 
 namespace chromeos_update_engine {
+namespace test_utils {
+
+// 300 byte pseudo-random string. Not null terminated.
+// This does not gzip compress well.
+extern const unsigned char kRandomString[300];
 
 // Writes the data passed to path. The file at path will be overwritten if it
 // exists. Returns true on success, false otherwise.
@@ -57,54 +62,13 @@
   return chdir(path.c_str());
 }
 
+// Checks if xattr is supported in the directory specified by
+// |dir_path| which must be writable. Returns true if the feature is
+// supported, false if not or if an error occured.
+bool IsXAttrSupported(const base::FilePath& dir_path);
+
 void FillWithData(std::vector<char>* buffer);
 
-namespace {  // NOLINT(build/namespaces) - anon. NS in header file.
-// 300 byte pseudo-random string. Not null terminated.
-// This does not gzip compress well.
-const unsigned char kRandomString[] = {
-  0xf2, 0xb7, 0x55, 0x92, 0xea, 0xa6, 0xc9, 0x57,
-  0xe0, 0xf8, 0xeb, 0x34, 0x93, 0xd9, 0xc4, 0x8f,
-  0xcb, 0x20, 0xfa, 0x37, 0x4b, 0x40, 0xcf, 0xdc,
-  0xa5, 0x08, 0x70, 0x89, 0x79, 0x35, 0xe2, 0x3d,
-  0x56, 0xa4, 0x75, 0x73, 0xa3, 0x6d, 0xd1, 0xd5,
-  0x26, 0xbb, 0x9c, 0x60, 0xbd, 0x2f, 0x5a, 0xfa,
-  0xb7, 0xd4, 0x3a, 0x50, 0xa7, 0x6b, 0x3e, 0xfd,
-  0x61, 0x2b, 0x3a, 0x31, 0x30, 0x13, 0x33, 0x53,
-  0xdb, 0xd0, 0x32, 0x71, 0x5c, 0x39, 0xed, 0xda,
-  0xb4, 0x84, 0xca, 0xbc, 0xbd, 0x78, 0x1c, 0x0c,
-  0xd8, 0x0b, 0x41, 0xe8, 0xe1, 0xe0, 0x41, 0xad,
-  0x03, 0x12, 0xd3, 0x3d, 0xb8, 0x75, 0x9b, 0xe6,
-  0xd9, 0x01, 0xd0, 0x87, 0xf4, 0x36, 0xfa, 0xa7,
-  0x0a, 0xfa, 0xc5, 0x87, 0x65, 0xab, 0x9a, 0x7b,
-  0xeb, 0x58, 0x23, 0xf0, 0xa8, 0x0a, 0xf2, 0x33,
-  0x3a, 0xe2, 0xe3, 0x35, 0x74, 0x95, 0xdd, 0x3c,
-  0x59, 0x5a, 0xd9, 0x52, 0x3a, 0x3c, 0xac, 0xe5,
-  0x15, 0x87, 0x6d, 0x82, 0xbc, 0xf8, 0x7d, 0xbe,
-  0xca, 0xd3, 0x2c, 0xd6, 0xec, 0x38, 0xeb, 0xe4,
-  0x53, 0xb0, 0x4c, 0x3f, 0x39, 0x29, 0xf7, 0xa4,
-  0x73, 0xa8, 0xcb, 0x32, 0x50, 0x05, 0x8c, 0x1c,
-  0x1c, 0xca, 0xc9, 0x76, 0x0b, 0x8f, 0x6b, 0x57,
-  0x1f, 0x24, 0x2b, 0xba, 0x82, 0xba, 0xed, 0x58,
-  0xd8, 0xbf, 0xec, 0x06, 0x64, 0x52, 0x6a, 0x3f,
-  0xe4, 0xad, 0xce, 0x84, 0xb4, 0x27, 0x55, 0x14,
-  0xe3, 0x75, 0x59, 0x73, 0x71, 0x51, 0xea, 0xe8,
-  0xcc, 0xda, 0x4f, 0x09, 0xaf, 0xa4, 0xbc, 0x0e,
-  0xa6, 0x1f, 0xe2, 0x3a, 0xf8, 0x96, 0x7d, 0x30,
-  0x23, 0xc5, 0x12, 0xb5, 0xd8, 0x73, 0x6b, 0x71,
-  0xab, 0xf1, 0xd7, 0x43, 0x58, 0xa7, 0xc9, 0xf0,
-  0xe4, 0x85, 0x1c, 0xd6, 0x92, 0x50, 0x2c, 0x98,
-  0x36, 0xfe, 0x87, 0xaf, 0x43, 0x8f, 0x8f, 0xf5,
-  0x88, 0x48, 0x18, 0x42, 0xcf, 0x42, 0xc1, 0xa8,
-  0xe8, 0x05, 0x08, 0xa1, 0x45, 0x70, 0x5b, 0x8c,
-  0x39, 0x28, 0xab, 0xe9, 0x6b, 0x51, 0xd2, 0xcb,
-  0x30, 0x04, 0xea, 0x7d, 0x2f, 0x6e, 0x6c, 0x3b,
-  0x5f, 0x82, 0xd9, 0x5b, 0x89, 0x37, 0x65, 0x65,
-  0xbe, 0x9f, 0xa3, 0x5d
-};
-
-}  // namespace
-
 // Creates an empty ext image.
 void CreateEmptyExtImageAtPath(const std::string& path,
                                size_t size,
@@ -122,6 +86,24 @@
 void VerifyAllPaths(const std::string& parent,
                     std::set<std::string> expected_paths);
 
+// Class to unmount FS when object goes out of scope
+class ScopedFilesystemUnmounter {
+ public:
+  explicit ScopedFilesystemUnmounter(const std::string& mountpoint)
+      : mountpoint_(mountpoint),
+        should_unmount_(true) {}
+  ~ScopedFilesystemUnmounter() {
+    if (should_unmount_) {
+      utils::UnmountFilesystem(mountpoint_);
+    }
+  }
+  void set_should_unmount(bool unmount) { should_unmount_ = unmount; }
+ private:
+  const std::string mountpoint_;
+  bool should_unmount_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedFilesystemUnmounter);
+};
+
 class ScopedLoopbackDeviceBinder {
  public:
   ScopedLoopbackDeviceBinder(const std::string& file, std::string* dev) {
@@ -178,7 +160,52 @@
   std::unique_ptr<ScopedPathUnlinker> unlinker_;
 };
 
-// Useful actions for test
+class ScopedLoopMounter {
+ public:
+  explicit ScopedLoopMounter(const std::string& file_path,
+                             std::string* mnt_path,
+                             unsigned long flags);  // NOLINT(runtime/int)
+
+ private:
+  // These objects must be destructed in the following order:
+  //   ScopedFilesystemUnmounter (the file system must be unmounted first)
+  //   ScopedLoopbackDeviceBinder (then the loop device can be deleted)
+  //   ScopedDirRemover (then the mount point can be deleted)
+  std::unique_ptr<ScopedDirRemover> dir_remover_;
+  std::unique_ptr<ScopedLoopbackDeviceBinder> loop_binder_;
+  std::unique_ptr<ScopedFilesystemUnmounter> unmounter_;
+};
+
+// Deletes a directory and all its contents synchronously. Returns true
+// on success. This may be called with a regular file--it will just unlink it.
+// This WILL cross filesystem boundaries.
+bool RecursiveUnlinkDir(const std::string& path);
+
+// Runs the default GLib main loop for at most |timeout_msec| or until the
+// function |terminate| returns true, whichever happens first. The function
+// |terminate| is called before every GLib main loop iteration and its value is
+// checked.
+void RunGMainLoopUntil(int timeout_msec, base::Callback<bool()> terminate);
+
+// Runs the default GLib main loop at most |iterations| times. This
+// dispatches all the events that are already waiting in the main loop and
+// those that get scheduled as a result of these events being attended.
+// Returns the number of iterations the main loop was ran. If there are more
+// than |iterations| events to attend, then this function returns |iterations|
+// and the remaining events are not dispatched.
+int RunGMainLoopMaxIterations(int iterations);
+
+// Allocates, initializes and returns a string GValue object.
+GValue* GValueNewString(const char* str);
+
+// Frees a GValue object and its allocated resources.
+void GValueFree(gpointer arg);
+
+}  // namespace test_utils
+
+
+// Useful actions for test. These need to be defined in the
+// chromeos_update_engine namespace.
 
 class NoneType;
 
@@ -248,42 +275,6 @@
   T object_;
 };
 
-class ScopedLoopMounter {
- public:
-  explicit ScopedLoopMounter(const std::string& file_path,
-                             std::string* mnt_path,
-                             unsigned long flags);  // NOLINT(runtime/int)
-
- private:
-  // These objects must be destructed in the following order:
-  //   ScopedFilesystemUnmounter (the file system must be unmounted first)
-  //   ScopedLoopbackDeviceBinder (then the loop device can be deleted)
-  //   ScopedDirRemover (then the mount point can be deleted)
-  std::unique_ptr<ScopedDirRemover> dir_remover_;
-  std::unique_ptr<ScopedLoopbackDeviceBinder> loop_binder_;
-  std::unique_ptr<ScopedFilesystemUnmounter> unmounter_;
-};
-
-// Runs the default GLib main loop for at most |timeout_msec| or until the
-// function |terminate| returns true, whichever happens first. The function
-// |terminate| is called before every GLib main loop iteration and its value is
-// checked.
-void RunGMainLoopUntil(int timeout_msec, base::Callback<bool()> terminate);
-
-// Runs the default GLib main loop at most |iterations| times. This
-// dispatches all the events that are already waiting in the main loop and
-// those that get scheduled as a result of these events being attended.
-// Returns the number of iterations the main loop was ran. If there are more
-// than |iterations| events to attend, then this function returns |iterations|
-// and the remaining events are not dispatched.
-int RunGMainLoopMaxIterations(int iterations);
-
-// Allocates, initializes and returns a string GValue object.
-GValue* GValueNewString(const char* str);
-
-// Frees a GValue object and its allocated resources.
-void GValueFree(gpointer arg);
-
 }  // namespace chromeos_update_engine
 
 #endif  // UPDATE_ENGINE_TEST_UTILS_H_
diff --git a/test_utils_unittest.cc b/test_utils_unittest.cc
new file mode 100644
index 0000000..ad41814
--- /dev/null
+++ b/test_utils_unittest.cc
@@ -0,0 +1,41 @@
+// Copyright 2014 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 <string>
+
+#include <gtest/gtest.h>
+
+using std::string;
+
+namespace chromeos_update_engine {
+namespace test_utils {
+
+class TestUtilsTest : public ::testing::Test { };
+
+TEST(UtilsTest, RecursiveUnlinkDirTest) {
+  string first_dir_name;
+  ASSERT_TRUE(utils::MakeTempDirectory("RecursiveUnlinkDirTest-a-XXXXXX",
+                                       &first_dir_name));
+  ASSERT_EQ(0, Chmod(first_dir_name, 0755));
+  string second_dir_name;
+  ASSERT_TRUE(utils::MakeTempDirectory("RecursiveUnlinkDirTest-b-XXXXXX",
+                                       &second_dir_name));
+  ASSERT_EQ(0, Chmod(second_dir_name, 0755));
+
+  EXPECT_EQ(0, Symlink(string("../") + first_dir_name,
+                       second_dir_name + "/link"));
+  EXPECT_EQ(0, System(string("echo hi > ") + second_dir_name + "/file"));
+  EXPECT_EQ(0, Mkdir(second_dir_name + "/dir", 0755));
+  EXPECT_EQ(0, System(string("echo ok > ") + second_dir_name + "/dir/subfile"));
+  EXPECT_TRUE(test_utils::RecursiveUnlinkDir(second_dir_name));
+  EXPECT_TRUE(utils::FileExists(first_dir_name.c_str()));
+  EXPECT_EQ(0, System(string("rm -rf ") + first_dir_name));
+  EXPECT_FALSE(utils::FileExists(second_dir_name.c_str()));
+  EXPECT_TRUE(test_utils::RecursiveUnlinkDir("/something/that/doesnt/exist"));
+}
+
+}  // namespace test_utils
+}  // namespace chromeos_update_engine
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index d2b1e14..1d1542b 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -141,7 +141,7 @@
   }
 
   virtual void TearDown() {
-    utils::RecursiveUnlinkDir(test_dir_);
+    test_utils::RecursiveUnlinkDir(test_dir_);
   }
 
   void QuitMainLoop();
diff --git a/update_engine.gyp b/update_engine.gyp
index aeb4bad..0e89d55 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -369,6 +369,7 @@
             'subprocess_unittest.cc',
             'terminator_unittest.cc',
             'test_utils.cc',
+            'test_utils_unittest.cc',
             'update_attempter_unittest.cc',
             'update_manager/boxed_value_unittest.cc',
             'update_manager/chromeos_policy_unittest.cc',
diff --git a/update_manager/evaluation_context_unittest.cc b/update_manager/evaluation_context_unittest.cc
index 19e3419..f38b641 100644
--- a/update_manager/evaluation_context_unittest.cc
+++ b/update_manager/evaluation_context_unittest.cc
@@ -21,8 +21,8 @@
 using base::Time;
 using base::TimeDelta;
 using chromeos_update_engine::FakeClock;
-using chromeos_update_engine::RunGMainLoopMaxIterations;
-using chromeos_update_engine::RunGMainLoopUntil;
+using chromeos_update_engine::test_utils::RunGMainLoopMaxIterations;
+using chromeos_update_engine::test_utils::RunGMainLoopUntil;
 using std::string;
 using std::unique_ptr;
 using testing::Return;
diff --git a/update_manager/event_loop_unittest.cc b/update_manager/event_loop_unittest.cc
index 69325fe..4f8f768 100644
--- a/update_manager/event_loop_unittest.cc
+++ b/update_manager/event_loop_unittest.cc
@@ -11,8 +11,8 @@
 
 using base::Bind;
 using base::TimeDelta;
-using chromeos_update_engine::RunGMainLoopMaxIterations;
-using chromeos_update_engine::RunGMainLoopUntil;
+using chromeos_update_engine::test_utils::RunGMainLoopMaxIterations;
+using chromeos_update_engine::test_utils::RunGMainLoopUntil;
 
 namespace {
 
diff --git a/update_manager/generic_variables_unittest.cc b/update_manager/generic_variables_unittest.cc
index 784ac4a..7de6725 100644
--- a/update_manager/generic_variables_unittest.cc
+++ b/update_manager/generic_variables_unittest.cc
@@ -12,7 +12,7 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/update_manager/umtest_utils.h"
 
-using chromeos_update_engine::RunGMainLoopMaxIterations;
+using chromeos_update_engine::test_utils::RunGMainLoopMaxIterations;
 using std::unique_ptr;
 
 namespace chromeos_update_manager {
diff --git a/update_manager/real_config_provider_unittest.cc b/update_manager/real_config_provider_unittest.cc
index 6e8d301..09f9fc0 100644
--- a/update_manager/real_config_provider_unittest.cc
+++ b/update_manager/real_config_provider_unittest.cc
@@ -16,7 +16,7 @@
 #include "update_engine/update_manager/umtest_utils.h"
 
 using base::TimeDelta;
-using chromeos_update_engine::WriteFileString;
+using chromeos_update_engine::test_utils::WriteFileString;
 using std::string;
 using std::unique_ptr;
 
diff --git a/update_manager/real_device_policy_provider_unittest.cc b/update_manager/real_device_policy_provider_unittest.cc
index 627027e..0ed2615 100644
--- a/update_manager/real_device_policy_provider_unittest.cc
+++ b/update_manager/real_device_policy_provider_unittest.cc
@@ -14,7 +14,7 @@
 #include "update_engine/update_manager/umtest_utils.h"
 
 using base::TimeDelta;
-using chromeos_update_engine::RunGMainLoopMaxIterations;
+using chromeos_update_engine::test_utils::RunGMainLoopMaxIterations;
 using std::set;
 using std::string;
 using std::unique_ptr;
diff --git a/update_manager/real_shill_provider_unittest.cc b/update_manager/real_shill_provider_unittest.cc
index 7859501..b384e67 100644
--- a/update_manager/real_shill_provider_unittest.cc
+++ b/update_manager/real_shill_provider_unittest.cc
@@ -19,9 +19,9 @@
 using base::Time;
 using base::TimeDelta;
 using chromeos_update_engine::FakeClock;
-using chromeos_update_engine::GValueFree;
-using chromeos_update_engine::GValueNewString;
 using chromeos_update_engine::MockDBusWrapper;
+using chromeos_update_engine::test_utils::GValueFree;
+using chromeos_update_engine::test_utils::GValueNewString;
 using std::pair;
 using std::unique_ptr;
 using testing::Eq;
diff --git a/update_manager/update_manager_unittest.cc b/update_manager/update_manager_unittest.cc
index 3534cfa..c0ce092 100644
--- a/update_manager/update_manager_unittest.cc
+++ b/update_manager/update_manager_unittest.cc
@@ -30,6 +30,7 @@
 using base::TimeDelta;
 using chromeos_update_engine::ErrorCode;
 using chromeos_update_engine::FakeClock;
+using chromeos_update_engine::test_utils::RunGMainLoopMaxIterations;
 using std::pair;
 using std::string;
 using std::tuple;
@@ -229,7 +230,7 @@
   umut_->AsyncPolicyRequest(callback, &Policy::UpdateCheckAllowed);
   // The callback should wait until we run the main loop for it to be executed.
   EXPECT_EQ(0, calls.size());
-  chromeos_update_engine::RunGMainLoopMaxIterations(100);
+  RunGMainLoopMaxIterations(100);
   EXPECT_EQ(1, calls.size());
 }
 
@@ -246,14 +247,14 @@
   umut_->AsyncPolicyRequest(callback, &Policy::UpdateCheckAllowed);
   // Run the main loop, ensure that policy was attempted once before deferring
   // to the default.
-  chromeos_update_engine::RunGMainLoopMaxIterations(100);
+  RunGMainLoopMaxIterations(100);
   EXPECT_EQ(1, num_called);
   ASSERT_EQ(1, calls.size());
   EXPECT_EQ(EvalStatus::kSucceeded, calls[0].first);
   // Wait for the timeout to expire, run the main loop again, ensure that
   // nothing happened.
   sleep(2);
-  chromeos_update_engine::RunGMainLoopMaxIterations(10);
+  RunGMainLoopMaxIterations(10);
   EXPECT_EQ(1, num_called);
   EXPECT_EQ(1, calls.size());
 }
@@ -274,7 +275,7 @@
   umut_->AsyncPolicyRequest(callback, &Policy::UpdateCheckAllowed);
   // Run the main loop, ensure that policy was attempted once but the callback
   // was not invoked.
-  chromeos_update_engine::RunGMainLoopMaxIterations(100);
+  RunGMainLoopMaxIterations(100);
   EXPECT_EQ(1, num_called);
   EXPECT_EQ(0, calls.size());
   // Wait for the expiration timeout to expire, run the main loop again,
@@ -283,7 +284,7 @@
   sleep(2);
   fake_clock_.SetWallclockTime(fake_clock_.GetWallclockTime() +
                                TimeDelta::FromSeconds(2));
-  chromeos_update_engine::RunGMainLoopMaxIterations(10);
+  RunGMainLoopMaxIterations(10);
   EXPECT_EQ(2, num_called);
   EXPECT_EQ(0, calls.size());
   // Wait for reevaluation due to delay to happen, ensure that it occurs and
@@ -291,7 +292,7 @@
   sleep(2);
   fake_clock_.SetWallclockTime(fake_clock_.GetWallclockTime() +
                                TimeDelta::FromSeconds(2));
-  chromeos_update_engine::RunGMainLoopMaxIterations(10);
+  RunGMainLoopMaxIterations(10);
   EXPECT_EQ(3, num_called);
   ASSERT_EQ(1, calls.size());
   EXPECT_EQ(EvalStatus::kSucceeded, calls[0].first);
diff --git a/update_manager/variable_unittest.cc b/update_manager/variable_unittest.cc
index 09c7649..7944c38 100644
--- a/update_manager/variable_unittest.cc
+++ b/update_manager/variable_unittest.cc
@@ -11,7 +11,7 @@
 #include "update_engine/test_utils.h"
 
 using base::TimeDelta;
-using chromeos_update_engine::RunGMainLoopMaxIterations;
+using chromeos_update_engine::test_utils::RunGMainLoopMaxIterations;
 using std::string;
 using std::vector;
 
diff --git a/utils.cc b/utils.cc
index c6c5226..b84eda0 100644
--- a/utils.cc
+++ b/utils.cc
@@ -6,7 +6,6 @@
 
 #include <stdint.h>
 
-#include <attr/xattr.h>
 #include <dirent.h>
 #include <elf.h>
 #include <errno.h>
@@ -249,10 +248,9 @@
   return Read(fp.get(), size, out_p);
 }
 
-// Invokes a pipe |cmd|, then uses |append_func| to append its stdout to a
-// container |out_p|.
-template <class T>
-static bool ReadPipeAndAppend(const string& cmd, T* out_p) {
+// TODO(deymo): This is only used in unittest, but requires the private
+// Read<string>() defined here. Expose Read<string>() or move to base/ version.
+bool ReadPipe(const string& cmd, string* out_p) {
   FILE* fp = popen(cmd.c_str(), "r");
   if (!fp)
     return false;
@@ -260,7 +258,6 @@
   return (success && pclose(fp) >= 0);
 }
 
-
 bool ReadFile(const string& path, vector<char>* out_p) {
   return ReadFileChunkAndAppend(path, 0, -1, out_p);
 }
@@ -274,14 +271,6 @@
   return ReadFileChunkAndAppend(path, offset, size, out_p);
 }
 
-bool ReadPipe(const string& cmd, vector<char>* out_p) {
-  return ReadPipeAndAppend(cmd, out_p);
-}
-
-bool ReadPipe(const string& cmd, string* out_p) {
-  return ReadPipeAndAppend(cmd, out_p);
-}
-
 off_t BlockDevSize(int fd) {
   uint64_t dev_size;
   int rc = ioctl(fd, BLKGETSIZE64, &dev_size);
@@ -360,63 +349,6 @@
   }
 }
 
-namespace {
-class ScopedDirCloser {
- public:
-  explicit ScopedDirCloser(DIR** dir) : dir_(dir) {}
-  ~ScopedDirCloser() {
-    if (dir_ && *dir_) {
-      int r = closedir(*dir_);
-      TEST_AND_RETURN_ERRNO(r == 0);
-      *dir_ = nullptr;
-      dir_ = nullptr;
-    }
-  }
- private:
-  DIR** dir_;
-};
-}  // namespace
-
-bool RecursiveUnlinkDir(const string& path) {
-  struct stat stbuf;
-  int r = lstat(path.c_str(), &stbuf);
-  TEST_AND_RETURN_FALSE_ERRNO((r == 0) || (errno == ENOENT));
-  if ((r < 0) && (errno == ENOENT))
-    // path request is missing. that's fine.
-    return true;
-  if (!S_ISDIR(stbuf.st_mode)) {
-    TEST_AND_RETURN_FALSE_ERRNO((unlink(path.c_str()) == 0) ||
-                                (errno == ENOENT));
-    // success or path disappeared before we could unlink.
-    return true;
-  }
-  {
-    // We have a dir, unlink all children, then delete dir
-    DIR *dir = opendir(path.c_str());
-    TEST_AND_RETURN_FALSE_ERRNO(dir);
-    ScopedDirCloser dir_closer(&dir);
-    struct dirent dir_entry;
-    struct dirent *dir_entry_p;
-    int err = 0;
-    while ((err = readdir_r(dir, &dir_entry, &dir_entry_p)) == 0) {
-      if (dir_entry_p == nullptr) {
-        // end of stream reached
-        break;
-      }
-      // Skip . and ..
-      if (!strcmp(dir_entry_p->d_name, ".") ||
-          !strcmp(dir_entry_p->d_name, ".."))
-        continue;
-      TEST_AND_RETURN_FALSE(RecursiveUnlinkDir(path + "/" +
-                                               dir_entry_p->d_name));
-    }
-    TEST_AND_RETURN_FALSE(err == 0);
-  }
-  // unlink dir
-  TEST_AND_RETURN_FALSE_ERRNO((rmdir(path.c_str()) == 0) || (errno == ENOENT));
-  return true;
-}
-
 string GetDiskName(const string& partition_name) {
   string disk_name;
   return SplitPartitionName(partition_name, &disk_name, nullptr) ?
@@ -432,7 +364,7 @@
 bool SplitPartitionName(const string& partition_name,
                         string* out_disk_name,
                         int* out_partition_num) {
-  if (!StringHasPrefix(partition_name, "/dev/")) {
+  if (!StartsWithASCII(partition_name, "/dev/", true)) {
     LOG(ERROR) << "Invalid partition device name: " << partition_name;
     return false;
   }
@@ -481,7 +413,7 @@
 }
 
 string MakePartitionName(const string& disk_name, int partition_num) {
-  if (!StringHasPrefix(disk_name, "/dev/")) {
+  if (!StartsWithASCII(disk_name, "/dev/", true)) {
     LOG(ERROR) << "Invalid disk name: " << disk_name;
     return string();
   }
@@ -501,7 +433,7 @@
 
   partition_name += std::to_string(partition_num);
 
-  if (StringHasPrefix(partition_name, "/dev/ubiblock")) {
+  if (StartsWithASCII(partition_name, "/dev/ubiblock", true)) {
     // Special case for UBI block devieces that have "_0" suffix.
     partition_name += "_0";
   }
@@ -611,18 +543,6 @@
   return true;
 }
 
-bool StringHasSuffix(const string& str, const string& suffix) {
-  if (suffix.size() > str.size())
-    return false;
-  return 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix);
-}
-
-bool StringHasPrefix(const string& str, const string& prefix) {
-  if (prefix.size() > str.size())
-    return false;
-  return 0 == str.compare(0, prefix.size(), prefix);
-}
-
 bool MountFilesystem(const string& device,
                      const string& mountpoint,
                      unsigned long mountflags) {  // NOLINT(runtime/int)
@@ -908,11 +828,6 @@
   }
 }
 
-int CompareCpuShares(CpuShares shares_lhs,
-                     CpuShares shares_rhs) {
-  return static_cast<int>(shares_lhs) - static_cast<int>(shares_rhs);
-}
-
 int FuzzInt(int value, unsigned int range) {
   int min = value - range / 2;
   int max = value + range - range / 2;
@@ -1520,36 +1435,6 @@
                       encoded_hash.c_str());
 }
 
-bool IsXAttrSupported(const base::FilePath& dir_path) {
-  char *path = strdup(dir_path.Append("xattr_test_XXXXXX").value().c_str());
-
-  int fd = mkstemp(path);
-  if (fd == -1) {
-    PLOG(ERROR) << "Error creating temporary file in " << dir_path.value();
-    free(path);
-    return false;
-  }
-
-  if (unlink(path) != 0) {
-    PLOG(ERROR) << "Error unlinking temporary file " << path;
-    close(fd);
-    free(path);
-    return false;
-  }
-
-  int xattr_res = fsetxattr(fd, "user.xattr-test", "value", strlen("value"), 0);
-  if (xattr_res != 0) {
-    if (errno == ENOTSUP) {
-      // Leave it to call-sites to warn about non-support.
-    } else {
-      PLOG(ERROR) << "Error setting xattr on " << path;
-    }
-  }
-  close(fd);
-  free(path);
-  return xattr_res == 0;
-}
-
 bool DecodeAndStoreBase64String(const string& base64_encoded,
                                 base::FilePath *out_path) {
   vector<char> contents;
diff --git a/utils.h b/utils.h
index 19bb9d6..9eefbac 100644
--- a/utils.h
+++ b/utils.h
@@ -87,7 +87,6 @@
 // Invokes |cmd| in a pipe and appends its stdout to the container pointed to by
 // |out_p|. Returns true upon successfully reading all of the output, false
 // otherwise, in which case the state of the output container is unknown.
-bool ReadPipe(const std::string& cmd, std::vector<char>* out_p);
 bool ReadPipe(const std::string& cmd, std::string* out_p);
 
 // Returns the size of the block device at path, or the file descriptor fd. If
@@ -139,11 +138,6 @@
 bool MakeTempDirectory(const std::string& base_dirname_template,
                        std::string* dirname);
 
-// Deletes a directory and all its contents synchronously. Returns true
-// on success. This may be called with a regular file--it will just unlink it.
-// This WILL cross filesystem boundaries.
-bool RecursiveUnlinkDir(const std::string& path);
-
 // Returns the disk device name for a partition. For example,
 // GetDiskName("/dev/sda3") returns "/dev/sda". Returns an empty string
 // if the input device is not of the "/dev/xyz#" form.
@@ -258,9 +252,6 @@
   HexDumpArray(reinterpret_cast<const unsigned char*>(&vect[0]), vect.size());
 }
 
-bool StringHasSuffix(const std::string& str, const std::string& suffix);
-bool StringHasPrefix(const std::string& str, const std::string& prefix);
-
 template<typename KeyType, typename ValueType>
 bool MapContainsKey(const std::map<KeyType, ValueType>& m, const KeyType& k) {
   return m.find(k) != m.end();
@@ -318,12 +309,6 @@
   kCpuSharesLow = 2,
 };
 
-// Compares cpu shares and returns an integer that is less
-// than, equal to or greater than 0 if |shares_lhs| is,
-// respectively, lower than, same as or higher than |shares_rhs|.
-int CompareCpuShares(CpuShares shares_lhs,
-                     CpuShares shares_rhs);
-
 // Sets the current process shares to |shares|. Returns true on
 // success, false otherwise.
 bool SetCpuShares(CpuShares shares);
@@ -398,11 +383,6 @@
 // http://www.chromium.org/chromium-os/chromiumos-design-docs/disk-format
 bool GetInstallDev(const std::string& boot_dev, std::string* install_dev);
 
-// Checks if xattr is supported in the directory specified by
-// |dir_path| which must be writable. Returns true if the feature is
-// supported, false if not or if an error occured.
-bool IsXAttrSupported(const base::FilePath& dir_path);
-
 // Decodes the data in |base64_encoded| and stores it in a temporary
 // file. Returns false if the given data is empty, not well-formed
 // base64 or if an error occurred. If true is returned, the decoded
@@ -456,24 +436,6 @@
 }  // namespace utils
 
 
-// Class to unmount FS when object goes out of scope
-class ScopedFilesystemUnmounter {
- public:
-  explicit ScopedFilesystemUnmounter(const std::string& mountpoint)
-      : mountpoint_(mountpoint),
-        should_unmount_(true) {}
-  ~ScopedFilesystemUnmounter() {
-    if (should_unmount_) {
-      utils::UnmountFilesystem(mountpoint_);
-    }
-  }
-  void set_should_unmount(bool unmount) { should_unmount_ = unmount; }
- private:
-  const std::string mountpoint_;
-  bool should_unmount_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedFilesystemUnmounter);
-};
-
 // Utility class to close a file descriptor
 class ScopedFdCloser {
  public:
diff --git a/utils_unittest.cc b/utils_unittest.cc
index e3133f9..d5dd6a9 100644
--- a/utils_unittest.cc
+++ b/utils_unittest.cc
@@ -139,56 +139,6 @@
   EXPECT_EQ("No such file or directory", utils::ErrnoNumberAsString(ENOENT));
 }
 
-TEST(UtilsTest, StringHasSuffixTest) {
-  EXPECT_TRUE(utils::StringHasSuffix("foo", "foo"));
-  EXPECT_TRUE(utils::StringHasSuffix("foo", "o"));
-  EXPECT_TRUE(utils::StringHasSuffix("", ""));
-  EXPECT_TRUE(utils::StringHasSuffix("abcabc", "abc"));
-  EXPECT_TRUE(utils::StringHasSuffix("adlrwashere", "ere"));
-  EXPECT_TRUE(utils::StringHasSuffix("abcdefgh", "gh"));
-  EXPECT_TRUE(utils::StringHasSuffix("abcdefgh", ""));
-  EXPECT_FALSE(utils::StringHasSuffix("foo", "afoo"));
-  EXPECT_FALSE(utils::StringHasSuffix("", "x"));
-  EXPECT_FALSE(utils::StringHasSuffix("abcdefgh", "fg"));
-  EXPECT_FALSE(utils::StringHasSuffix("abcdefgh", "ab"));
-}
-
-TEST(UtilsTest, StringHasPrefixTest) {
-  EXPECT_TRUE(utils::StringHasPrefix("foo", "foo"));
-  EXPECT_TRUE(utils::StringHasPrefix("foo", "f"));
-  EXPECT_TRUE(utils::StringHasPrefix("", ""));
-  EXPECT_TRUE(utils::StringHasPrefix("abcabc", "abc"));
-  EXPECT_TRUE(utils::StringHasPrefix("adlrwashere", "adl"));
-  EXPECT_TRUE(utils::StringHasPrefix("abcdefgh", "ab"));
-  EXPECT_TRUE(utils::StringHasPrefix("abcdefgh", ""));
-  EXPECT_FALSE(utils::StringHasPrefix("foo", "fooa"));
-  EXPECT_FALSE(utils::StringHasPrefix("", "x"));
-  EXPECT_FALSE(utils::StringHasPrefix("abcdefgh", "bc"));
-  EXPECT_FALSE(utils::StringHasPrefix("abcdefgh", "gh"));
-}
-
-TEST(UtilsTest, RecursiveUnlinkDirTest) {
-  string first_dir_name;
-  ASSERT_TRUE(utils::MakeTempDirectory("RecursiveUnlinkDirTest-a-XXXXXX",
-                                       &first_dir_name));
-  ASSERT_EQ(0, Chmod(first_dir_name, 0755));
-  string second_dir_name;
-  ASSERT_TRUE(utils::MakeTempDirectory("RecursiveUnlinkDirTest-b-XXXXXX",
-                                       &second_dir_name));
-  ASSERT_EQ(0, Chmod(second_dir_name, 0755));
-
-  EXPECT_EQ(0, Symlink(string("../") + first_dir_name,
-                       second_dir_name + "/link"));
-  EXPECT_EQ(0, System(string("echo hi > ") + second_dir_name + "/file"));
-  EXPECT_EQ(0, Mkdir(second_dir_name + "/dir", 0755));
-  EXPECT_EQ(0, System(string("echo ok > ") + second_dir_name + "/dir/subfile"));
-  EXPECT_TRUE(utils::RecursiveUnlinkDir(second_dir_name));
-  EXPECT_TRUE(utils::FileExists(first_dir_name.c_str()));
-  EXPECT_EQ(0, System(string("rm -rf ") + first_dir_name));
-  EXPECT_FALSE(utils::FileExists(second_dir_name.c_str()));
-  EXPECT_TRUE(utils::RecursiveUnlinkDir("/something/that/doesnt/exist"));
-}
-
 TEST(UtilsTest, IsSymlinkTest) {
   string temp_dir;
   EXPECT_TRUE(utils::MakeTempDirectory("symlink-test.XXXXXX", &temp_dir));
@@ -200,7 +150,7 @@
   EXPECT_FALSE(utils::IsSymlink(temp_file.c_str()));
   EXPECT_TRUE(utils::IsSymlink(temp_symlink.c_str()));
   EXPECT_FALSE(utils::IsSymlink("/non/existent/path"));
-  EXPECT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
+  EXPECT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
 }
 
 TEST(UtilsTest, IsDirTest) {
@@ -214,7 +164,7 @@
   EXPECT_FALSE(utils::IsDir(temp_file.c_str()));
   EXPECT_FALSE(utils::IsDir(temp_symlink.c_str()));
   EXPECT_FALSE(utils::IsDir("/non/existent/path"));
-  ASSERT_TRUE(utils::RecursiveUnlinkDir(temp_dir));
+  ASSERT_TRUE(test_utils::RecursiveUnlinkDir(temp_dir));
 }
 
 TEST(UtilsTest, GetDiskNameTest) {
@@ -270,16 +220,26 @@
   EXPECT_EQ("/dev/ubiblock3_0", utils::MakePartitionName("/dev/ubiblock", 3));
 }
 
+namespace {
+// Compares cpu shares and returns an integer that is less
+// than, equal to or greater than 0 if |shares_lhs| is,
+// respectively, lower than, same as or higher than |shares_rhs|.
+int CompareCpuShares(utils::CpuShares shares_lhs,
+                     utils::CpuShares shares_rhs) {
+  return static_cast<int>(shares_lhs) - static_cast<int>(shares_rhs);
+}
+}  // namespace
 
+// Tests the CPU shares enum is in the order we expect it.
 TEST(UtilsTest, CompareCpuSharesTest) {
-  EXPECT_LT(utils::CompareCpuShares(utils::kCpuSharesLow,
-                                    utils::kCpuSharesNormal), 0);
-  EXPECT_GT(utils::CompareCpuShares(utils::kCpuSharesNormal,
-                                    utils::kCpuSharesLow), 0);
-  EXPECT_EQ(utils::CompareCpuShares(utils::kCpuSharesNormal,
-                                    utils::kCpuSharesNormal), 0);
-  EXPECT_GT(utils::CompareCpuShares(utils::kCpuSharesHigh,
-                                    utils::kCpuSharesNormal), 0);
+  EXPECT_LT(CompareCpuShares(utils::kCpuSharesLow,
+                             utils::kCpuSharesNormal), 0);
+  EXPECT_GT(CompareCpuShares(utils::kCpuSharesNormal,
+                             utils::kCpuSharesLow), 0);
+  EXPECT_EQ(CompareCpuShares(utils::kCpuSharesNormal,
+                             utils::kCpuSharesNormal), 0);
+  EXPECT_GT(CompareCpuShares(utils::kCpuSharesHigh,
+                             utils::kCpuSharesNormal), 0);
 }
 
 TEST(UtilsTest, FuzzIntTest) {
@@ -318,9 +278,9 @@
   string img;
   EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &img, nullptr));
   ScopedPathUnlinker img_unlinker(img);
-  CreateExtImageAtPath(img, nullptr);
+  test_utils::CreateExtImageAtPath(img, nullptr);
   // Extend the "partition" holding the file system from 10MiB to 20MiB.
-  EXPECT_EQ(0, System(base::StringPrintf(
+  EXPECT_EQ(0, test_utils::System(base::StringPrintf(
       "dd if=/dev/zero of=%s seek=20971519 bs=1 count=1",
       img.c_str())));
   EXPECT_EQ(20 * 1024 * 1024, utils::FileSize(img));
@@ -426,13 +386,13 @@
 namespace {
 void GetFileFormatTester(const string& expected,
                          const vector<uint8_t>& contents) {
-  ScopedTempFile file;
+  test_utils::ScopedTempFile file;
   ASSERT_TRUE(utils::WriteFile(file.GetPath().c_str(),
                                reinterpret_cast<const char*>(contents.data()),
                                contents.size()));
   EXPECT_EQ(expected, utils::GetFileFormat(file.GetPath()));
 }
-}
+}  // namespace
 
 TEST(UtilsTest, GetFileFormatTest) {
   EXPECT_EQ("File not found.", utils::GetFileFormat("/path/to/nowhere"));
diff --git a/zip_unittest.cc b/zip_unittest.cc
index 72fb9a6..0b6e5b8 100644
--- a/zip_unittest.cc
+++ b/zip_unittest.cc
@@ -14,6 +14,7 @@
 #include "update_engine/test_utils.h"
 #include "update_engine/utils.h"
 
+using chromeos_update_engine::test_utils::kRandomString;
 using std::string;
 using std::vector;