Make unit tests less timing sensitive when unmounting busy loop devices.
This CL modifies utils::UnmountFilesystem() to retry when umount()
fails to unmount a busy loop device and replaces several unit tests to
use the modified utils::UnmountFilesystem() instead of calling
System("umount").
BUG=chromium-os:35112
TEST=Run unit tests repeatedly.
Change-Id: I42978f02b4797c68acbec6c351ea2663b9ec7b59
Reviewed-on: https://gerrit.chromium.org/gerrit/34862
Reviewed-by: Ben Chan <[email protected]>
Tested-by: Ben Chan <[email protected]>
Commit-Ready: Ben Chan <[email protected]>
diff --git a/filesystem_iterator_unittest.cc b/filesystem_iterator_unittest.cc
index aca95ff..aed16e5 100644
--- a/filesystem_iterator_unittest.cc
+++ b/filesystem_iterator_unittest.cc
@@ -57,9 +57,9 @@
set<string> expected_paths(expected_paths_vector.begin(),
expected_paths_vector.end());
VerifyAllPaths(kMountPath, expected_paths);
-
- EXPECT_EQ(0, System(string("umount ") + kMountPath + "/some_dir/mnt"));
- EXPECT_EQ(0, System(string("umount ") + kMountPath));
+
+ EXPECT_TRUE(utils::UnmountFilesystem(kMountPath + string("/some_dir/mnt")));
+ EXPECT_TRUE(utils::UnmountFilesystem(kMountPath));
EXPECT_EQ(0, System(string("rm -f ") + first_image + " " + sub_image));
}
diff --git a/postinstall_runner_action_unittest.cc b/postinstall_runner_action_unittest.cc
index 8f42ddd..65f378e 100644
--- a/postinstall_runner_action_unittest.cc
+++ b/postinstall_runner_action_unittest.cc
@@ -119,7 +119,7 @@
ASSERT_TRUE(WriteFileString(mountpoint + "/postinst", script));
ASSERT_EQ(0, System(string("chmod a+x ") + mountpoint + "/postinst"));
- ASSERT_EQ(0, System(string("umount ") + mountpoint));
+ ASSERT_TRUE(utils::UnmountFilesystem(mountpoint));
ASSERT_EQ(0, System(string("rm -f ") + cwd + "/postinst_called"));
diff --git a/test_utils.cc b/test_utils.cc
index fddd2d1..5379979 100644
--- a/test_utils.cc
+++ b/test_utils.cc
@@ -217,7 +217,7 @@
kMountPath, kMountPath)));
EXPECT_EQ(0, System(StringPrintf("ln -s bogus %s/boguslink",
kMountPath)));
- EXPECT_EQ(0, System(StringPrintf("umount %s", kMountPath)));
+ EXPECT_TRUE(utils::UnmountFilesystem(kMountPath));
if (out_paths) {
out_paths->clear();
diff --git a/utils.cc b/utils.cc
index e0d9244..1e87262 100644
--- a/utils.cc
+++ b/utils.cc
@@ -41,6 +41,16 @@
namespace chromeos_update_engine {
+namespace {
+
+// The following constants control how UnmountFilesystem should retry if
+// umount() fails with an errno EBUSY, i.e. retry 5 times over the course of
+// one second.
+const int kUnmountMaxNumOfRetries = 5;
+const int kUnmountRetryIntervalInMicroseconds = 200 * 1000; // 200 ms
+
+} // namespace
+
namespace utils {
static const char kDevImageMarker[] = "/root/.dev_mode";
@@ -497,7 +507,14 @@
}
bool UnmountFilesystem(const string& mountpoint) {
- TEST_AND_RETURN_FALSE_ERRNO(umount(mountpoint.c_str()) == 0);
+ for (int num_retries = 0; ; ++num_retries) {
+ if (umount(mountpoint.c_str()) == 0)
+ break;
+
+ TEST_AND_RETURN_FALSE_ERRNO(errno == EBUSY &&
+ num_retries < kUnmountMaxNumOfRetries);
+ usleep(kUnmountRetryIntervalInMicroseconds);
+ }
return true;
}