Home | History | Annotate | Download | only in common
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "update_engine/common/utils.h"
     18 
     19 #include <fcntl.h>
     20 #include <stdint.h>
     21 #include <sys/mount.h>
     22 #include <sys/stat.h>
     23 #include <sys/types.h>
     24 
     25 #include <string>
     26 #include <vector>
     27 
     28 #include <base/files/file_path.h>
     29 #include <base/files/file_util.h>
     30 #include <base/files/scoped_temp_dir.h>
     31 #include <gtest/gtest.h>
     32 
     33 #include "update_engine/common/test_utils.h"
     34 
     35 using std::string;
     36 using std::vector;
     37 
     38 namespace chromeos_update_engine {
     39 
     40 class UtilsTest : public ::testing::Test { };
     41 
     42 TEST(UtilsTest, CanParseECVersion) {
     43   // Should be able to parse and valid key value line.
     44   EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
     45   EXPECT_EQ("123456", utils::ParseECVersion(
     46       "b=1231a fw_version=123456 a=fasd2"));
     47   EXPECT_EQ("12345", utils::ParseECVersion("fw_version=12345"));
     48   EXPECT_EQ("00VFA616", utils::ParseECVersion(
     49       "vendor=\"sam\" fw_version=\"00VFA616\""));
     50 
     51   // For invalid entries, should return the empty string.
     52   EXPECT_EQ("", utils::ParseECVersion("b=1231a fw_version a=fasd2"));
     53 }
     54 
     55 TEST(UtilsTest, WriteFileOpenFailure) {
     56   EXPECT_FALSE(utils::WriteFile("/this/doesn't/exist", "hello", 5));
     57 }
     58 
     59 TEST(UtilsTest, WriteFileReadFile) {
     60   base::FilePath file;
     61   EXPECT_TRUE(base::CreateTemporaryFile(&file));
     62   ScopedPathUnlinker unlinker(file.value());
     63   EXPECT_TRUE(utils::WriteFile(file.value().c_str(), "hello", 5));
     64 
     65   brillo::Blob readback;
     66   EXPECT_TRUE(utils::ReadFile(file.value().c_str(), &readback));
     67   EXPECT_EQ("hello", string(readback.begin(), readback.end()));
     68 }
     69 
     70 TEST(UtilsTest, ReadFileFailure) {
     71   brillo::Blob empty;
     72   EXPECT_FALSE(utils::ReadFile("/this/doesn't/exist", &empty));
     73 }
     74 
     75 TEST(UtilsTest, ReadFileChunk) {
     76   base::FilePath file;
     77   EXPECT_TRUE(base::CreateTemporaryFile(&file));
     78   ScopedPathUnlinker unlinker(file.value());
     79   brillo::Blob data;
     80   const size_t kSize = 1024 * 1024;
     81   for (size_t i = 0; i < kSize; i++) {
     82     data.push_back(i % 255);
     83   }
     84   EXPECT_TRUE(utils::WriteFile(file.value().c_str(), data.data(), data.size()));
     85   brillo::Blob in_data;
     86   EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), kSize, 10, &in_data));
     87   EXPECT_TRUE(in_data.empty());
     88   EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), 0, -1, &in_data));
     89   EXPECT_TRUE(data == in_data);
     90   in_data.clear();
     91   EXPECT_TRUE(utils::ReadFileChunk(file.value().c_str(), 10, 20, &in_data));
     92   EXPECT_TRUE(brillo::Blob(data.begin() + 10, data.begin() + 10 + 20) ==
     93               in_data);
     94 }
     95 
     96 TEST(UtilsTest, ErrnoNumberAsStringTest) {
     97   EXPECT_EQ("No such file or directory", utils::ErrnoNumberAsString(ENOENT));
     98 }
     99 
    100 TEST(UtilsTest, IsSymlinkTest) {
    101   base::ScopedTempDir temp_dir;
    102   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    103   string temp_file = temp_dir.path().Append("temp-file").value();
    104   EXPECT_TRUE(utils::WriteFile(temp_file.c_str(), "", 0));
    105   string temp_symlink = temp_dir.path().Append("temp-symlink").value();
    106   EXPECT_EQ(0, symlink(temp_file.c_str(), temp_symlink.c_str()));
    107   EXPECT_FALSE(utils::IsSymlink(temp_dir.path().value().c_str()));
    108   EXPECT_FALSE(utils::IsSymlink(temp_file.c_str()));
    109   EXPECT_TRUE(utils::IsSymlink(temp_symlink.c_str()));
    110   EXPECT_FALSE(utils::IsSymlink("/non/existent/path"));
    111 }
    112 
    113 TEST(UtilsTest, SplitPartitionNameTest) {
    114   string disk;
    115   int part_num;
    116 
    117   EXPECT_TRUE(utils::SplitPartitionName("/dev/sda3", &disk, &part_num));
    118   EXPECT_EQ("/dev/sda", disk);
    119   EXPECT_EQ(3, part_num);
    120 
    121   EXPECT_TRUE(utils::SplitPartitionName("/dev/sdp1234", &disk, &part_num));
    122   EXPECT_EQ("/dev/sdp", disk);
    123   EXPECT_EQ(1234, part_num);
    124 
    125   EXPECT_TRUE(utils::SplitPartitionName("/dev/mmcblk0p3", &disk, &part_num));
    126   EXPECT_EQ("/dev/mmcblk0", disk);
    127   EXPECT_EQ(3, part_num);
    128 
    129   EXPECT_TRUE(utils::SplitPartitionName("/dev/ubiblock3_2", &disk, &part_num));
    130   EXPECT_EQ("/dev/ubiblock", disk);
    131   EXPECT_EQ(3, part_num);
    132 
    133   EXPECT_TRUE(utils::SplitPartitionName("/dev/loop10", &disk, &part_num));
    134   EXPECT_EQ("/dev/loop", disk);
    135   EXPECT_EQ(10, part_num);
    136 
    137   EXPECT_TRUE(utils::SplitPartitionName("/dev/loop28p11", &disk, &part_num));
    138   EXPECT_EQ("/dev/loop28", disk);
    139   EXPECT_EQ(11, part_num);
    140 
    141   EXPECT_TRUE(utils::SplitPartitionName("/dev/loop10_0", &disk, &part_num));
    142   EXPECT_EQ("/dev/loop", disk);
    143   EXPECT_EQ(10, part_num);
    144 
    145   EXPECT_TRUE(utils::SplitPartitionName("/dev/loop28p11_0", &disk, &part_num));
    146   EXPECT_EQ("/dev/loop28", disk);
    147   EXPECT_EQ(11, part_num);
    148 
    149   EXPECT_FALSE(utils::SplitPartitionName("/dev/mmcblk0p", &disk, &part_num));
    150   EXPECT_FALSE(utils::SplitPartitionName("/dev/sda", &disk, &part_num));
    151   EXPECT_FALSE(utils::SplitPartitionName("/dev/foo/bar", &disk, &part_num));
    152   EXPECT_FALSE(utils::SplitPartitionName("/", &disk, &part_num));
    153   EXPECT_FALSE(utils::SplitPartitionName("", &disk, &part_num));
    154 }
    155 
    156 TEST(UtilsTest, MakePartitionNameTest) {
    157   EXPECT_EQ("/dev/sda4", utils::MakePartitionName("/dev/sda", 4));
    158   EXPECT_EQ("/dev/sda123", utils::MakePartitionName("/dev/sda", 123));
    159   EXPECT_EQ("/dev/mmcblk2", utils::MakePartitionName("/dev/mmcblk", 2));
    160   EXPECT_EQ("/dev/mmcblk0p2", utils::MakePartitionName("/dev/mmcblk0", 2));
    161   EXPECT_EQ("/dev/loop8", utils::MakePartitionName("/dev/loop", 8));
    162   EXPECT_EQ("/dev/loop12p2", utils::MakePartitionName("/dev/loop12", 2));
    163   EXPECT_EQ("/dev/ubi5_0", utils::MakePartitionName("/dev/ubiblock", 5));
    164   EXPECT_EQ("/dev/mtd4", utils::MakePartitionName("/dev/ubiblock", 4));
    165   EXPECT_EQ("/dev/ubi3_0", utils::MakePartitionName("/dev/ubiblock", 3));
    166   EXPECT_EQ("/dev/mtd2", utils::MakePartitionName("/dev/ubiblock", 2));
    167   EXPECT_EQ("/dev/ubi1_0", utils::MakePartitionName("/dev/ubiblock", 1));
    168 }
    169 
    170 TEST(UtilsTest, MakePartitionNameForMountTest) {
    171   EXPECT_EQ("/dev/sda4", utils::MakePartitionNameForMount("/dev/sda4"));
    172   EXPECT_EQ("/dev/sda123", utils::MakePartitionNameForMount("/dev/sda123"));
    173   EXPECT_EQ("/dev/mmcblk2", utils::MakePartitionNameForMount("/dev/mmcblk2"));
    174   EXPECT_EQ("/dev/mmcblk0p2",
    175             utils::MakePartitionNameForMount("/dev/mmcblk0p2"));
    176   EXPECT_EQ("/dev/loop0", utils::MakePartitionNameForMount("/dev/loop0"));
    177   EXPECT_EQ("/dev/loop8", utils::MakePartitionNameForMount("/dev/loop8"));
    178   EXPECT_EQ("/dev/loop12p2",
    179             utils::MakePartitionNameForMount("/dev/loop12p2"));
    180   EXPECT_EQ("/dev/ubiblock5_0",
    181             utils::MakePartitionNameForMount("/dev/ubiblock5_0"));
    182   EXPECT_EQ("/dev/mtd4",
    183             utils::MakePartitionNameForMount("/dev/ubi4_0"));
    184   EXPECT_EQ("/dev/ubiblock3_0",
    185             utils::MakePartitionNameForMount("/dev/ubiblock3"));
    186   EXPECT_EQ("/dev/mtd2", utils::MakePartitionNameForMount("/dev/ubi2"));
    187   EXPECT_EQ("/dev/ubi1_0",
    188             utils::MakePartitionNameForMount("/dev/ubiblock1"));
    189 }
    190 
    191 TEST(UtilsTest, FuzzIntTest) {
    192   static const uint32_t kRanges[] = { 0, 1, 2, 20 };
    193   for (uint32_t range : kRanges) {
    194     const int kValue = 50;
    195     for (int tries = 0; tries < 100; ++tries) {
    196       uint32_t value = utils::FuzzInt(kValue, range);
    197       EXPECT_GE(value, kValue - range / 2);
    198       EXPECT_LE(value, kValue + range - range / 2);
    199     }
    200   }
    201 }
    202 
    203 namespace {
    204 void GetFileFormatTester(const string& expected,
    205                          const vector<uint8_t>& contents) {
    206   test_utils::ScopedTempFile file;
    207   ASSERT_TRUE(utils::WriteFile(file.path().c_str(),
    208                                reinterpret_cast<const char*>(contents.data()),
    209                                contents.size()));
    210   EXPECT_EQ(expected, utils::GetFileFormat(file.path()));
    211 }
    212 }  // namespace
    213 
    214 TEST(UtilsTest, GetFileFormatTest) {
    215   EXPECT_EQ("File not found.", utils::GetFileFormat("/path/to/nowhere"));
    216   GetFileFormatTester("data", vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8});
    217   GetFileFormatTester("ELF", vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46});
    218 
    219   // Real tests from cros_installer on different boards.
    220   // ELF 32-bit LSB executable, Intel 80386
    221   GetFileFormatTester(
    222       "ELF 32-bit little-endian x86",
    223       vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
    224                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    225                       0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
    226                       0x90, 0x83, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00});
    227 
    228   // ELF 32-bit LSB executable, MIPS
    229   GetFileFormatTester(
    230       "ELF 32-bit little-endian mips",
    231       vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
    232                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    233                       0x03, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
    234                       0xc0, 0x12, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
    235 
    236   // ELF 32-bit LSB executable, ARM
    237   GetFileFormatTester(
    238       "ELF 32-bit little-endian arm",
    239       vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00,
    240                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    241                       0x02, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00,
    242                       0x85, 0x8b, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00});
    243 
    244   // ELF 64-bit LSB executable, x86-64
    245   GetFileFormatTester(
    246       "ELF 64-bit little-endian x86-64",
    247       vector<uint8_t>{0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
    248                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    249                       0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
    250                       0xb0, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00});
    251 }
    252 
    253 TEST(UtilsTest, FormatTimeDeltaTest) {
    254   // utils::FormatTimeDelta() is not locale-aware (it's only used for logging
    255   // which is not localized) so we only need to test the C locale
    256   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromMilliseconds(100)),
    257             "0.1s");
    258   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(0)),
    259             "0s");
    260   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1)),
    261             "1s");
    262   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(59)),
    263             "59s");
    264   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(60)),
    265             "1m0s");
    266   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(61)),
    267             "1m1s");
    268   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(90)),
    269             "1m30s");
    270   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(1205)),
    271             "20m5s");
    272   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3600)),
    273             "1h0m0s");
    274   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3601)),
    275             "1h0m1s");
    276   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(3661)),
    277             "1h1m1s");
    278   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(7261)),
    279             "2h1m1s");
    280   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86400)),
    281             "1d0h0m0s");
    282   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(86401)),
    283             "1d0h0m1s");
    284   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000)),
    285             "2d7h33m20s");
    286   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(200000) +
    287                                    base::TimeDelta::FromMilliseconds(1)),
    288             "2d7h33m20.001s");
    289   EXPECT_EQ(utils::FormatTimeDelta(base::TimeDelta::FromSeconds(-1)),
    290             "-1s");
    291 }
    292 
    293 TEST(UtilsTest, TimeFromStructTimespecTest) {
    294   struct timespec ts;
    295 
    296   // Unix epoch (Thursday 00:00:00 UTC on Jan 1, 1970)
    297   ts = (struct timespec) {.tv_sec = 0, .tv_nsec = 0};
    298   EXPECT_EQ(base::Time::UnixEpoch(), utils::TimeFromStructTimespec(&ts));
    299 
    300   // 42 ms after the Unix billennium (Sunday 01:46:40 UTC on September 9, 2001)
    301   ts = (struct timespec) {.tv_sec = 1000 * 1000 * 1000,
    302                           .tv_nsec = 42 * 1000 * 1000};
    303   base::Time::Exploded exploded = (base::Time::Exploded) {
    304     .year = 2001, .month = 9, .day_of_week = 0, .day_of_month = 9,
    305     .hour = 1, .minute = 46, .second = 40, .millisecond = 42};
    306   EXPECT_EQ(base::Time::FromUTCExploded(exploded),
    307             utils::TimeFromStructTimespec(&ts));
    308 }
    309 
    310 TEST(UtilsTest, DecodeAndStoreBase64String) {
    311   base::FilePath path;
    312 
    313   // Ensure we return false on empty strings or invalid base64.
    314   EXPECT_FALSE(utils::DecodeAndStoreBase64String("", &path));
    315   EXPECT_FALSE(utils::DecodeAndStoreBase64String("not valid base64", &path));
    316 
    317   // Pass known base64 and check that it matches. This string was generated
    318   // the following way:
    319   //
    320   //   $ echo "Update Engine" | base64
    321   //   VXBkYXRlIEVuZ2luZQo=
    322   EXPECT_TRUE(utils::DecodeAndStoreBase64String("VXBkYXRlIEVuZ2luZQo=",
    323                                                 &path));
    324   ScopedPathUnlinker unlinker(path.value());
    325   string expected_contents = "Update Engine\n";
    326   string contents;
    327   EXPECT_TRUE(utils::ReadFile(path.value(), &contents));
    328   EXPECT_EQ(contents, expected_contents);
    329   EXPECT_EQ(static_cast<off_t>(expected_contents.size()),
    330             utils::FileSize(path.value()));
    331 }
    332 
    333 TEST(UtilsTest, ConvertToOmahaInstallDate) {
    334   // The Omaha Epoch starts at Jan 1, 2007 0:00 PST which is a
    335   // Monday. In Unix time, this point in time is easily obtained via
    336   // the date(1) command like this:
    337   //
    338   //  $ date +"%s" --date="Jan 1, 2007 0:00 PST"
    339   const time_t omaha_epoch = 1167638400;
    340   int value;
    341 
    342   // Points in time *on and after* the Omaha epoch should not fail.
    343   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    344       base::Time::FromTimeT(omaha_epoch), &value));
    345   EXPECT_GE(value, 0);
    346 
    347   // Anything before the Omaha epoch should fail. We test it for two points.
    348   EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
    349       base::Time::FromTimeT(omaha_epoch - 1), &value));
    350   EXPECT_FALSE(utils::ConvertToOmahaInstallDate(
    351       base::Time::FromTimeT(omaha_epoch - 100*24*3600), &value));
    352 
    353   // Check that we jump from 0 to 7 exactly on the one-week mark, e.g.
    354   // on Jan 8, 2007 0:00 PST.
    355   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    356       base::Time::FromTimeT(omaha_epoch + 7*24*3600 - 1), &value));
    357   EXPECT_EQ(value, 0);
    358   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    359       base::Time::FromTimeT(omaha_epoch + 7*24*3600), &value));
    360   EXPECT_EQ(value, 7);
    361 
    362   // Check a couple of more values.
    363   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    364       base::Time::FromTimeT(omaha_epoch + 10*24*3600), &value));
    365   EXPECT_EQ(value, 7);
    366   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    367       base::Time::FromTimeT(omaha_epoch + 20*24*3600), &value));
    368   EXPECT_EQ(value, 14);
    369   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    370       base::Time::FromTimeT(omaha_epoch + 26*24*3600), &value));
    371   EXPECT_EQ(value, 21);
    372   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    373       base::Time::FromTimeT(omaha_epoch + 29*24*3600), &value));
    374   EXPECT_EQ(value, 28);
    375 
    376   // The date Jun 4, 2007 0:00 PDT is a Monday and is hence a point
    377   // where the Omaha InstallDate jumps 7 days. Its unix time is
    378   // 1180940400. Notably, this is a point in time where Daylight
    379   // Savings Time (DST) was is in effect (e.g. it's PDT, not PST).
    380   //
    381   // Note that as utils::ConvertToOmahaInstallDate() _deliberately_
    382   // ignores DST (as it's hard to implement in a thread-safe way using
    383   // glibc, see comments in utils.h) we have to fudge by the DST
    384   // offset which is one hour. Conveniently, if the function were
    385   // someday modified to be DST aware, this test would have to be
    386   // modified as well.
    387   const time_t dst_time = 1180940400;  // Jun 4, 2007 0:00 PDT.
    388   const time_t fudge = 3600;
    389   int value1, value2;
    390   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    391       base::Time::FromTimeT(dst_time + fudge - 1), &value1));
    392   EXPECT_TRUE(utils::ConvertToOmahaInstallDate(
    393       base::Time::FromTimeT(dst_time + fudge), &value2));
    394   EXPECT_EQ(value1, value2 - 7);
    395 }
    396 
    397 TEST(UtilsTest, GetMinorVersion) {
    398   // Test GetMinorVersion by verifying that it parses the conf file and returns
    399   // the correct value.
    400   uint32_t minor_version;
    401 
    402   brillo::KeyValueStore store;
    403   EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
    404 
    405   EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=one-two-three\n"));
    406   EXPECT_FALSE(utils::GetMinorVersion(store, &minor_version));
    407 
    408   EXPECT_TRUE(store.LoadFromString("PAYLOAD_MINOR_VERSION=123\n"));
    409   EXPECT_TRUE(utils::GetMinorVersion(store, &minor_version));
    410   EXPECT_EQ(123U, minor_version);
    411 }
    412 
    413 static bool BoolMacroTestHelper() {
    414   int i = 1;
    415   unsigned int ui = 1;
    416   bool b = 1;
    417   std::unique_ptr<char> cptr(new char);
    418 
    419   TEST_AND_RETURN_FALSE(i);
    420   TEST_AND_RETURN_FALSE(ui);
    421   TEST_AND_RETURN_FALSE(b);
    422   TEST_AND_RETURN_FALSE(cptr);
    423 
    424   TEST_AND_RETURN_FALSE_ERRNO(i);
    425   TEST_AND_RETURN_FALSE_ERRNO(ui);
    426   TEST_AND_RETURN_FALSE_ERRNO(b);
    427   TEST_AND_RETURN_FALSE_ERRNO(cptr);
    428 
    429   return true;
    430 }
    431 
    432 static void VoidMacroTestHelper(bool* ret) {
    433   int i = 1;
    434   unsigned int ui = 1;
    435   bool b = 1;
    436   std::unique_ptr<char> cptr(new char);
    437 
    438   *ret = false;
    439 
    440   TEST_AND_RETURN(i);
    441   TEST_AND_RETURN(ui);
    442   TEST_AND_RETURN(b);
    443   TEST_AND_RETURN(cptr);
    444 
    445   TEST_AND_RETURN_ERRNO(i);
    446   TEST_AND_RETURN_ERRNO(ui);
    447   TEST_AND_RETURN_ERRNO(b);
    448   TEST_AND_RETURN_ERRNO(cptr);
    449 
    450   *ret = true;
    451 }
    452 
    453 TEST(UtilsTest, TestMacros) {
    454   bool void_test = false;
    455   VoidMacroTestHelper(&void_test);
    456   EXPECT_TRUE(void_test);
    457 
    458   EXPECT_TRUE(BoolMacroTestHelper());
    459 }
    460 
    461 TEST(UtilsTest, RunAsRootUnmountFilesystemFailureTest) {
    462   EXPECT_FALSE(utils::UnmountFilesystem("/path/to/non-existing-dir"));
    463 }
    464 
    465 TEST(UtilsTest, RunAsRootUnmountFilesystemBusyFailureTest) {
    466   string tmp_image;
    467   EXPECT_TRUE(utils::MakeTempFile("img.XXXXXX", &tmp_image, nullptr));
    468   ScopedPathUnlinker tmp_image_unlinker(tmp_image);
    469 
    470   EXPECT_TRUE(base::CopyFile(
    471       test_utils::GetBuildArtifactsPath().Append("gen/disk_ext2_4k.img"),
    472       base::FilePath(tmp_image)));
    473 
    474   base::ScopedTempDir mnt_dir;
    475   EXPECT_TRUE(mnt_dir.CreateUniqueTempDir());
    476 
    477   string loop_dev;
    478   test_utils::ScopedLoopbackDeviceBinder loop_binder(
    479       tmp_image, true, &loop_dev);
    480 
    481   EXPECT_FALSE(utils::IsMountpoint(mnt_dir.path().value()));
    482   // This is the actual test part. While we hold a file descriptor open for the
    483   // mounted filesystem, umount should still succeed.
    484   EXPECT_TRUE(utils::MountFilesystem(
    485       loop_dev, mnt_dir.path().value(), MS_RDONLY, "ext4", ""));
    486   // Verify the directory is a mount point now.
    487   EXPECT_TRUE(utils::IsMountpoint(mnt_dir.path().value()));
    488 
    489   string target_file = mnt_dir.path().Append("empty-file").value();
    490   int fd = HANDLE_EINTR(open(target_file.c_str(), O_RDONLY));
    491   EXPECT_GE(fd, 0);
    492   EXPECT_TRUE(utils::UnmountFilesystem(mnt_dir.path().value()));
    493   // The filesystem should be already unmounted at this point.
    494   EXPECT_FALSE(utils::IsMountpoint(mnt_dir.path().value()));
    495   IGNORE_EINTR(close(fd));
    496   // The filesystem was already unmounted so this call should fail.
    497   EXPECT_FALSE(utils::UnmountFilesystem(mnt_dir.path().value()));
    498 }
    499 
    500 TEST(UtilsTest, IsMountpointTest) {
    501   EXPECT_TRUE(utils::IsMountpoint("/"));
    502   EXPECT_FALSE(utils::IsMountpoint("/path/to/nowhere"));
    503 
    504   base::ScopedTempDir mnt_dir;
    505   EXPECT_TRUE(mnt_dir.CreateUniqueTempDir());
    506   EXPECT_FALSE(utils::IsMountpoint(mnt_dir.path().value()));
    507 
    508   base::FilePath file;
    509   EXPECT_TRUE(base::CreateTemporaryFile(&file));
    510   ScopedPathUnlinker unlinker(file.value());
    511   EXPECT_FALSE(utils::IsMountpoint(file.value()));
    512 }
    513 
    514 }  // namespace chromeos_update_engine
    515