Commit 68b1410c authored by Michael Lee's avatar Michael Lee Committed by Facebook Github Bot 3

Split FileTest to a smaller test and an extended test

Summary: FileTest pulls in subprocess and does a lot more than just directly test File.h

Reviewed By: yfeldblum

Differential Revision: D2971641

fb-gh-sync-id: 16e1096ab3b0f6434a26f84c889ebb082ee3f210
shipit-source-id: 16e1096ab3b0f6434a26f84c889ebb082ee3f210
parent 7bc876aa
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/File.h>
#include <boost/thread/locks.hpp>
#include <folly/String.h>
#include <folly/Subprocess.h>
#include <folly/experimental/io/FsUtil.h>
#include <folly/experimental/TestUtil.h>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <mutex>
using namespace folly;
using namespace folly::test;
DEFINE_bool(s, false, "get shared lock");
DEFINE_bool(x, false, "get exclusive lock");
TEST(File, Locks) {
typedef std::unique_lock<File> Lock;
typedef boost::shared_lock<File> SharedLock;
// Find out where we are.
static constexpr size_t pathLength = 2048;
char buf[pathLength + 1];
int r = readlink("/proc/self/exe", buf, pathLength);
CHECK_ERR(r);
buf[r] = '\0';
fs::path me(buf);
auto helper_basename = "file_test_lock_helper";
fs::path helper;
if (fs::exists(me.parent_path() / helper_basename)) {
helper = me.parent_path() / helper_basename;
} else {
throw std::runtime_error(
folly::to<std::string>("cannot find helper ", helper_basename));
}
TemporaryFile tempFile;
File f(tempFile.fd());
enum LockMode { EXCLUSIVE, SHARED };
auto testLock = [&](LockMode mode, bool expectedSuccess) {
auto ret = Subprocess({helper.native(),
mode == SHARED ? "-s" : "-x",
tempFile.path().native()}).wait();
EXPECT_TRUE(ret.exited());
if (ret.exited()) {
EXPECT_EQ(expectedSuccess ? 0 : 42, ret.exitStatus());
}
};
// Make sure nothing breaks and things compile.
{ Lock lock(f); }
{ SharedLock lock(f); }
{
Lock lock(f, std::defer_lock);
EXPECT_TRUE(lock.try_lock());
}
{
SharedLock lock(f, boost::defer_lock);
EXPECT_TRUE(lock.try_lock());
}
// X blocks X
{
Lock lock(f);
testLock(EXCLUSIVE, false);
}
// X blocks S
{
Lock lock(f);
testLock(SHARED, false);
}
// S blocks X
{
SharedLock lock(f);
testLock(EXCLUSIVE, false);
}
// S does not block S
{
SharedLock lock(f);
testLock(SHARED, true);
}
}
...@@ -16,19 +16,11 @@ ...@@ -16,19 +16,11 @@
#include <folly/File.h> #include <folly/File.h>
#include <mutex> #include <folly/String.h>
#include <boost/thread/locks.hpp>
#include <glog/logging.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <folly/String.h>
#include <folly/Subprocess.h>
#include <folly/experimental/io/FsUtil.h>
#include <folly/experimental/TestUtil.h>
using namespace folly; using namespace folly;
using namespace folly::test;
namespace { namespace {
void expectWouldBlock(ssize_t r) { void expectWouldBlock(ssize_t r) {
...@@ -143,89 +135,3 @@ TEST(File, Truthy) { ...@@ -143,89 +135,3 @@ TEST(File, Truthy) {
EXPECT_TRUE(false); EXPECT_TRUE(false);
} }
} }
TEST(File, Locks) {
typedef std::unique_lock<File> Lock;
typedef boost::shared_lock<File> SharedLock;
// Find out where we are.
static constexpr size_t pathLength = 2048;
char buf[pathLength + 1];
int r = readlink("/proc/self/exe", buf, pathLength);
CHECK_ERR(r);
buf[r] = '\0';
// NOTE(agallagher): Our various internal build systems layout built
// binaries differently, so the two layouts below.
fs::path me(buf);
auto helper_basename = "file_test_lock_helper";
fs::path helper;
if (fs::exists(me.parent_path() / helper_basename)) {
helper = me.parent_path() / helper_basename;
} else if (fs::exists(
me.parent_path().parent_path() / helper_basename / helper_basename)) {
helper = me.parent_path().parent_path()
/ helper_basename / helper_basename;
} else {
throw std::runtime_error(
folly::to<std::string>("cannot find helper ", helper_basename));
}
TemporaryFile tempFile;
File f(tempFile.fd());
enum LockMode { EXCLUSIVE, SHARED };
auto testLock = [&] (LockMode mode, bool expectedSuccess) {
auto ret =
Subprocess({helper.native(),
mode == SHARED ? "-s" : "-x",
tempFile.path().native()}).wait();
EXPECT_TRUE(ret.exited());
if (ret.exited()) {
EXPECT_EQ(expectedSuccess ? 0 : 42, ret.exitStatus());
}
};
// Make sure nothing breaks and things compile.
{
Lock lock(f);
}
{
SharedLock lock(f);
}
{
Lock lock(f, std::defer_lock);
EXPECT_TRUE(lock.try_lock());
}
{
SharedLock lock(f, boost::defer_lock);
EXPECT_TRUE(lock.try_lock());
}
// X blocks X
{
Lock lock(f);
testLock(EXCLUSIVE, false);
}
// X blocks S
{
Lock lock(f);
testLock(SHARED, false);
}
// S blocks X
{
SharedLock lock(f);
testLock(EXCLUSIVE, false);
}
// S does not block S
{
SharedLock lock(f);
testLock(SHARED, true);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment