Fixes to utility / unit test related code.

* Eliminated bugs related to reading content from pipes/files, including
  general cleanup/refactoring of these code pieces and API.

* Eliminated bugs related binding/unbinding of loopback devices, which
  are used in unit testing.

BUG=chromium-os:31082
TEST=Builds and runs unit tests

CQ-DEPEND=Ib7b3552e98ca40b6141688e2dea5a1407db12b2a

Change-Id: Ifaab8697602a35ce7d7fb9384fdcb1ca64b72515
Reviewed-on: https://gerrit.chromium.org/gerrit/27911
Reviewed-by: Don Garrett <[email protected]>
Tested-by: Gilad Arnold <[email protected]>
Commit-Ready: Gilad Arnold <[email protected]>
diff --git a/test_utils.h b/test_utils.h
index 86ee030..6d85157 100644
--- a/test_utils.h
+++ b/test_utils.h
@@ -36,7 +36,8 @@
 // the first partition is marked bootable.
 std::vector<char> GenerateSampleMbr();
 
-std::string BindToUnusedLoopDevice(const std::string &filename);
+bool BindToUnusedLoopDevice(const std::string &filename,
+                            std::string* lo_dev_name_ptr);
 
 // Returns true iff a == b
 bool ExpectVectorsEq(const std::vector<char>& a, const std::vector<char>& b);
@@ -114,13 +115,17 @@
 class ScopedLoopbackDeviceBinder {
  public:
   ScopedLoopbackDeviceBinder(const std::string& file, std::string* dev) {
-    dev_ = BindToUnusedLoopDevice(file);
+    is_bound_ = BindToUnusedLoopDevice(file, &dev_);
+    EXPECT_TRUE(is_bound_);
 
-    if (dev)
+    if (is_bound_ && dev)
       *dev = dev_;
   }
 
   ~ScopedLoopbackDeviceBinder() {
+    if (!is_bound_)
+      return;
+
     for (int retry = 0; retry < 5; retry++) {
       std::vector<std::string> args;
       args.push_back("/sbin/losetup");
@@ -136,10 +141,14 @@
     ADD_FAILURE();
   }
 
-  const std::string &dev() { return dev_; }
+  const std::string &dev() {
+    EXPECT_TRUE(is_bound_);
+    return dev_;
+  }
 
  private:
   std::string dev_;
+  bool is_bound_;
   DISALLOW_COPY_AND_ASSIGN(ScopedLoopbackDeviceBinder);
 };