Add LOCK DATA DIRECTORY query (#68)

This commit is contained in:
antonio2368
2021-01-19 12:10:06 +01:00
committed by Antonio Andelic
parent 8f5b88f24a
commit a84ffe86c1
19 changed files with 453 additions and 81 deletions

View File

@@ -27,7 +27,7 @@ class FileLockerTest : public ::testing::Test {
std::filesystem::current_path(testing_directory);
for (auto i = 1; i <= files_number; ++i) {
std::ofstream file(fmt::format("{}", i));
std::ofstream(fmt::format("{}", i));
}
std::filesystem::current_path(save_path);
@@ -40,52 +40,158 @@ class FileLockerTest : public ::testing::Test {
}
};
TEST_F(FileLockerTest, DeleteWhileLocking) {
// Test are parameterized based on the type of path used for locking and
// deleting. We test all of the combinations for absolute/relative paths for
// locking path and absolute/relative paths for deleting
// Parameter is represented by tuple (lock_absolute, delete_absolute).
class FileLockerParameterizedTest
: public FileLockerTest,
public ::testing::WithParamInterface<std::tuple<bool, bool>> {};
TEST_P(FileLockerParameterizedTest, DeleteWhileLocking) {
CreateFiles(1);
utils::FileRetainer file_retainer;
auto t1 = std::thread([&]() {
const auto save_path = std::filesystem::current_path();
std::filesystem::current_path(testing_directory);
const auto file = std::filesystem::path("1");
const auto file_absolute = std::filesystem::absolute(file);
const auto [lock_absolute, delete_absolute] = GetParam();
{
auto locker = file_retainer.AddLocker();
{
auto acc = locker.Access();
std::this_thread::sleep_for(100ms);
file_retainer.DeleteFile(delete_absolute ? file_absolute : file);
ASSERT_TRUE(std::filesystem::exists(file));
}
});
const auto file = testing_directory / "1";
auto t2 = std::thread([&]() {
std::this_thread::sleep_for(50ms);
file_retainer.DeleteFile(file);
ASSERT_TRUE(std::filesystem::exists(file));
});
t1.join();
t2.join();
}
ASSERT_FALSE(std::filesystem::exists(file));
std::filesystem::current_path(save_path);
}
TEST_F(FileLockerTest, DeleteWhileInLocker) {
TEST_P(FileLockerParameterizedTest, DeleteWhileInLocker) {
CreateFiles(1);
utils::FileRetainer file_retainer;
const auto file = testing_directory / "1";
auto t1 = std::thread([&]() {
const auto save_path = std::filesystem::current_path();
std::filesystem::current_path(testing_directory);
const auto file = std::filesystem::path("1");
const auto file_absolute = std::filesystem::absolute(file);
const auto [lock_absolute, delete_absolute] = GetParam();
{
auto locker = file_retainer.AddLocker();
{
auto acc = locker.Access();
acc.AddFile(file);
acc.AddPath(lock_absolute ? file_absolute : file);
}
std::this_thread::sleep_for(100ms);
});
auto t2 = std::thread([&]() {
std::this_thread::sleep_for(50ms);
file_retainer.DeleteFile(file);
file_retainer.DeleteFile(delete_absolute ? file_absolute : file);
ASSERT_TRUE(std::filesystem::exists(file));
});
}
t1.join();
t2.join();
ASSERT_FALSE(std::filesystem::exists(file));
std::filesystem::current_path(save_path);
}
TEST_P(FileLockerParameterizedTest, DirectoryLock) {
utils::FileRetainer file_retainer;
// For this test we create the following file structure
// testing_directory
// 1
// additional
// 2
// We check 2 cases:
// - locking the subdirectory "additional", only "2" should be preserved
// - locking the directory testing_directory, all of the files shold be
// preserved
ASSERT_TRUE(std::filesystem::create_directory(testing_directory));
const auto save_path = std::filesystem::current_path();
std::filesystem::current_path(testing_directory);
// Create additional directory inside the testing directory with a single file
const auto additional_directory = std::filesystem::path("additional");
ASSERT_TRUE(std::filesystem::create_directory(additional_directory));
const auto nested_file =
std::filesystem::path(fmt::format("{}/2", additional_directory.string()));
const auto nested_file_absolute = std::filesystem::absolute(nested_file);
const auto file = std::filesystem::path("1");
const auto file_absolute = std::filesystem::absolute(file);
const auto directory_lock_test = [&](const bool lock_nested_directory) {
const auto directory_to_lock =
lock_nested_directory ? additional_directory : testing_directory;
const auto [lock_absolute, delete_absolute] = GetParam();
std::ofstream(file.string());
std::ofstream(nested_file.string());
{
auto locker = file_retainer.AddLocker();
{
auto acc = locker.Access();
acc.AddPath(lock_absolute ? std::filesystem::absolute(directory_to_lock)
: directory_to_lock);
}
file_retainer.DeleteFile(delete_absolute ? file_absolute : file);
ASSERT_NE(std::filesystem::exists(file), lock_nested_directory);
file_retainer.DeleteFile(delete_absolute ? nested_file_absolute
: nested_file);
ASSERT_TRUE(std::filesystem::exists(nested_file));
}
ASSERT_FALSE(std::filesystem::exists(file));
ASSERT_FALSE(std::filesystem::exists(nested_file));
};
directory_lock_test(true);
directory_lock_test(false);
std::filesystem::current_path(save_path);
}
TEST_P(FileLockerParameterizedTest, RemovePath) {
utils::FileRetainer file_retainer;
ASSERT_TRUE(std::filesystem::create_directory(testing_directory));
const auto save_path = std::filesystem::current_path();
std::filesystem::current_path(testing_directory);
const auto file = std::filesystem::path("1");
const auto file_absolute = std::filesystem::absolute(file);
auto remove_path_test = [&](const bool delete_explicitly_file) {
const auto [lock_absolute, delete_absolute] = GetParam();
// Create the file
std::ofstream(file.string());
auto locker = file_retainer.AddLocker();
{
auto acc = locker.Access();
acc.AddPath(lock_absolute ? file_absolute : file);
}
file_retainer.DeleteFile(delete_absolute ? file_absolute : file);
ASSERT_TRUE(std::filesystem::exists(file));
{
auto acc = locker.Access();
// If absolute was sent to AddPath method, use relative now
// to test those combinations.
acc.RemovePath(lock_absolute ? file : file_absolute);
}
if (delete_explicitly_file) {
file_retainer.DeleteFile(delete_absolute ? file_absolute : file);
} else {
file_retainer.CleanQueue();
}
ASSERT_FALSE(std::filesystem::exists(file));
};
remove_path_test(true);
remove_path_test(false);
std::filesystem::current_path(save_path);
}
INSTANTIATE_TEST_CASE_P(FileLockerPathVariantTests, FileLockerParameterizedTest,
::testing::Values(std::make_tuple(false, false),
std::make_tuple(false, true),
std::make_tuple(true, false),
std::make_tuple(true, true)));
TEST_F(FileLockerTest, MultipleLockers) {
CreateFiles(3);
utils::FileRetainer file_retainer;
@@ -97,17 +203,18 @@ TEST_F(FileLockerTest, MultipleLockers) {
auto locker = file_retainer.AddLocker();
{
auto acc = locker.Access();
acc.AddFile(file1);
acc.AddFile(common_file);
acc.AddPath(file1);
acc.AddPath(common_file);
}
std::this_thread::sleep_for(200ms);
});
auto t2 = std::thread([&]() {
auto locker = file_retainer.AddLocker();
{
auto acc = locker.Access();
acc.AddFile(file2);
acc.AddFile(common_file);
acc.AddPath(file2);
acc.AddPath(common_file);
}
std::this_thread::sleep_for(200ms);
});
@@ -117,7 +224,7 @@ TEST_F(FileLockerTest, MultipleLockers) {
file_retainer.DeleteFile(file1);
file_retainer.DeleteFile(file2);
file_retainer.DeleteFile(common_file);
ASSERT_FALSE(std::filesystem::exists(file1));
ASSERT_TRUE(std::filesystem::exists(file1));
ASSERT_TRUE(std::filesystem::exists(file2));
ASSERT_TRUE(std::filesystem::exists(common_file));
});
@@ -168,7 +275,7 @@ TEST_F(FileLockerTest, MultipleLockersAndDeleters) {
auto acc = locker.Access();
for (auto i = 0; i < file_access_num; ++i) {
auto file = random_file();
if (acc.AddFile(file)) {
if (acc.AddPath(file)) {
ASSERT_TRUE(std::filesystem::exists(file));
locked_files.emplace_back(std::move(file));
} else {