1//===- unittests/LockFileManagerTest.cpp - LockFileManager tests ----------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/LockFileManager.h"
11#include "llvm/Support/FileSystem.h"
12#include "llvm/Support/Path.h"
13#include "gtest/gtest.h"
14#include <memory>
15
16using namespace llvm;
17
18namespace {
19
20TEST(LockFileManagerTest, Basic) {
21  SmallString<64> TmpDir;
22  std::error_code EC;
23  EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir);
24  ASSERT_FALSE(EC);
25
26  SmallString<64> LockedFile(TmpDir);
27  sys::path::append(LockedFile, "file.lock");
28
29  {
30    // The lock file should not exist, so we should successfully acquire it.
31    LockFileManager Locked1(LockedFile);
32    EXPECT_EQ(LockFileManager::LFS_Owned, Locked1.getState());
33
34    // Attempting to reacquire the lock should fail.  Waiting on it would cause
35    // deadlock, so don't try that.
36    LockFileManager Locked2(LockedFile);
37    EXPECT_NE(LockFileManager::LFS_Owned, Locked2.getState());
38  }
39
40  // Now that the lock is out of scope, the file should be gone.
41  EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile)));
42
43  EC = sys::fs::remove(StringRef(TmpDir));
44  ASSERT_FALSE(EC);
45}
46
47TEST(LockFileManagerTest, LinkLockExists) {
48  SmallString<64> TmpDir;
49  std::error_code EC;
50  EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir);
51  ASSERT_FALSE(EC);
52
53  SmallString<64> LockedFile(TmpDir);
54  sys::path::append(LockedFile, "file");
55
56  SmallString<64> FileLocK(TmpDir);
57  sys::path::append(FileLocK, "file.lock");
58
59  SmallString<64> TmpFileLock(TmpDir);
60  sys::path::append(TmpFileLock, "file.lock-000");
61
62  int FD;
63  EC = sys::fs::openFileForWrite(StringRef(TmpFileLock), FD, sys::fs::F_None);
64  ASSERT_FALSE(EC);
65
66  int Ret = close(FD);
67  ASSERT_EQ(Ret, 0);
68
69  EC = sys::fs::create_link(TmpFileLock.str(), FileLocK.str());
70  ASSERT_FALSE(EC);
71
72  EC = sys::fs::remove(StringRef(TmpFileLock));
73  ASSERT_FALSE(EC);
74
75  {
76    // The lock file doesn't point to a real file, so we should successfully
77    // acquire it.
78    LockFileManager Locked(LockedFile);
79    EXPECT_EQ(LockFileManager::LFS_Owned, Locked.getState());
80  }
81
82  // Now that the lock is out of scope, the file should be gone.
83  EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile)));
84
85  EC = sys::fs::remove(StringRef(TmpDir));
86  ASSERT_FALSE(EC);
87}
88
89
90TEST(LockFileManagerTest, RelativePath) {
91  SmallString<64> TmpDir;
92  std::error_code EC;
93  EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir);
94  ASSERT_FALSE(EC);
95
96  char PathBuf[1024];
97  const char *OrigPath = getcwd(PathBuf, 1024);
98  chdir(TmpDir.c_str());
99
100  sys::fs::create_directory("inner");
101  SmallString<64> LockedFile("inner");
102  sys::path::append(LockedFile, "file");
103
104  SmallString<64> FileLock(LockedFile);
105  FileLock += ".lock";
106
107  {
108    // The lock file should not exist, so we should successfully acquire it.
109    LockFileManager Locked(LockedFile);
110    EXPECT_EQ(LockFileManager::LFS_Owned, Locked.getState());
111    EXPECT_TRUE(sys::fs::exists(FileLock.str()));
112  }
113
114  // Now that the lock is out of scope, the file should be gone.
115  EXPECT_FALSE(sys::fs::exists(LockedFile.str()));
116  EXPECT_FALSE(sys::fs::exists(FileLock.str()));
117
118  EC = sys::fs::remove("inner");
119  ASSERT_FALSE(EC);
120
121  chdir(OrigPath);
122
123  EC = sys::fs::remove(StringRef(TmpDir));
124  ASSERT_FALSE(EC);
125}
126
127} // end anonymous namespace
128