FileLockTest.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright 2016-present Facebook, Inc.
  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. #include <folly/File.h>
  17. #include <mutex>
  18. #include <boost/thread/locks.hpp>
  19. #include <glog/logging.h>
  20. #include <folly/String.h>
  21. #include <folly/Subprocess.h>
  22. #include <folly/experimental/TestUtil.h>
  23. #include <folly/experimental/io/FsUtil.h>
  24. #include <folly/portability/GFlags.h>
  25. #include <folly/portability/GTest.h>
  26. using namespace folly;
  27. using namespace folly::test;
  28. DEFINE_bool(s, false, "get shared lock");
  29. DEFINE_bool(x, false, "get exclusive lock");
  30. TEST(File, Locks) {
  31. typedef std::unique_lock<File> Lock;
  32. typedef boost::shared_lock<File> SharedLock;
  33. // Find out where we are.
  34. static constexpr size_t pathLength = 2048;
  35. char buf[pathLength + 1];
  36. int r = readlink("/proc/self/exe", buf, pathLength);
  37. CHECK(r != -1);
  38. buf[r] = '\0';
  39. fs::path me(buf);
  40. auto helper_basename = "file_test_lock_helper";
  41. fs::path helper;
  42. if (fs::exists(me.parent_path() / helper_basename)) {
  43. helper = me.parent_path() / helper_basename;
  44. } else {
  45. throw std::runtime_error(
  46. folly::to<std::string>("cannot find helper ", helper_basename));
  47. }
  48. TemporaryFile tempFile;
  49. File f(tempFile.fd());
  50. enum LockMode { EXCLUSIVE, SHARED };
  51. auto testLock = [&](LockMode mode, bool expectedSuccess) {
  52. auto ret = Subprocess({helper.string(),
  53. mode == SHARED ? "-s" : "-x",
  54. tempFile.path().string()})
  55. .wait();
  56. EXPECT_TRUE(ret.exited());
  57. if (ret.exited()) {
  58. EXPECT_EQ(expectedSuccess ? 0 : 42, ret.exitStatus());
  59. }
  60. };
  61. // Make sure nothing breaks and things compile.
  62. { Lock lock(f); }
  63. { SharedLock lock(f); }
  64. {
  65. Lock lock(f, std::defer_lock);
  66. EXPECT_TRUE(lock.try_lock());
  67. }
  68. {
  69. SharedLock lock(f, boost::defer_lock);
  70. EXPECT_TRUE(lock.try_lock());
  71. }
  72. // X blocks X
  73. {
  74. Lock lock(f);
  75. testLock(EXCLUSIVE, false);
  76. }
  77. // X blocks S
  78. {
  79. Lock lock(f);
  80. testLock(SHARED, false);
  81. }
  82. // S blocks X
  83. {
  84. SharedLock lock(f);
  85. testLock(EXCLUSIVE, false);
  86. }
  87. // S does not block S
  88. {
  89. SharedLock lock(f);
  90. testLock(SHARED, true);
  91. }
  92. }