comparison unittests/Support/Path.cpp @ 148:63bd29f05246

merged
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 14 Aug 2019 19:46:37 +0900
parents c2174574ed3a
children
comparison
equal deleted inserted replaced
146:3fc4d5c3e21e 148:63bd29f05246
1 //===- llvm/unittest/Support/Path.cpp - Path tests ------------------------===// 1 //===- llvm/unittest/Support/Path.cpp - Path tests ------------------------===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // 4 // See https://llvm.org/LICENSE.txt for license information.
5 // This file is distributed under the University of Illinois Open Source 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 // License. See LICENSE.TXT for details.
7 // 6 //
8 //===----------------------------------------------------------------------===// 7 //===----------------------------------------------------------------------===//
9 8
10 #include "llvm/Support/Path.h" 9 #include "llvm/Support/Path.h"
11 #include "llvm/ADT/STLExtras.h" 10 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallVector.h" 11 #include "llvm/ADT/SmallVector.h"
13 #include "llvm/ADT/Triple.h" 12 #include "llvm/ADT/Triple.h"
14 #include "llvm/BinaryFormat/Magic.h" 13 #include "llvm/BinaryFormat/Magic.h"
14 #include "llvm/Config/llvm-config.h"
15 #include "llvm/Support/ConvertUTF.h" 15 #include "llvm/Support/ConvertUTF.h"
16 #include "llvm/Support/Errc.h" 16 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/ErrorHandling.h" 17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/FileSystem.h" 18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/FileUtilities.h" 19 #include "llvm/Support/FileUtilities.h"
20 #include "llvm/Support/Host.h" 20 #include "llvm/Support/Host.h"
21 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/raw_ostream.h" 22 #include "llvm/Support/raw_ostream.h"
23 #include "gtest/gtest.h" 23 #include "gtest/gtest.h"
24 24 #include "gmock/gmock.h"
25 #ifdef LLVM_ON_WIN32 25
26 #ifdef _WIN32
26 #include "llvm/ADT/ArrayRef.h" 27 #include "llvm/ADT/ArrayRef.h"
28 #include "llvm/Support/Chrono.h"
27 #include <windows.h> 29 #include <windows.h>
28 #include <winerror.h> 30 #include <winerror.h>
29 #endif 31 #endif
30 32
31 #ifdef LLVM_ON_UNIX 33 #ifdef LLVM_ON_UNIX
45 << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ 47 << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
46 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ 48 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
47 } else { \ 49 } else { \
48 } 50 }
49 51
52 #define ASSERT_ERROR(x) \
53 if (!x) { \
54 SmallString<128> MessageStorage; \
55 raw_svector_ostream Message(MessageStorage); \
56 Message << #x ": did not return a failure error code.\n"; \
57 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
58 }
59
50 namespace { 60 namespace {
61
62 struct FileDescriptorCloser {
63 explicit FileDescriptorCloser(int FD) : FD(FD) {}
64 ~FileDescriptorCloser() { ::close(FD); }
65 int FD;
66 };
51 67
52 TEST(is_separator, Works) { 68 TEST(is_separator, Works) {
53 EXPECT_TRUE(path::is_separator('/')); 69 EXPECT_TRUE(path::is_separator('/'));
54 EXPECT_FALSE(path::is_separator('\0')); 70 EXPECT_FALSE(path::is_separator('\0'));
55 EXPECT_FALSE(path::is_separator('-')); 71 EXPECT_FALSE(path::is_separator('-'));
56 EXPECT_FALSE(path::is_separator(' ')); 72 EXPECT_FALSE(path::is_separator(' '));
57 73
58 EXPECT_TRUE(path::is_separator('\\', path::Style::windows)); 74 EXPECT_TRUE(path::is_separator('\\', path::Style::windows));
59 EXPECT_FALSE(path::is_separator('\\', path::Style::posix)); 75 EXPECT_FALSE(path::is_separator('\\', path::Style::posix));
60 76
61 #ifdef LLVM_ON_WIN32 77 #ifdef _WIN32
62 EXPECT_TRUE(path::is_separator('\\')); 78 EXPECT_TRUE(path::is_separator('\\'));
63 #else 79 #else
64 EXPECT_FALSE(path::is_separator('\\')); 80 EXPECT_FALSE(path::is_separator('\\'));
65 #endif 81 #endif
66 } 82 }
76 paths.push_back("foo/"); 92 paths.push_back("foo/");
77 paths.push_back("/foo/"); 93 paths.push_back("/foo/");
78 paths.push_back("foo/bar"); 94 paths.push_back("foo/bar");
79 paths.push_back("/foo/bar"); 95 paths.push_back("/foo/bar");
80 paths.push_back("//net"); 96 paths.push_back("//net");
97 paths.push_back("//net/");
81 paths.push_back("//net/foo"); 98 paths.push_back("//net/foo");
82 paths.push_back("///foo///"); 99 paths.push_back("///foo///");
83 paths.push_back("///foo///bar"); 100 paths.push_back("///foo///bar");
84 paths.push_back("/."); 101 paths.push_back("/.");
85 paths.push_back("./"); 102 paths.push_back("./");
106 paths.push_back("c:foo\\"); 123 paths.push_back("c:foo\\");
107 paths.push_back("c:\\foo\\"); 124 paths.push_back("c:\\foo\\");
108 paths.push_back("c:\\foo/"); 125 paths.push_back("c:\\foo/");
109 paths.push_back("c:/foo\\bar"); 126 paths.push_back("c:/foo\\bar");
110 127
111 SmallVector<StringRef, 5> ComponentStack;
112 for (SmallVector<StringRef, 40>::const_iterator i = paths.begin(), 128 for (SmallVector<StringRef, 40>::const_iterator i = paths.begin(),
113 e = paths.end(); 129 e = paths.end();
114 i != e; 130 i != e;
115 ++i) { 131 ++i) {
132 SCOPED_TRACE(*i);
133 SmallVector<StringRef, 5> ComponentStack;
116 for (sys::path::const_iterator ci = sys::path::begin(*i), 134 for (sys::path::const_iterator ci = sys::path::begin(*i),
117 ce = sys::path::end(*i); 135 ce = sys::path::end(*i);
118 ci != ce; 136 ci != ce;
119 ++ci) { 137 ++ci) {
120 ASSERT_FALSE(ci->empty()); 138 EXPECT_FALSE(ci->empty());
121 ComponentStack.push_back(*ci); 139 ComponentStack.push_back(*ci);
122 } 140 }
123 141
142 SmallVector<StringRef, 5> ReverseComponentStack;
124 for (sys::path::reverse_iterator ci = sys::path::rbegin(*i), 143 for (sys::path::reverse_iterator ci = sys::path::rbegin(*i),
125 ce = sys::path::rend(*i); 144 ce = sys::path::rend(*i);
126 ci != ce; 145 ci != ce;
127 ++ci) { 146 ++ci) {
128 ASSERT_TRUE(*ci == ComponentStack.back()); 147 EXPECT_FALSE(ci->empty());
129 ComponentStack.pop_back(); 148 ReverseComponentStack.push_back(*ci);
130 } 149 }
131 ASSERT_TRUE(ComponentStack.empty()); 150 std::reverse(ReverseComponentStack.begin(), ReverseComponentStack.end());
151 EXPECT_THAT(ComponentStack, testing::ContainerEq(ReverseComponentStack));
132 152
133 // Crash test most of the API - since we're iterating over all of our paths 153 // Crash test most of the API - since we're iterating over all of our paths
134 // here there isn't really anything reasonable to assert on in the results. 154 // here there isn't really anything reasonable to assert on in the results.
135 (void)path::has_root_path(*i); 155 (void)path::has_root_path(*i);
136 (void)path::root_path(*i); 156 (void)path::root_path(*i);
163 EXPECT_EQ(*sys::path::rbegin(filename), (stem + ext).str()); 183 EXPECT_EQ(*sys::path::rbegin(filename), (stem + ext).str());
164 184
165 path::native(*i, temp_store); 185 path::native(*i, temp_store);
166 } 186 }
167 187
168 SmallString<32> Relative("foo.cpp"); 188 {
169 ASSERT_NO_ERROR(sys::fs::make_absolute("/root", Relative)); 189 SmallString<32> Relative("foo.cpp");
170 Relative[5] = '/'; // Fix up windows paths. 190 sys::fs::make_absolute("/root", Relative);
171 ASSERT_EQ("/root/foo.cpp", Relative); 191 Relative[5] = '/'; // Fix up windows paths.
172 } 192 ASSERT_EQ("/root/foo.cpp", Relative);
173 193 }
174 TEST(Support, RelativePathIterator) { 194
175 SmallString<64> Path(StringRef("c/d/e/foo.txt")); 195 {
176 typedef SmallVector<StringRef, 4> PathComponents; 196 SmallString<32> Relative("foo.cpp");
177 PathComponents ExpectedPathComponents; 197 sys::fs::make_absolute("//root", Relative);
178 PathComponents ActualPathComponents; 198 Relative[6] = '/'; // Fix up windows paths.
179 199 ASSERT_EQ("//root/foo.cpp", Relative);
180 StringRef(Path).split(ExpectedPathComponents, '/'); 200 }
181 201 }
182 for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E; 202
183 ++I) { 203 TEST(Support, FilenameParent) {
184 ActualPathComponents.push_back(*I); 204 EXPECT_EQ("/", path::filename("/"));
185 } 205 EXPECT_EQ("", path::parent_path("/"));
186 206
187 ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size()); 207 EXPECT_EQ("\\", path::filename("c:\\", path::Style::windows));
188 208 EXPECT_EQ("c:", path::parent_path("c:\\", path::Style::windows));
189 for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) { 209
190 EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str()); 210 EXPECT_EQ("/", path::filename("///"));
191 } 211 EXPECT_EQ("", path::parent_path("///"));
192 } 212
193 213 EXPECT_EQ("\\", path::filename("c:\\\\", path::Style::windows));
194 TEST(Support, RelativePathDotIterator) { 214 EXPECT_EQ("c:", path::parent_path("c:\\\\", path::Style::windows));
195 SmallString<64> Path(StringRef(".c/.d/../.")); 215
196 typedef SmallVector<StringRef, 4> PathComponents; 216 EXPECT_EQ("bar", path::filename("/foo/bar"));
197 PathComponents ExpectedPathComponents; 217 EXPECT_EQ("/foo", path::parent_path("/foo/bar"));
198 PathComponents ActualPathComponents; 218
199 219 EXPECT_EQ("foo", path::filename("/foo"));
200 StringRef(Path).split(ExpectedPathComponents, '/'); 220 EXPECT_EQ("/", path::parent_path("/foo"));
201 221
202 for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E; 222 EXPECT_EQ("foo", path::filename("foo"));
203 ++I) { 223 EXPECT_EQ("", path::parent_path("foo"));
204 ActualPathComponents.push_back(*I); 224
205 } 225 EXPECT_EQ(".", path::filename("foo/"));
206 226 EXPECT_EQ("foo", path::parent_path("foo/"));
207 ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size()); 227
208 228 EXPECT_EQ("//net", path::filename("//net"));
209 for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) { 229 EXPECT_EQ("", path::parent_path("//net"));
210 EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str()); 230
211 } 231 EXPECT_EQ("/", path::filename("//net/"));
212 } 232 EXPECT_EQ("//net", path::parent_path("//net/"));
213 233
214 TEST(Support, AbsolutePathIterator) { 234 EXPECT_EQ("foo", path::filename("//net/foo"));
215 SmallString<64> Path(StringRef("/c/d/e/foo.txt")); 235 EXPECT_EQ("//net/", path::parent_path("//net/foo"));
216 typedef SmallVector<StringRef, 4> PathComponents; 236
217 PathComponents ExpectedPathComponents; 237 // These checks are just to make sure we do something reasonable with the
218 PathComponents ActualPathComponents; 238 // paths below. They are not meant to prescribe the one true interpretation of
219 239 // these paths. Other decompositions (e.g. "//" -> "" + "//") are also
220 StringRef(Path).split(ExpectedPathComponents, '/'); 240 // possible.
221 241 EXPECT_EQ("/", path::filename("//"));
222 // The root path will also be a component when iterating 242 EXPECT_EQ("", path::parent_path("//"));
223 ExpectedPathComponents[0] = "/"; 243
224 244 EXPECT_EQ("\\", path::filename("\\\\", path::Style::windows));
225 for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E; 245 EXPECT_EQ("", path::parent_path("\\\\", path::Style::windows));
226 ++I) { 246
227 ActualPathComponents.push_back(*I); 247 EXPECT_EQ("\\", path::filename("\\\\\\", path::Style::windows));
228 } 248 EXPECT_EQ("", path::parent_path("\\\\\\", path::Style::windows));
229 249 }
230 ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size()); 250
231 251 static std::vector<StringRef>
232 for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) { 252 GetComponents(StringRef Path, path::Style S = path::Style::native) {
233 EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str()); 253 return {path::begin(Path, S), path::end(Path)};
234 } 254 }
235 } 255
236 256 TEST(Support, PathIterator) {
237 TEST(Support, AbsolutePathDotIterator) { 257 EXPECT_THAT(GetComponents("/foo"), testing::ElementsAre("/", "foo"));
238 SmallString<64> Path(StringRef("/.c/.d/../.")); 258 EXPECT_THAT(GetComponents("/"), testing::ElementsAre("/"));
239 typedef SmallVector<StringRef, 4> PathComponents; 259 EXPECT_THAT(GetComponents("//"), testing::ElementsAre("/"));
240 PathComponents ExpectedPathComponents; 260 EXPECT_THAT(GetComponents("///"), testing::ElementsAre("/"));
241 PathComponents ActualPathComponents; 261 EXPECT_THAT(GetComponents("c/d/e/foo.txt"),
242 262 testing::ElementsAre("c", "d", "e", "foo.txt"));
243 StringRef(Path).split(ExpectedPathComponents, '/'); 263 EXPECT_THAT(GetComponents(".c/.d/../."),
244 264 testing::ElementsAre(".c", ".d", "..", "."));
245 // The root path will also be a component when iterating 265 EXPECT_THAT(GetComponents("/c/d/e/foo.txt"),
246 ExpectedPathComponents[0] = "/"; 266 testing::ElementsAre("/", "c", "d", "e", "foo.txt"));
247 267 EXPECT_THAT(GetComponents("/.c/.d/../."),
248 for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E; 268 testing::ElementsAre("/", ".c", ".d", "..", "."));
249 ++I) { 269 EXPECT_THAT(GetComponents("c:\\c\\e\\foo.txt", path::Style::windows),
250 ActualPathComponents.push_back(*I); 270 testing::ElementsAre("c:", "\\", "c", "e", "foo.txt"));
251 } 271 EXPECT_THAT(GetComponents("//net/"), testing::ElementsAre("//net", "/"));
252 272 EXPECT_THAT(GetComponents("//net/c/foo.txt"),
253 ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size()); 273 testing::ElementsAre("//net", "/", "c", "foo.txt"));
254
255 for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
256 EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
257 }
258 }
259
260 TEST(Support, AbsolutePathIteratorWin32) {
261 SmallString<64> Path(StringRef("c:\\c\\e\\foo.txt"));
262 typedef SmallVector<StringRef, 4> PathComponents;
263 PathComponents ExpectedPathComponents;
264 PathComponents ActualPathComponents;
265
266 StringRef(Path).split(ExpectedPathComponents, "\\");
267
268 // The root path (which comes after the drive name) will also be a component
269 // when iterating.
270 ExpectedPathComponents.insert(ExpectedPathComponents.begin()+1, "\\");
271
272 for (path::const_iterator I = path::begin(Path, path::Style::windows),
273 E = path::end(Path);
274 I != E; ++I) {
275 ActualPathComponents.push_back(*I);
276 }
277
278 ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
279
280 for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
281 EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
282 }
283 } 274 }
284 275
285 TEST(Support, AbsolutePathIteratorEnd) { 276 TEST(Support, AbsolutePathIteratorEnd) {
286 // Trailing slashes are converted to '.' unless they are part of the root path. 277 // Trailing slashes are converted to '.' unless they are part of the root path.
287 SmallVector<std::pair<StringRef, path::Style>, 4> Paths; 278 SmallVector<std::pair<StringRef, path::Style>, 4> Paths;
288 Paths.emplace_back("/foo/", path::Style::native); 279 Paths.emplace_back("/foo/", path::Style::native);
289 Paths.emplace_back("/foo//", path::Style::native); 280 Paths.emplace_back("/foo//", path::Style::native);
290 Paths.emplace_back("//net//", path::Style::native); 281 Paths.emplace_back("//net/foo/", path::Style::native);
291 Paths.emplace_back("c:\\\\", path::Style::windows); 282 Paths.emplace_back("c:\\foo\\", path::Style::windows);
292 283
293 for (auto &Path : Paths) { 284 for (auto &Path : Paths) {
285 SCOPED_TRACE(Path.first);
294 StringRef LastComponent = *path::rbegin(Path.first, Path.second); 286 StringRef LastComponent = *path::rbegin(Path.first, Path.second);
295 EXPECT_EQ(".", LastComponent); 287 EXPECT_EQ(".", LastComponent);
296 } 288 }
297 289
298 SmallVector<std::pair<StringRef, path::Style>, 3> RootPaths; 290 SmallVector<std::pair<StringRef, path::Style>, 3> RootPaths;
299 RootPaths.emplace_back("/", path::Style::native); 291 RootPaths.emplace_back("/", path::Style::native);
300 RootPaths.emplace_back("//net/", path::Style::native); 292 RootPaths.emplace_back("//net/", path::Style::native);
301 RootPaths.emplace_back("c:\\", path::Style::windows); 293 RootPaths.emplace_back("c:\\", path::Style::windows);
294 RootPaths.emplace_back("//net//", path::Style::native);
295 RootPaths.emplace_back("c:\\\\", path::Style::windows);
302 296
303 for (auto &Path : RootPaths) { 297 for (auto &Path : RootPaths) {
298 SCOPED_TRACE(Path.first);
304 StringRef LastComponent = *path::rbegin(Path.first, Path.second); 299 StringRef LastComponent = *path::rbegin(Path.first, Path.second);
305 EXPECT_EQ(1u, LastComponent.size()); 300 EXPECT_EQ(1u, LastComponent.size());
306 EXPECT_TRUE(path::is_separator(LastComponent[0], Path.second)); 301 EXPECT_TRUE(path::is_separator(LastComponent[0], Path.second));
307 } 302 }
308 } 303 }
309 304
310 TEST(Support, HomeDirectory) { 305 TEST(Support, HomeDirectory) {
311 std::string expected; 306 std::string expected;
312 #ifdef LLVM_ON_WIN32 307 #ifdef _WIN32
313 if (wchar_t const *path = ::_wgetenv(L"USERPROFILE")) { 308 if (wchar_t const *path = ::_wgetenv(L"USERPROFILE")) {
314 auto pathLen = ::wcslen(path); 309 auto pathLen = ::wcslen(path);
315 ArrayRef<char> ref{reinterpret_cast<char const *>(path), 310 ArrayRef<char> ref{reinterpret_cast<char const *>(path),
316 pathLen * sizeof(wchar_t)}; 311 pathLen * sizeof(wchar_t)};
317 convertUTF16ToUTF8String(ref, expected); 312 convertUTF16ToUTF8String(ref, expected);
358 // unset before, we don't reset it). 353 // unset before, we don't reset it).
359 if (OriginalEnv) ::setenv("HOME", OriginalEnv, 1); 354 if (OriginalEnv) ::setenv("HOME", OriginalEnv, 1);
360 } 355 }
361 #endif 356 #endif
362 357
363 TEST(Support, UserCacheDirectory) {
364 SmallString<13> CacheDir;
365 SmallString<20> CacheDir2;
366 auto Status = path::user_cache_directory(CacheDir, "");
367 EXPECT_TRUE(Status ^ CacheDir.empty());
368
369 if (Status) {
370 EXPECT_TRUE(path::user_cache_directory(CacheDir2, "")); // should succeed
371 EXPECT_EQ(CacheDir, CacheDir2); // and return same paths
372
373 EXPECT_TRUE(path::user_cache_directory(CacheDir, "A", "B", "file.c"));
374 auto It = path::rbegin(CacheDir);
375 EXPECT_EQ("file.c", *It);
376 EXPECT_EQ("B", *++It);
377 EXPECT_EQ("A", *++It);
378 auto ParentDir = *++It;
379
380 // Test Unicode: "<user_cache_dir>/(pi)r^2/aleth.0"
381 EXPECT_TRUE(path::user_cache_directory(CacheDir2, "\xCF\x80r\xC2\xB2",
382 "\xE2\x84\xB5.0"));
383 auto It2 = path::rbegin(CacheDir2);
384 EXPECT_EQ("\xE2\x84\xB5.0", *It2);
385 EXPECT_EQ("\xCF\x80r\xC2\xB2", *++It2);
386 auto ParentDir2 = *++It2;
387
388 EXPECT_EQ(ParentDir, ParentDir2);
389 }
390 }
391
392 TEST(Support, TempDirectory) { 358 TEST(Support, TempDirectory) {
393 SmallString<32> TempDir; 359 SmallString<32> TempDir;
394 path::system_temp_directory(false, TempDir); 360 path::system_temp_directory(false, TempDir);
395 EXPECT_TRUE(!TempDir.empty()); 361 EXPECT_TRUE(!TempDir.empty());
396 TempDir.clear(); 362 TempDir.clear();
397 path::system_temp_directory(true, TempDir); 363 path::system_temp_directory(true, TempDir);
398 EXPECT_TRUE(!TempDir.empty()); 364 EXPECT_TRUE(!TempDir.empty());
399 } 365 }
400 366
401 #ifdef LLVM_ON_WIN32 367 #ifdef _WIN32
402 static std::string path2regex(std::string Path) { 368 static std::string path2regex(std::string Path) {
403 size_t Pos = 0; 369 size_t Pos = 0;
404 while ((Pos = Path.find('\\', Pos)) != std::string::npos) { 370 while ((Pos = Path.find('\\', Pos)) != std::string::npos) {
405 Path.replace(Pos, 1, "\\\\"); 371 Path.replace(Pos, 1, "\\\\");
406 Pos += 2; 372 Pos += 2;
462 class FileSystemTest : public testing::Test { 428 class FileSystemTest : public testing::Test {
463 protected: 429 protected:
464 /// Unique temporary directory in which all created filesystem entities must 430 /// Unique temporary directory in which all created filesystem entities must
465 /// be placed. It is removed at the end of each test (must be empty). 431 /// be placed. It is removed at the end of each test (must be empty).
466 SmallString<128> TestDirectory; 432 SmallString<128> TestDirectory;
433 SmallString<128> NonExistantFile;
467 434
468 void SetUp() override { 435 void SetUp() override {
469 ASSERT_NO_ERROR( 436 ASSERT_NO_ERROR(
470 fs::createUniqueDirectory("file-system-test", TestDirectory)); 437 fs::createUniqueDirectory("file-system-test", TestDirectory));
471 // We don't care about this specific file. 438 // We don't care about this specific file.
472 errs() << "Test Directory: " << TestDirectory << '\n'; 439 errs() << "Test Directory: " << TestDirectory << '\n';
473 errs().flush(); 440 errs().flush();
441 NonExistantFile = TestDirectory;
442
443 // Even though this value is hardcoded, is a 128-bit GUID, so we should be
444 // guaranteed that this file will never exist.
445 sys::path::append(NonExistantFile, "1B28B495C16344CB9822E588CD4C3EF0");
474 } 446 }
475 447
476 void TearDown() override { ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } 448 void TearDown() override { ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); }
477 }; 449 };
478 450
550 Twine(TestDirectory) + "/././test1/../test1/test2/./test3/..", Actual)); 522 Twine(TestDirectory) + "/././test1/../test1/test2/./test3/..", Actual));
551 523
552 EXPECT_EQ(Expected, Actual); 524 EXPECT_EQ(Expected, Actual);
553 525
554 SmallString<64> HomeDir; 526 SmallString<64> HomeDir;
527
528 // This can fail if $HOME is not set and getpwuid fails.
555 bool Result = llvm::sys::path::home_directory(HomeDir); 529 bool Result = llvm::sys::path::home_directory(HomeDir);
556 if (Result) { 530 if (Result) {
557 ASSERT_NO_ERROR(fs::real_path(HomeDir, Expected)); 531 ASSERT_NO_ERROR(fs::real_path(HomeDir, Expected));
558 ASSERT_NO_ERROR(fs::real_path("~", Actual, true)); 532 ASSERT_NO_ERROR(fs::real_path("~", Actual, true));
559 EXPECT_EQ(Expected, Actual); 533 EXPECT_EQ(Expected, Actual);
562 } 536 }
563 537
564 ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/test1")); 538 ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/test1"));
565 } 539 }
566 540
541 TEST_F(FileSystemTest, ExpandTilde) {
542 SmallString<64> Expected;
543 SmallString<64> Actual;
544 SmallString<64> HomeDir;
545
546 // This can fail if $HOME is not set and getpwuid fails.
547 bool Result = llvm::sys::path::home_directory(HomeDir);
548 if (Result) {
549 fs::expand_tilde(HomeDir, Expected);
550
551 fs::expand_tilde("~", Actual);
552 EXPECT_EQ(Expected, Actual);
553
554 #ifdef _WIN32
555 Expected += "\\foo";
556 fs::expand_tilde("~\\foo", Actual);
557 #else
558 Expected += "/foo";
559 fs::expand_tilde("~/foo", Actual);
560 #endif
561
562 EXPECT_EQ(Expected, Actual);
563 }
564 }
565
567 #ifdef LLVM_ON_UNIX 566 #ifdef LLVM_ON_UNIX
568 TEST_F(FileSystemTest, RealPathNoReadPerm) { 567 TEST_F(FileSystemTest, RealPathNoReadPerm) {
569 SmallString<64> Expanded; 568 SmallString<64> Expanded;
570 569
571 ASSERT_NO_ERROR( 570 ASSERT_NO_ERROR(
586 TEST_F(FileSystemTest, TempFileKeepDiscard) { 585 TEST_F(FileSystemTest, TempFileKeepDiscard) {
587 // We can keep then discard. 586 // We can keep then discard.
588 auto TempFileOrError = fs::TempFile::create(TestDirectory + "/test-%%%%"); 587 auto TempFileOrError = fs::TempFile::create(TestDirectory + "/test-%%%%");
589 ASSERT_TRUE((bool)TempFileOrError); 588 ASSERT_TRUE((bool)TempFileOrError);
590 fs::TempFile File = std::move(*TempFileOrError); 589 fs::TempFile File = std::move(*TempFileOrError);
590 ASSERT_EQ(-1, TempFileOrError->FD);
591 ASSERT_FALSE((bool)File.keep(TestDirectory + "/keep")); 591 ASSERT_FALSE((bool)File.keep(TestDirectory + "/keep"));
592 ASSERT_FALSE((bool)File.discard()); 592 ASSERT_FALSE((bool)File.discard());
593 ASSERT_TRUE(fs::exists(TestDirectory + "/keep")); 593 ASSERT_TRUE(fs::exists(TestDirectory + "/keep"));
594 ASSERT_NO_ERROR(fs::remove(TestDirectory + "/keep")); 594 ASSERT_NO_ERROR(fs::remove(TestDirectory + "/keep"));
595 } 595 }
597 TEST_F(FileSystemTest, TempFileDiscardDiscard) { 597 TEST_F(FileSystemTest, TempFileDiscardDiscard) {
598 // We can discard twice. 598 // We can discard twice.
599 auto TempFileOrError = fs::TempFile::create(TestDirectory + "/test-%%%%"); 599 auto TempFileOrError = fs::TempFile::create(TestDirectory + "/test-%%%%");
600 ASSERT_TRUE((bool)TempFileOrError); 600 ASSERT_TRUE((bool)TempFileOrError);
601 fs::TempFile File = std::move(*TempFileOrError); 601 fs::TempFile File = std::move(*TempFileOrError);
602 ASSERT_EQ(-1, TempFileOrError->FD);
602 ASSERT_FALSE((bool)File.discard()); 603 ASSERT_FALSE((bool)File.discard());
603 ASSERT_FALSE((bool)File.discard()); 604 ASSERT_FALSE((bool)File.discard());
604 ASSERT_FALSE(fs::exists(TestDirectory + "/keep")); 605 ASSERT_FALSE(fs::exists(TestDirectory + "/keep"));
605 } 606 }
606 607
665 666
666 // Make sure Temp1 doesn't exist. 667 // Make sure Temp1 doesn't exist.
667 ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist), 668 ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist),
668 errc::no_such_file_or_directory); 669 errc::no_such_file_or_directory);
669 670
670 #ifdef LLVM_ON_WIN32 671 #ifdef _WIN32
671 // Path name > 260 chars should get an error. 672 // Path name > 260 chars should get an error.
672 const char *Path270 = 673 const char *Path270 =
673 "abcdefghijklmnopqrstuvwxyz9abcdefghijklmnopqrstuvwxyz8" 674 "abcdefghijklmnopqrstuvwxyz9abcdefghijklmnopqrstuvwxyz8"
674 "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" 675 "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6"
675 "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" 676 "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4"
686 ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath)); 687 ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath));
687 ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); 688 ASSERT_NO_ERROR(fs::remove(Twine(TempPath)));
688 #endif 689 #endif
689 } 690 }
690 691
692 TEST_F(FileSystemTest, TempFileCollisions) {
693 SmallString<128> TestDirectory;
694 ASSERT_NO_ERROR(
695 fs::createUniqueDirectory("CreateUniqueFileTest", TestDirectory));
696 FileRemover Cleanup(TestDirectory);
697 SmallString<128> Model = TestDirectory;
698 path::append(Model, "%.tmp");
699 SmallString<128> Path;
700 std::vector<fs::TempFile> TempFiles;
701
702 auto TryCreateTempFile = [&]() {
703 Expected<fs::TempFile> T = fs::TempFile::create(Model);
704 if (T) {
705 TempFiles.push_back(std::move(*T));
706 return true;
707 } else {
708 logAllUnhandledErrors(T.takeError(), errs(),
709 "Failed to create temporary file: ");
710 return false;
711 }
712 };
713
714 // Our single-character template allows for 16 unique names. Check that
715 // calling TryCreateTempFile repeatedly results in 16 successes.
716 // Because the test depends on random numbers, it could theoretically fail.
717 // However, the probability of this happening is tiny: with 32 calls, each
718 // of which will retry up to 128 times, to not get a given digit we would
719 // have to fail at least 15 + 17 * 128 = 2191 attempts. The probability of
720 // 2191 attempts not producing a given hexadecimal digit is
721 // (1 - 1/16) ** 2191 or 3.88e-62.
722 int Successes = 0;
723 for (int i = 0; i < 32; ++i)
724 if (TryCreateTempFile()) ++Successes;
725 EXPECT_EQ(Successes, 16);
726
727 for (fs::TempFile &T : TempFiles)
728 cantFail(T.discard());
729 }
730
691 TEST_F(FileSystemTest, CreateDir) { 731 TEST_F(FileSystemTest, CreateDir) {
692 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); 732 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo"));
693 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); 733 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo"));
694 ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), 734 ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false),
695 errc::file_exists); 735 errc::file_exists);
713 753
714 // Restore umask to be safe. 754 // Restore umask to be safe.
715 ::umask(OldUmask); 755 ::umask(OldUmask);
716 #endif 756 #endif
717 757
718 #ifdef LLVM_ON_WIN32 758 #ifdef _WIN32
719 // Prove that create_directories() can handle a pathname > 248 characters, 759 // Prove that create_directories() can handle a pathname > 248 characters,
720 // which is the documented limit for CreateDirectory(). 760 // which is the documented limit for CreateDirectory().
721 // (248 is MAX_PATH subtracting room for an 8.3 filename.) 761 // (248 is MAX_PATH subtracting room for an 8.3 filename.)
722 // Generate a directory path guaranteed to fall into that range. 762 // Generate a directory path guaranteed to fall into that range.
723 size_t TmpLen = TestDirectory.size(); 763 size_t TmpLen = TestDirectory.size();
883 Twine(TestDirectory) + "/symlink/d/da")); 923 Twine(TestDirectory) + "/symlink/d/da"));
884 ASSERT_NO_ERROR( 924 ASSERT_NO_ERROR(
885 fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/e")); 925 fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/e"));
886 926
887 typedef std::vector<std::string> v_t; 927 typedef std::vector<std::string> v_t;
888 v_t visited; 928 v_t VisitedNonBrokenSymlinks;
889 929 v_t VisitedBrokenSymlinks;
890 // The directory iterator doesn't stat the file, so we should be able to
891 // iterate over the whole directory.
892 std::error_code ec; 930 std::error_code ec;
931 using testing::UnorderedElementsAre;
932 using testing::UnorderedElementsAreArray;
933
934 // Broken symbol links are expected to throw an error.
893 for (fs::directory_iterator i(Twine(TestDirectory) + "/symlink", ec), e; 935 for (fs::directory_iterator i(Twine(TestDirectory) + "/symlink", ec), e;
894 i != e; i.increment(ec)) { 936 i != e; i.increment(ec)) {
895 ASSERT_NO_ERROR(ec); 937 ASSERT_NO_ERROR(ec);
896 visited.push_back(path::filename(i->path())); 938 if (i->status().getError() ==
897 } 939 std::make_error_code(std::errc::no_such_file_or_directory)) {
898 std::sort(visited.begin(), visited.end()); 940 VisitedBrokenSymlinks.push_back(path::filename(i->path()));
899 v_t expected = {"a", "b", "c", "d", "e"}; 941 continue;
900 ASSERT_TRUE(visited.size() == expected.size()); 942 }
901 ASSERT_TRUE(std::equal(visited.begin(), visited.end(), expected.begin())); 943 VisitedNonBrokenSymlinks.push_back(path::filename(i->path()));
902 visited.clear(); 944 }
903 945 EXPECT_THAT(VisitedNonBrokenSymlinks, UnorderedElementsAre("b", "d"));
904 // The recursive directory iterator has to stat the file, so we need to skip 946 VisitedNonBrokenSymlinks.clear();
905 // the broken symlinks. 947
906 for (fs::recursive_directory_iterator 948 EXPECT_THAT(VisitedBrokenSymlinks, UnorderedElementsAre("a", "c", "e"));
907 i(Twine(TestDirectory) + "/symlink", ec), 949 VisitedBrokenSymlinks.clear();
908 e; 950
951 // Broken symbol links are expected to throw an error.
952 for (fs::recursive_directory_iterator i(
953 Twine(TestDirectory) + "/symlink", ec), e; i != e; i.increment(ec)) {
954 ASSERT_NO_ERROR(ec);
955 if (i->status().getError() ==
956 std::make_error_code(std::errc::no_such_file_or_directory)) {
957 VisitedBrokenSymlinks.push_back(path::filename(i->path()));
958 continue;
959 }
960 VisitedNonBrokenSymlinks.push_back(path::filename(i->path()));
961 }
962 EXPECT_THAT(VisitedNonBrokenSymlinks,
963 UnorderedElementsAre("b", "bb", "d", "da", "dd", "ddd", "ddd"));
964 VisitedNonBrokenSymlinks.clear();
965
966 EXPECT_THAT(VisitedBrokenSymlinks,
967 UnorderedElementsAre("a", "ba", "bc", "c", "e"));
968 VisitedBrokenSymlinks.clear();
969
970 for (fs::recursive_directory_iterator i(
971 Twine(TestDirectory) + "/symlink", ec, /*follow_symlinks=*/false), e;
909 i != e; i.increment(ec)) { 972 i != e; i.increment(ec)) {
910 ASSERT_NO_ERROR(ec); 973 ASSERT_NO_ERROR(ec);
911 974 if (i->status().getError() ==
912 ErrorOr<fs::basic_file_status> status = i->status();
913 if (status.getError() ==
914 std::make_error_code(std::errc::no_such_file_or_directory)) { 975 std::make_error_code(std::errc::no_such_file_or_directory)) {
915 i.no_push(); 976 VisitedBrokenSymlinks.push_back(path::filename(i->path()));
916 continue; 977 continue;
917 } 978 }
918 979 VisitedNonBrokenSymlinks.push_back(path::filename(i->path()));
919 visited.push_back(path::filename(i->path())); 980 }
920 } 981 EXPECT_THAT(VisitedNonBrokenSymlinks,
921 std::sort(visited.begin(), visited.end()); 982 UnorderedElementsAreArray({"a", "b", "ba", "bb", "bc", "c", "d",
922 expected = {"b", "bb", "d", "da", "dd", "ddd", "ddd"}; 983 "da", "dd", "ddd", "e"}));
923 ASSERT_TRUE(visited.size() == expected.size()); 984 VisitedNonBrokenSymlinks.clear();
924 ASSERT_TRUE(std::equal(visited.begin(), visited.end(), expected.begin())); 985
925 visited.clear(); 986 EXPECT_THAT(VisitedBrokenSymlinks, UnorderedElementsAre());
926 987 VisitedBrokenSymlinks.clear();
927 // This recursive directory iterator doesn't follow symlinks, so we don't need
928 // to skip them.
929 for (fs::recursive_directory_iterator
930 i(Twine(TestDirectory) + "/symlink", ec, /*follow_symlinks=*/false),
931 e;
932 i != e; i.increment(ec)) {
933 ASSERT_NO_ERROR(ec);
934 visited.push_back(path::filename(i->path()));
935 }
936 std::sort(visited.begin(), visited.end());
937 expected = {"a", "b", "ba", "bb", "bc", "c", "d", "da", "dd", "ddd", "e"};
938 ASSERT_TRUE(visited.size() == expected.size());
939 ASSERT_TRUE(std::equal(visited.begin(), visited.end(), expected.begin()));
940 988
941 ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/symlink")); 989 ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/symlink"));
942 } 990 }
943 #endif 991 #endif
944 992
973 1021
974 ASSERT_NO_ERROR(fs::remove_directories(BaseDir)); 1022 ASSERT_NO_ERROR(fs::remove_directories(BaseDir));
975 ASSERT_FALSE(fs::exists(BaseDir)); 1023 ASSERT_FALSE(fs::exists(BaseDir));
976 } 1024 }
977 1025
978 #ifdef LLVM_ON_WIN32 1026 #ifdef _WIN32
979 TEST_F(FileSystemTest, CarriageReturn) { 1027 TEST_F(FileSystemTest, CarriageReturn) {
980 SmallString<128> FilePathname(TestDirectory); 1028 SmallString<128> FilePathname(TestDirectory);
981 std::error_code EC; 1029 std::error_code EC;
982 path::append(FilePathname, "test"); 1030 path::append(FilePathname, "test");
983 1031
984 { 1032 {
985 raw_fd_ostream File(FilePathname, EC, sys::fs::F_Text); 1033 raw_fd_ostream File(FilePathname, EC, sys::fs::OF_Text);
986 ASSERT_NO_ERROR(EC); 1034 ASSERT_NO_ERROR(EC);
987 File << '\n'; 1035 File << '\n';
988 } 1036 }
989 { 1037 {
990 auto Buf = MemoryBuffer::getFile(FilePathname.str()); 1038 auto Buf = MemoryBuffer::getFile(FilePathname.str());
991 EXPECT_TRUE((bool)Buf); 1039 EXPECT_TRUE((bool)Buf);
992 EXPECT_EQ(Buf.get()->getBuffer(), "\r\n"); 1040 EXPECT_EQ(Buf.get()->getBuffer(), "\r\n");
993 } 1041 }
994 1042
995 { 1043 {
996 raw_fd_ostream File(FilePathname, EC, sys::fs::F_None); 1044 raw_fd_ostream File(FilePathname, EC, sys::fs::OF_None);
997 ASSERT_NO_ERROR(EC); 1045 ASSERT_NO_ERROR(EC);
998 File << '\n'; 1046 File << '\n';
999 } 1047 }
1000 { 1048 {
1001 auto Buf = MemoryBuffer::getFile(FilePathname.str()); 1049 auto Buf = MemoryBuffer::getFile(FilePathname.str());
1043 1091
1044 // Map in temp file and add some content 1092 // Map in temp file and add some content
1045 std::error_code EC; 1093 std::error_code EC;
1046 StringRef Val("hello there"); 1094 StringRef Val("hello there");
1047 { 1095 {
1048 fs::mapped_file_region mfr(FileDescriptor, 1096 fs::mapped_file_region mfr(fs::convertFDToNativeFile(FileDescriptor),
1049 fs::mapped_file_region::readwrite, Size, 0, EC); 1097 fs::mapped_file_region::readwrite, Size, 0, EC);
1050 ASSERT_NO_ERROR(EC); 1098 ASSERT_NO_ERROR(EC);
1051 std::copy(Val.begin(), Val.end(), mfr.data()); 1099 std::copy(Val.begin(), Val.end(), mfr.data());
1052 // Explicitly add a 0. 1100 // Explicitly add a 0.
1053 mfr.data()[Val.size()] = 0; 1101 mfr.data()[Val.size()] = 0;
1058 // Map it back in read-only 1106 // Map it back in read-only
1059 { 1107 {
1060 int FD; 1108 int FD;
1061 EC = fs::openFileForRead(Twine(TempPath), FD); 1109 EC = fs::openFileForRead(Twine(TempPath), FD);
1062 ASSERT_NO_ERROR(EC); 1110 ASSERT_NO_ERROR(EC);
1063 fs::mapped_file_region mfr(FD, fs::mapped_file_region::readonly, Size, 0, EC); 1111 fs::mapped_file_region mfr(fs::convertFDToNativeFile(FD),
1112 fs::mapped_file_region::readonly, Size, 0, EC);
1064 ASSERT_NO_ERROR(EC); 1113 ASSERT_NO_ERROR(EC);
1065 1114
1066 // Verify content 1115 // Verify content
1067 EXPECT_EQ(StringRef(mfr.const_data()), Val); 1116 EXPECT_EQ(StringRef(mfr.const_data()), Val);
1068 1117
1069 // Unmap temp file 1118 // Unmap temp file
1070 fs::mapped_file_region m(FD, fs::mapped_file_region::readonly, Size, 0, EC); 1119 fs::mapped_file_region m(fs::convertFDToNativeFile(FD),
1120 fs::mapped_file_region::readonly, Size, 0, EC);
1071 ASSERT_NO_ERROR(EC); 1121 ASSERT_NO_ERROR(EC);
1072 ASSERT_EQ(close(FD), 0); 1122 ASSERT_EQ(close(FD), 0);
1073 } 1123 }
1074 ASSERT_NO_ERROR(fs::remove(TempPath)); 1124 ASSERT_NO_ERROR(fs::remove(TempPath));
1075 } 1125 }
1091 path::native(Posix, path::Style::posix); 1141 path::native(Posix, path::Style::posix);
1092 EXPECT_EQ(std::get<1>(T), Win); 1142 EXPECT_EQ(std::get<1>(T), Win);
1093 EXPECT_EQ(std::get<2>(T), Posix); 1143 EXPECT_EQ(std::get<2>(T), Posix);
1094 } 1144 }
1095 1145
1096 #if defined(LLVM_ON_WIN32) 1146 #if defined(_WIN32)
1097 SmallString<64> PathHome; 1147 SmallString<64> PathHome;
1098 path::home_directory(PathHome); 1148 path::home_directory(PathHome);
1099 1149
1100 const char *Path7a = "~/aaa"; 1150 const char *Path7a = "~/aaa";
1101 SmallString<64> Path7(Path7a); 1151 SmallString<64> Path7(Path7a);
1212 ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); 1262 ASSERT_TRUE(sys::fs::exists(Twine(TempPath)));
1213 1263
1214 // Open the file for read 1264 // Open the file for read
1215 int FileDescriptor2; 1265 int FileDescriptor2;
1216 SmallString<64> ResultPath; 1266 SmallString<64> ResultPath;
1217 ASSERT_NO_ERROR( 1267 ASSERT_NO_ERROR(fs::openFileForRead(Twine(TempPath), FileDescriptor2,
1218 fs::openFileForRead(Twine(TempPath), FileDescriptor2, &ResultPath)) 1268 fs::OF_None, &ResultPath))
1219 1269
1220 // If we succeeded, check that the paths are the same (modulo case): 1270 // If we succeeded, check that the paths are the same (modulo case):
1221 if (!ResultPath.empty()) { 1271 if (!ResultPath.empty()) {
1222 // The paths returned by createTemporaryFile and getPathFromOpenFD 1272 // The paths returned by createTemporaryFile and getPathFromOpenFD
1223 // should reference the same file on disk. 1273 // should reference the same file on disk.
1224 fs::UniqueID D1, D2; 1274 fs::UniqueID D1, D2;
1225 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1)); 1275 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1));
1226 ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2)); 1276 ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2));
1227 ASSERT_EQ(D1, D2); 1277 ASSERT_EQ(D1, D2);
1228 } 1278 }
1229
1230 ::close(FileDescriptor); 1279 ::close(FileDescriptor);
1280 ::close(FileDescriptor2);
1281
1282 #ifdef _WIN32
1283 // Since Windows Vista, file access time is not updated by default.
1284 // This is instead updated manually by openFileForRead.
1285 // https://blogs.technet.microsoft.com/filecab/2006/11/07/disabling-last-access-time-in-windows-vista-to-improve-ntfs-performance/
1286 // This part of the unit test is Windows specific as the updating of
1287 // access times can be disabled on Linux using /etc/fstab.
1288
1289 // Set access time to UNIX epoch.
1290 ASSERT_NO_ERROR(sys::fs::openFileForWrite(Twine(TempPath), FileDescriptor,
1291 fs::CD_OpenExisting));
1292 TimePoint<> Epoch(std::chrono::milliseconds(0));
1293 ASSERT_NO_ERROR(fs::setLastAccessAndModificationTime(FileDescriptor, Epoch));
1294 ::close(FileDescriptor);
1295
1296 // Open the file and ensure access time is updated, when forced.
1297 ASSERT_NO_ERROR(fs::openFileForRead(Twine(TempPath), FileDescriptor,
1298 fs::OF_UpdateAtime, &ResultPath));
1299
1300 sys::fs::file_status Status;
1301 ASSERT_NO_ERROR(sys::fs::status(FileDescriptor, Status));
1302 auto FileAccessTime = Status.getLastAccessedTime();
1303
1304 ASSERT_NE(Epoch, FileAccessTime);
1305 ::close(FileDescriptor);
1306
1307 // Ideally this test would include a case when ATime is not forced to update,
1308 // however the expected behaviour will differ depending on the configuration
1309 // of the Windows file system.
1310 #endif
1311 }
1312
1313 static void createFileWithData(const Twine &Path, bool ShouldExistBefore,
1314 fs::CreationDisposition Disp, StringRef Data) {
1315 int FD;
1316 ASSERT_EQ(ShouldExistBefore, fs::exists(Path));
1317 ASSERT_NO_ERROR(fs::openFileForWrite(Path, FD, Disp));
1318 FileDescriptorCloser Closer(FD);
1319 ASSERT_TRUE(fs::exists(Path));
1320
1321 ASSERT_EQ(Data.size(), (size_t)write(FD, Data.data(), Data.size()));
1322 }
1323
1324 static void verifyFileContents(const Twine &Path, StringRef Contents) {
1325 auto Buffer = MemoryBuffer::getFile(Path);
1326 ASSERT_TRUE((bool)Buffer);
1327 StringRef Data = Buffer.get()->getBuffer();
1328 ASSERT_EQ(Data, Contents);
1329 }
1330
1331 TEST_F(FileSystemTest, CreateNew) {
1332 int FD;
1333 Optional<FileDescriptorCloser> Closer;
1334
1335 // Succeeds if the file does not exist.
1336 ASSERT_FALSE(fs::exists(NonExistantFile));
1337 ASSERT_NO_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateNew));
1338 ASSERT_TRUE(fs::exists(NonExistantFile));
1339
1340 FileRemover Cleanup(NonExistantFile);
1341 Closer.emplace(FD);
1342
1343 // And creates a file of size 0.
1344 sys::fs::file_status Status;
1345 ASSERT_NO_ERROR(sys::fs::status(FD, Status));
1346 EXPECT_EQ(0ULL, Status.getSize());
1347
1348 // Close this first, before trying to re-open the file.
1349 Closer.reset();
1350
1351 // But fails if the file does exist.
1352 ASSERT_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateNew));
1353 }
1354
1355 TEST_F(FileSystemTest, CreateAlways) {
1356 int FD;
1357 Optional<FileDescriptorCloser> Closer;
1358
1359 // Succeeds if the file does not exist.
1360 ASSERT_FALSE(fs::exists(NonExistantFile));
1361 ASSERT_NO_ERROR(
1362 fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateAlways));
1363
1364 Closer.emplace(FD);
1365
1366 ASSERT_TRUE(fs::exists(NonExistantFile));
1367
1368 FileRemover Cleanup(NonExistantFile);
1369
1370 // And creates a file of size 0.
1371 uint64_t FileSize;
1372 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1373 ASSERT_EQ(0ULL, FileSize);
1374
1375 // If we write some data to it re-create it with CreateAlways, it succeeds and
1376 // truncates to 0 bytes.
1377 ASSERT_EQ(4, write(FD, "Test", 4));
1378
1379 Closer.reset();
1380
1381 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1382 ASSERT_EQ(4ULL, FileSize);
1383
1384 ASSERT_NO_ERROR(
1385 fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateAlways));
1386 Closer.emplace(FD);
1387 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1388 ASSERT_EQ(0ULL, FileSize);
1389 }
1390
1391 TEST_F(FileSystemTest, OpenExisting) {
1392 int FD;
1393
1394 // Fails if the file does not exist.
1395 ASSERT_FALSE(fs::exists(NonExistantFile));
1396 ASSERT_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_OpenExisting));
1397 ASSERT_FALSE(fs::exists(NonExistantFile));
1398
1399 // Make a dummy file now so that we can try again when the file does exist.
1400 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1401 FileRemover Cleanup(NonExistantFile);
1402 uint64_t FileSize;
1403 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1404 ASSERT_EQ(4ULL, FileSize);
1405
1406 // If we re-create it with different data, it overwrites rather than
1407 // appending.
1408 createFileWithData(NonExistantFile, true, fs::CD_OpenExisting, "Buzz");
1409 verifyFileContents(NonExistantFile, "Buzz");
1410 }
1411
1412 TEST_F(FileSystemTest, OpenAlways) {
1413 // Succeeds if the file does not exist.
1414 createFileWithData(NonExistantFile, false, fs::CD_OpenAlways, "Fizz");
1415 FileRemover Cleanup(NonExistantFile);
1416 uint64_t FileSize;
1417 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1418 ASSERT_EQ(4ULL, FileSize);
1419
1420 // Now re-open it and write again, verifying the contents get over-written.
1421 createFileWithData(NonExistantFile, true, fs::CD_OpenAlways, "Bu");
1422 verifyFileContents(NonExistantFile, "Buzz");
1423 }
1424
1425 TEST_F(FileSystemTest, AppendSetsCorrectFileOffset) {
1426 fs::CreationDisposition Disps[] = {fs::CD_CreateAlways, fs::CD_OpenAlways,
1427 fs::CD_OpenExisting};
1428
1429 // Write some data and re-open it with every possible disposition (this is a
1430 // hack that shouldn't work, but is left for compatibility. OF_Append
1431 // overrides
1432 // the specified disposition.
1433 for (fs::CreationDisposition Disp : Disps) {
1434 int FD;
1435 Optional<FileDescriptorCloser> Closer;
1436
1437 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1438
1439 FileRemover Cleanup(NonExistantFile);
1440
1441 uint64_t FileSize;
1442 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1443 ASSERT_EQ(4ULL, FileSize);
1444 ASSERT_NO_ERROR(
1445 fs::openFileForWrite(NonExistantFile, FD, Disp, fs::OF_Append));
1446 Closer.emplace(FD);
1447 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1448 ASSERT_EQ(4ULL, FileSize);
1449
1450 ASSERT_EQ(4, write(FD, "Buzz", 4));
1451 Closer.reset();
1452
1453 verifyFileContents(NonExistantFile, "FizzBuzz");
1454 }
1455 }
1456
1457 static void verifyRead(int FD, StringRef Data, bool ShouldSucceed) {
1458 std::vector<char> Buffer;
1459 Buffer.resize(Data.size());
1460 int Result = ::read(FD, Buffer.data(), Buffer.size());
1461 if (ShouldSucceed) {
1462 ASSERT_EQ((size_t)Result, Data.size());
1463 ASSERT_EQ(Data, StringRef(Buffer.data(), Buffer.size()));
1464 } else {
1465 ASSERT_EQ(-1, Result);
1466 ASSERT_EQ(EBADF, errno);
1467 }
1468 }
1469
1470 static void verifyWrite(int FD, StringRef Data, bool ShouldSucceed) {
1471 int Result = ::write(FD, Data.data(), Data.size());
1472 if (ShouldSucceed)
1473 ASSERT_EQ((size_t)Result, Data.size());
1474 else {
1475 ASSERT_EQ(-1, Result);
1476 ASSERT_EQ(EBADF, errno);
1477 }
1478 }
1479
1480 TEST_F(FileSystemTest, ReadOnlyFileCantWrite) {
1481 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1482 FileRemover Cleanup(NonExistantFile);
1483
1484 int FD;
1485 ASSERT_NO_ERROR(fs::openFileForRead(NonExistantFile, FD));
1486 FileDescriptorCloser Closer(FD);
1487
1488 verifyWrite(FD, "Buzz", false);
1489 verifyRead(FD, "Fizz", true);
1490 }
1491
1492 TEST_F(FileSystemTest, WriteOnlyFileCantRead) {
1493 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1494 FileRemover Cleanup(NonExistantFile);
1495
1496 int FD;
1497 ASSERT_NO_ERROR(
1498 fs::openFileForWrite(NonExistantFile, FD, fs::CD_OpenExisting));
1499 FileDescriptorCloser Closer(FD);
1500 verifyRead(FD, "Fizz", false);
1501 verifyWrite(FD, "Buzz", true);
1502 }
1503
1504 TEST_F(FileSystemTest, ReadWriteFileCanReadOrWrite) {
1505 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1506 FileRemover Cleanup(NonExistantFile);
1507
1508 int FD;
1509 ASSERT_NO_ERROR(fs::openFileForReadWrite(NonExistantFile, FD,
1510 fs::CD_OpenExisting, fs::OF_None));
1511 FileDescriptorCloser Closer(FD);
1512 verifyRead(FD, "Fizz", true);
1513 verifyWrite(FD, "Buzz", true);
1514 }
1515
1516 TEST_F(FileSystemTest, is_local) {
1517 bool TestDirectoryIsLocal;
1518 ASSERT_NO_ERROR(fs::is_local(TestDirectory, TestDirectoryIsLocal));
1519 EXPECT_EQ(TestDirectoryIsLocal, fs::is_local(TestDirectory));
1520
1521 int FD;
1522 SmallString<128> TempPath;
1523 ASSERT_NO_ERROR(
1524 fs::createUniqueFile(Twine(TestDirectory) + "/temp", FD, TempPath));
1525 FileRemover Cleanup(TempPath);
1526
1527 // Make sure it exists.
1528 ASSERT_TRUE(sys::fs::exists(Twine(TempPath)));
1529
1530 bool TempFileIsLocal;
1531 ASSERT_NO_ERROR(fs::is_local(FD, TempFileIsLocal));
1532 EXPECT_EQ(TempFileIsLocal, fs::is_local(FD));
1533 ::close(FD);
1534
1535 // Expect that the file and its parent directory are equally local or equally
1536 // remote.
1537 EXPECT_EQ(TestDirectoryIsLocal, TempFileIsLocal);
1538 }
1539
1540 TEST_F(FileSystemTest, getUmask) {
1541 #ifdef _WIN32
1542 EXPECT_EQ(fs::getUmask(), 0U) << "Should always be 0 on Windows.";
1543 #else
1544 unsigned OldMask = ::umask(0022);
1545 unsigned CurrentMask = fs::getUmask();
1546 EXPECT_EQ(CurrentMask, 0022U)
1547 << "getUmask() didn't return previously set umask()";
1548 EXPECT_EQ(::umask(OldMask), 0022U) << "getUmask() may have changed umask()";
1549 #endif
1550 }
1551
1552 TEST_F(FileSystemTest, RespectUmask) {
1553 #ifndef _WIN32
1554 unsigned OldMask = ::umask(0022);
1555
1556 int FD;
1557 SmallString<128> TempPath;
1558 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath));
1559
1560 fs::perms AllRWE = static_cast<fs::perms>(0777);
1561
1562 ASSERT_NO_ERROR(fs::setPermissions(TempPath, AllRWE));
1563
1564 ErrorOr<fs::perms> Perms = fs::getPermissions(TempPath);
1565 ASSERT_TRUE(!!Perms);
1566 EXPECT_EQ(Perms.get(), AllRWE) << "Should have ignored umask by default";
1567
1568 ASSERT_NO_ERROR(fs::setPermissions(TempPath, AllRWE));
1569
1570 Perms = fs::getPermissions(TempPath);
1571 ASSERT_TRUE(!!Perms);
1572 EXPECT_EQ(Perms.get(), AllRWE) << "Should have ignored umask";
1573
1574 ASSERT_NO_ERROR(
1575 fs::setPermissions(FD, static_cast<fs::perms>(AllRWE & ~fs::getUmask())));
1576 Perms = fs::getPermissions(TempPath);
1577 ASSERT_TRUE(!!Perms);
1578 EXPECT_EQ(Perms.get(), static_cast<fs::perms>(0755))
1579 << "Did not respect umask";
1580
1581 (void)::umask(0057);
1582
1583 ASSERT_NO_ERROR(
1584 fs::setPermissions(FD, static_cast<fs::perms>(AllRWE & ~fs::getUmask())));
1585 Perms = fs::getPermissions(TempPath);
1586 ASSERT_TRUE(!!Perms);
1587 EXPECT_EQ(Perms.get(), static_cast<fs::perms>(0720))
1588 << "Did not respect umask";
1589
1590 (void)::umask(OldMask);
1591 (void)::close(FD);
1592 #endif
1231 } 1593 }
1232 1594
1233 TEST_F(FileSystemTest, set_current_path) { 1595 TEST_F(FileSystemTest, set_current_path) {
1234 SmallString<128> path; 1596 SmallString<128> path;
1235 1597
1271 EXPECT_TRUE(CheckPermissions(fs::all_all)); 1633 EXPECT_TRUE(CheckPermissions(fs::all_all));
1272 1634
1273 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read | fs::all_exe), NoError); 1635 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read | fs::all_exe), NoError);
1274 EXPECT_TRUE(CheckPermissions(fs::all_read | fs::all_exe)); 1636 EXPECT_TRUE(CheckPermissions(fs::all_read | fs::all_exe));
1275 1637
1276 #if defined(LLVM_ON_WIN32) 1638 #if defined(_WIN32)
1277 fs::perms ReadOnly = fs::all_read | fs::all_exe; 1639 fs::perms ReadOnly = fs::all_read | fs::all_exe;
1278 EXPECT_EQ(fs::setPermissions(TempPath, fs::no_perms), NoError); 1640 EXPECT_EQ(fs::setPermissions(TempPath, fs::no_perms), NoError);
1279 EXPECT_TRUE(CheckPermissions(ReadOnly)); 1641 EXPECT_TRUE(CheckPermissions(ReadOnly));
1280 1642
1281 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_read), NoError); 1643 EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_read), NoError);
1400 1762
1401 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_gid_on_exe), NoError); 1763 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_gid_on_exe), NoError);
1402 EXPECT_TRUE(CheckPermissions(fs::set_gid_on_exe)); 1764 EXPECT_TRUE(CheckPermissions(fs::set_gid_on_exe));
1403 1765
1404 // Modern BSDs require root to set the sticky bit on files. 1766 // Modern BSDs require root to set the sticky bit on files.
1405 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) 1767 // AIX and Solaris without root will mask off (i.e., lose) the sticky bit
1768 // on files.
1769 #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && \
1770 !defined(_AIX) && !(defined(__sun__) && defined(__svr4__))
1406 EXPECT_EQ(fs::setPermissions(TempPath, fs::sticky_bit), NoError); 1771 EXPECT_EQ(fs::setPermissions(TempPath, fs::sticky_bit), NoError);
1407 EXPECT_TRUE(CheckPermissions(fs::sticky_bit)); 1772 EXPECT_TRUE(CheckPermissions(fs::sticky_bit));
1408 1773
1409 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe | 1774 EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe |
1410 fs::set_gid_on_exe | 1775 fs::set_gid_on_exe |
1420 EXPECT_TRUE(CheckPermissions(fs::all_read | fs::set_uid_on_exe | 1785 EXPECT_TRUE(CheckPermissions(fs::all_read | fs::set_uid_on_exe |
1421 fs::set_gid_on_exe | fs::sticky_bit)); 1786 fs::set_gid_on_exe | fs::sticky_bit));
1422 1787
1423 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms), NoError); 1788 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms), NoError);
1424 EXPECT_TRUE(CheckPermissions(fs::all_perms)); 1789 EXPECT_TRUE(CheckPermissions(fs::all_perms));
1425 #endif // !FreeBSD && !NetBSD && !OpenBSD 1790 #endif // !FreeBSD && !NetBSD && !OpenBSD && !AIX
1426 1791
1427 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms & ~fs::sticky_bit), 1792 EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms & ~fs::sticky_bit),
1428 NoError); 1793 NoError);
1429 EXPECT_TRUE(CheckPermissions(fs::all_perms & ~fs::sticky_bit)); 1794 EXPECT_TRUE(CheckPermissions(fs::all_perms & ~fs::sticky_bit));
1430 #endif 1795 #endif