1 //===- llvm/unittest/Support/Path.cpp - Path tests ------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Support/Path.h"
11 #include "llvm/Support/Errc.h"
12 #include "llvm/Support/ErrorHandling.h"
13 #include "llvm/Support/FileSystem.h"
14 #include "llvm/Support/MemoryBuffer.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include "gtest/gtest.h"
24 using namespace llvm::sys
;
26 #define ASSERT_NO_ERROR(x) \
27 if (std::error_code ASSERT_NO_ERROR_ec = x) { \
28 SmallString<128> MessageStorage; \
29 raw_svector_ostream Message(MessageStorage); \
30 Message << #x ": did not return errc::success.\n" \
31 << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
32 << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
33 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
39 TEST(is_separator
, Works
) {
40 EXPECT_TRUE(path::is_separator('/'));
41 EXPECT_FALSE(path::is_separator('\0'));
42 EXPECT_FALSE(path::is_separator('-'));
43 EXPECT_FALSE(path::is_separator(' '));
46 EXPECT_TRUE(path::is_separator('\\'));
48 EXPECT_FALSE(path::is_separator('\\'));
53 SmallVector
<StringRef
, 40> paths
;
56 paths
.push_back("..");
57 paths
.push_back("foo");
59 paths
.push_back("/foo");
60 paths
.push_back("foo/");
61 paths
.push_back("/foo/");
62 paths
.push_back("foo/bar");
63 paths
.push_back("/foo/bar");
64 paths
.push_back("//net");
65 paths
.push_back("//net/foo");
66 paths
.push_back("///foo///");
67 paths
.push_back("///foo///bar");
68 paths
.push_back("/.");
69 paths
.push_back("./");
70 paths
.push_back("/..");
71 paths
.push_back("../");
72 paths
.push_back("foo/.");
73 paths
.push_back("foo/..");
74 paths
.push_back("foo/./");
75 paths
.push_back("foo/./bar");
76 paths
.push_back("foo/..");
77 paths
.push_back("foo/../");
78 paths
.push_back("foo/../bar");
79 paths
.push_back("c:");
80 paths
.push_back("c:/");
81 paths
.push_back("c:foo");
82 paths
.push_back("c:/foo");
83 paths
.push_back("c:foo/");
84 paths
.push_back("c:/foo/");
85 paths
.push_back("c:/foo/bar");
86 paths
.push_back("prn:");
87 paths
.push_back("c:\\");
88 paths
.push_back("c:foo");
89 paths
.push_back("c:\\foo");
90 paths
.push_back("c:foo\\");
91 paths
.push_back("c:\\foo\\");
92 paths
.push_back("c:\\foo/");
93 paths
.push_back("c:/foo\\bar");
95 SmallVector
<StringRef
, 5> ComponentStack
;
96 for (SmallVector
<StringRef
, 40>::const_iterator i
= paths
.begin(),
100 for (sys::path::const_iterator ci
= sys::path::begin(*i
),
101 ce
= sys::path::end(*i
);
104 ASSERT_FALSE(ci
->empty());
105 ComponentStack
.push_back(*ci
);
108 for (sys::path::reverse_iterator ci
= sys::path::rbegin(*i
),
109 ce
= sys::path::rend(*i
);
112 ASSERT_TRUE(*ci
== ComponentStack
.back());
113 ComponentStack
.pop_back();
115 ASSERT_TRUE(ComponentStack
.empty());
117 path::has_root_path(*i
);
119 path::has_root_name(*i
);
121 path::has_root_directory(*i
);
122 path::root_directory(*i
);
123 path::has_parent_path(*i
);
124 path::parent_path(*i
);
125 path::has_filename(*i
);
129 path::has_extension(*i
);
131 path::is_absolute(*i
);
132 path::is_relative(*i
);
134 SmallString
<128> temp_store
;
136 ASSERT_NO_ERROR(fs::make_absolute(temp_store
));
138 path::remove_filename(temp_store
);
141 path::replace_extension(temp_store
, "ext");
142 StringRef
filename(temp_store
.begin(), temp_store
.size()), stem
, ext
;
143 stem
= path::stem(filename
);
144 ext
= path::extension(filename
);
145 EXPECT_EQ(*sys::path::rbegin(filename
), (stem
+ ext
).str());
147 path::native(*i
, temp_store
);
151 TEST(Support
, RelativePathIterator
) {
152 SmallString
<64> Path(StringRef("c/d/e/foo.txt"));
153 typedef SmallVector
<StringRef
, 4> PathComponents
;
154 PathComponents ExpectedPathComponents
;
155 PathComponents ActualPathComponents
;
157 StringRef(Path
).split(ExpectedPathComponents
, "/");
159 for (path::const_iterator I
= path::begin(Path
), E
= path::end(Path
); I
!= E
;
161 ActualPathComponents
.push_back(*I
);
164 ASSERT_EQ(ExpectedPathComponents
.size(), ActualPathComponents
.size());
166 for (size_t i
= 0; i
<ExpectedPathComponents
.size(); ++i
) {
167 EXPECT_EQ(ExpectedPathComponents
[i
].str(), ActualPathComponents
[i
].str());
171 TEST(Support
, AbsolutePathIterator
) {
172 SmallString
<64> Path(StringRef("/c/d/e/foo.txt"));
173 typedef SmallVector
<StringRef
, 4> PathComponents
;
174 PathComponents ExpectedPathComponents
;
175 PathComponents ActualPathComponents
;
177 StringRef(Path
).split(ExpectedPathComponents
, "/");
179 // The root path will also be a component when iterating
180 ExpectedPathComponents
[0] = "/";
182 for (path::const_iterator I
= path::begin(Path
), E
= path::end(Path
); I
!= E
;
184 ActualPathComponents
.push_back(*I
);
187 ASSERT_EQ(ExpectedPathComponents
.size(), ActualPathComponents
.size());
189 for (size_t i
= 0; i
<ExpectedPathComponents
.size(); ++i
) {
190 EXPECT_EQ(ExpectedPathComponents
[i
].str(), ActualPathComponents
[i
].str());
195 TEST(Support
, AbsolutePathIteratorWin32
) {
196 SmallString
<64> Path(StringRef("c:\\c\\e\\foo.txt"));
197 typedef SmallVector
<StringRef
, 4> PathComponents
;
198 PathComponents ExpectedPathComponents
;
199 PathComponents ActualPathComponents
;
201 StringRef(Path
).split(ExpectedPathComponents
, "\\");
203 // The root path (which comes after the drive name) will also be a component
205 ExpectedPathComponents
.insert(ExpectedPathComponents
.begin()+1, "\\");
207 for (path::const_iterator I
= path::begin(Path
), E
= path::end(Path
); I
!= E
;
209 ActualPathComponents
.push_back(*I
);
212 ASSERT_EQ(ExpectedPathComponents
.size(), ActualPathComponents
.size());
214 for (size_t i
= 0; i
<ExpectedPathComponents
.size(); ++i
) {
215 EXPECT_EQ(ExpectedPathComponents
[i
].str(), ActualPathComponents
[i
].str());
218 #endif // LLVM_ON_WIN32
220 TEST(Support
, AbsolutePathIteratorEnd
) {
221 // Trailing slashes are converted to '.' unless they are part of the root path.
222 SmallVector
<StringRef
, 4> Paths
;
223 Paths
.push_back("/foo/");
224 Paths
.push_back("/foo//");
225 Paths
.push_back("//net//");
227 Paths
.push_back("c:\\\\");
230 for (StringRef Path
: Paths
) {
231 StringRef LastComponent
= *path::rbegin(Path
);
232 EXPECT_EQ(".", LastComponent
);
235 SmallVector
<StringRef
, 3> RootPaths
;
236 RootPaths
.push_back("/");
237 RootPaths
.push_back("//net/");
239 RootPaths
.push_back("c:\\");
242 for (StringRef Path
: RootPaths
) {
243 StringRef LastComponent
= *path::rbegin(Path
);
244 EXPECT_EQ(1u, LastComponent
.size());
245 EXPECT_TRUE(path::is_separator(LastComponent
[0]));
249 TEST(Support
, HomeDirectory
) {
251 // This test only makes sense on Unix if $HOME is set.
252 if (::getenv("HOME")) {
254 SmallString
<128> HomeDir
;
255 EXPECT_TRUE(path::home_directory(HomeDir
));
256 EXPECT_FALSE(HomeDir
.empty());
262 class FileSystemTest
: public testing::Test
{
264 /// Unique temporary directory in which all created filesystem entities must
265 /// be placed. It is removed at the end of each test (must be empty).
266 SmallString
<128> TestDirectory
;
268 virtual void SetUp() {
270 fs::createUniqueDirectory("file-system-test", TestDirectory
));
271 // We don't care about this specific file.
272 errs() << "Test Directory: " << TestDirectory
<< '\n';
276 virtual void TearDown() {
277 ASSERT_NO_ERROR(fs::remove(TestDirectory
.str()));
281 TEST_F(FileSystemTest
, Unique
) {
282 // Create a temp file.
284 SmallString
<64> TempPath
;
286 fs::createTemporaryFile("prefix", "temp", FileDescriptor
, TempPath
));
288 // The same file should return an identical unique id.
290 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath
), F1
));
291 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath
), F2
));
294 // Different files should return different unique ids.
296 SmallString
<64> TempPath2
;
298 fs::createTemporaryFile("prefix", "temp", FileDescriptor2
, TempPath2
));
301 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2
), D
));
303 ::close(FileDescriptor2
);
305 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2
)));
307 // Two paths representing the same file on disk should still provide the
308 // same unique id. We can test this by making a hard link.
309 ASSERT_NO_ERROR(fs::create_link(Twine(TempPath
), Twine(TempPath2
)));
311 ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2
), D2
));
314 ::close(FileDescriptor
);
316 SmallString
<128> Dir1
;
318 fs::createUniqueDirectory("dir1", Dir1
));
319 ASSERT_NO_ERROR(fs::getUniqueID(Dir1
.c_str(), F1
));
320 ASSERT_NO_ERROR(fs::getUniqueID(Dir1
.c_str(), F2
));
323 SmallString
<128> Dir2
;
325 fs::createUniqueDirectory("dir2", Dir2
));
326 ASSERT_NO_ERROR(fs::getUniqueID(Dir2
.c_str(), F2
));
330 TEST_F(FileSystemTest
, TempFiles
) {
331 // Create a temp file.
333 SmallString
<64> TempPath
;
335 fs::createTemporaryFile("prefix", "temp", FileDescriptor
, TempPath
));
337 // Make sure it exists.
338 ASSERT_TRUE(sys::fs::exists(Twine(TempPath
)));
340 // Create another temp tile.
342 SmallString
<64> TempPath2
;
343 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD2
, TempPath2
));
344 ASSERT_TRUE(TempPath2
.endswith(".temp"));
345 ASSERT_NE(TempPath
.str(), TempPath2
.str());
347 fs::file_status A
, B
;
348 ASSERT_NO_ERROR(fs::status(Twine(TempPath
), A
));
349 ASSERT_NO_ERROR(fs::status(Twine(TempPath2
), B
));
350 EXPECT_FALSE(fs::equivalent(A
, B
));
355 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2
)));
356 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2
)));
357 ASSERT_EQ(fs::remove(Twine(TempPath2
), false),
358 errc::no_such_file_or_directory
);
360 std::error_code EC
= fs::status(TempPath2
.c_str(), B
);
361 EXPECT_EQ(EC
, errc::no_such_file_or_directory
);
362 EXPECT_EQ(B
.type(), fs::file_type::file_not_found
);
364 // Make sure Temp2 doesn't exist.
365 ASSERT_EQ(fs::access(Twine(TempPath2
), sys::fs::AccessMode::Exist
),
366 errc::no_such_file_or_directory
);
368 SmallString
<64> TempPath3
;
369 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3
));
370 ASSERT_FALSE(TempPath3
.endswith("."));
372 // Create a hard link to Temp1.
373 ASSERT_NO_ERROR(fs::create_link(Twine(TempPath
), Twine(TempPath2
)));
375 ASSERT_NO_ERROR(fs::equivalent(Twine(TempPath
), Twine(TempPath2
), equal
));
377 ASSERT_NO_ERROR(fs::status(Twine(TempPath
), A
));
378 ASSERT_NO_ERROR(fs::status(Twine(TempPath2
), B
));
379 EXPECT_TRUE(fs::equivalent(A
, B
));
382 ::close(FileDescriptor
);
383 ASSERT_NO_ERROR(fs::remove(Twine(TempPath
)));
385 // Remove the hard link.
386 ASSERT_NO_ERROR(fs::remove(Twine(TempPath2
)));
388 // Make sure Temp1 doesn't exist.
389 ASSERT_EQ(fs::access(Twine(TempPath
), sys::fs::AccessMode::Exist
),
390 errc::no_such_file_or_directory
);
393 // Path name > 260 chars should get an error.
394 const char *Path270
=
395 "abcdefghijklmnopqrstuvwxyz9abcdefghijklmnopqrstuvwxyz8"
396 "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6"
397 "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4"
398 "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2"
399 "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0";
400 EXPECT_EQ(fs::createUniqueFile(Path270
, FileDescriptor
, TempPath
),
401 errc::invalid_argument
);
402 // Relative path < 247 chars, no problem.
403 const char *Path216
=
404 "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6"
405 "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4"
406 "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2"
407 "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0";
408 ASSERT_NO_ERROR(fs::createTemporaryFile(Path216
, "", TempPath
));
409 ASSERT_NO_ERROR(fs::remove(Twine(TempPath
)));
413 TEST_F(FileSystemTest
, CreateDir
) {
414 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory
) + "foo"));
415 ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory
) + "foo"));
416 ASSERT_EQ(fs::create_directory(Twine(TestDirectory
) + "foo", false),
418 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "foo"));
421 // Prove that create_directories() can handle a pathname > 248 characters,
422 // which is the documented limit for CreateDirectory().
423 // (248 is MAX_PATH subtracting room for an 8.3 filename.)
424 // Generate a directory path guaranteed to fall into that range.
425 size_t TmpLen
= TestDirectory
.size();
426 const char *OneDir
= "\\123456789";
427 size_t OneDirLen
= strlen(OneDir
);
428 ASSERT_LT(OneDirLen
, 12U);
429 size_t NLevels
= ((248 - TmpLen
) / OneDirLen
) + 1;
430 SmallString
<260> LongDir(TestDirectory
);
431 for (size_t I
= 0; I
< NLevels
; ++I
)
432 LongDir
.append(OneDir
);
433 ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir
)));
434 ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir
)));
435 ASSERT_EQ(fs::create_directories(Twine(LongDir
), false),
437 // Tidy up, "recursively" removing the directories.
438 StringRef
ThisDir(LongDir
);
439 for (size_t J
= 0; J
< NLevels
; ++J
) {
440 ASSERT_NO_ERROR(fs::remove(ThisDir
));
441 ThisDir
= path::parent_path(ThisDir
);
444 // Similarly for a relative pathname. Need to set the current directory to
445 // TestDirectory so that the one we create ends up in the right place.
446 char PreviousDir
[260];
447 size_t PreviousDirLen
= ::GetCurrentDirectoryA(260, PreviousDir
);
448 ASSERT_GT(PreviousDirLen
, 0U);
449 ASSERT_LT(PreviousDirLen
, 260U);
450 ASSERT_NE(::SetCurrentDirectoryA(TestDirectory
.c_str()), 0);
452 // Generate a relative directory name with absolute length > 248.
453 size_t LongDirLen
= 249 - TestDirectory
.size();
454 LongDir
.assign(LongDirLen
, 'a');
455 ASSERT_NO_ERROR(fs::create_directory(Twine(LongDir
)));
456 // While we're here, prove that .. and . handling works in these long paths.
457 const char *DotDotDirs
= "\\..\\.\\b";
458 LongDir
.append(DotDotDirs
);
459 ASSERT_NO_ERROR(fs::create_directory("b"));
460 ASSERT_EQ(fs::create_directory(Twine(LongDir
), false), errc::file_exists
);
462 ASSERT_NO_ERROR(fs::remove("b"));
463 ASSERT_NO_ERROR(fs::remove(
464 Twine(LongDir
.substr(0, LongDir
.size() - strlen(DotDotDirs
)))));
465 ASSERT_NE(::SetCurrentDirectoryA(PreviousDir
), 0);
469 TEST_F(FileSystemTest
, DirectoryIteration
) {
471 for (fs::directory_iterator
i(".", ec
), e
; i
!= e
; i
.increment(ec
))
474 // Create a known hierarchy to recurse over.
476 fs::create_directories(Twine(TestDirectory
) + "/recursive/a0/aa1"));
478 fs::create_directories(Twine(TestDirectory
) + "/recursive/a0/ab1"));
479 ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory
) +
480 "/recursive/dontlookhere/da1"));
482 fs::create_directories(Twine(TestDirectory
) + "/recursive/z0/za1"));
484 fs::create_directories(Twine(TestDirectory
) + "/recursive/pop/p1"));
485 typedef std::vector
<std::string
> v_t
;
487 for (fs::recursive_directory_iterator
i(Twine(TestDirectory
)
488 + "/recursive", ec
), e
; i
!= e
; i
.increment(ec
)){
490 if (path::filename(i
->path()) == "p1") {
492 // FIXME: recursive_directory_iterator should be more robust.
495 if (path::filename(i
->path()) == "dontlookhere")
497 visited
.push_back(path::filename(i
->path()));
499 v_t::const_iterator a0
= std::find(visited
.begin(), visited
.end(), "a0");
500 v_t::const_iterator aa1
= std::find(visited
.begin(), visited
.end(), "aa1");
501 v_t::const_iterator ab1
= std::find(visited
.begin(), visited
.end(), "ab1");
502 v_t::const_iterator dontlookhere
= std::find(visited
.begin(), visited
.end(),
504 v_t::const_iterator da1
= std::find(visited
.begin(), visited
.end(), "da1");
505 v_t::const_iterator z0
= std::find(visited
.begin(), visited
.end(), "z0");
506 v_t::const_iterator za1
= std::find(visited
.begin(), visited
.end(), "za1");
507 v_t::const_iterator pop
= std::find(visited
.begin(), visited
.end(), "pop");
508 v_t::const_iterator p1
= std::find(visited
.begin(), visited
.end(), "p1");
510 // Make sure that each path was visited correctly.
511 ASSERT_NE(a0
, visited
.end());
512 ASSERT_NE(aa1
, visited
.end());
513 ASSERT_NE(ab1
, visited
.end());
514 ASSERT_NE(dontlookhere
, visited
.end());
515 ASSERT_EQ(da1
, visited
.end()); // Not visited.
516 ASSERT_NE(z0
, visited
.end());
517 ASSERT_NE(za1
, visited
.end());
518 ASSERT_NE(pop
, visited
.end());
519 ASSERT_EQ(p1
, visited
.end()); // Not visited.
521 // Make sure that parents were visited before children. No other ordering
522 // guarantees can be made across siblings.
527 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive/a0/aa1"));
528 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive/a0/ab1"));
529 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive/a0"));
531 fs::remove(Twine(TestDirectory
) + "/recursive/dontlookhere/da1"));
532 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive/dontlookhere"));
533 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive/pop/p1"));
534 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive/pop"));
535 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive/z0/za1"));
536 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive/z0"));
537 ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory
) + "/recursive"));
540 const char archive
[] = "!<arch>\x0A";
541 const char bitcode
[] = "\xde\xc0\x17\x0b";
542 const char coff_object
[] = "\x00\x00......";
543 const char coff_bigobj
[] = "\x00\x00\xff\xff\x00\x02......"
544 "\xc7\xa1\xba\xd1\xee\xba\xa9\x4b\xaf\x20\xfa\xf6\x6a\xa4\xdc\xb8";
545 const char coff_import_library
[] = "\x00\x00\xff\xff....";
546 const char elf_relocatable
[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0,
547 0, 0, 0, 0, 0, 0, 0, 0, 1 };
548 const char macho_universal_binary
[] = "\xca\xfe\xba\xbe...\0x00";
549 const char macho_object
[] = "\xfe\xed\xfa\xce..........\x00\x01";
550 const char macho_executable
[] = "\xfe\xed\xfa\xce..........\x00\x02";
551 const char macho_fixed_virtual_memory_shared_lib
[] =
552 "\xfe\xed\xfa\xce..........\x00\x03";
553 const char macho_core
[] = "\xfe\xed\xfa\xce..........\x00\x04";
554 const char macho_preload_executable
[] = "\xfe\xed\xfa\xce..........\x00\x05";
555 const char macho_dynamically_linked_shared_lib
[] =
556 "\xfe\xed\xfa\xce..........\x00\x06";
557 const char macho_dynamic_linker
[] = "\xfe\xed\xfa\xce..........\x00\x07";
558 const char macho_bundle
[] = "\xfe\xed\xfa\xce..........\x00\x08";
559 const char macho_dsym_companion
[] = "\xfe\xed\xfa\xce..........\x00\x0a";
560 const char windows_resource
[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff";
561 const char macho_dynamically_linked_shared_lib_stub
[] =
562 "\xfe\xed\xfa\xce..........\x00\x09";
564 TEST_F(FileSystemTest
, Magic
) {
566 const char *filename
;
567 const char *magic_str
;
568 size_t magic_str_len
;
569 fs::file_magic magic
;
571 #define DEFINE(magic) \
572 { #magic, magic, sizeof(magic), fs::file_magic::magic }
576 { "coff_bigobj", coff_bigobj
, sizeof(coff_bigobj
), fs::file_magic::coff_object
},
577 DEFINE(coff_import_library
),
578 DEFINE(elf_relocatable
),
579 DEFINE(macho_universal_binary
),
580 DEFINE(macho_object
),
581 DEFINE(macho_executable
),
582 DEFINE(macho_fixed_virtual_memory_shared_lib
),
584 DEFINE(macho_preload_executable
),
585 DEFINE(macho_dynamically_linked_shared_lib
),
586 DEFINE(macho_dynamic_linker
),
587 DEFINE(macho_bundle
),
588 DEFINE(macho_dynamically_linked_shared_lib_stub
),
589 DEFINE(macho_dsym_companion
),
590 DEFINE(windows_resource
)
594 // Create some files filled with magic.
595 for (type
*i
= types
, *e
= types
+ (sizeof(types
) / sizeof(type
)); i
!= e
;
597 SmallString
<128> file_pathname(TestDirectory
);
598 path::append(file_pathname
, i
->filename
);
600 raw_fd_ostream
file(file_pathname
, EC
, sys::fs::F_None
);
601 ASSERT_FALSE(file
.has_error());
602 StringRef
magic(i
->magic_str
, i
->magic_str_len
);
605 EXPECT_EQ(i
->magic
, fs::identify_magic(magic
));
606 ASSERT_NO_ERROR(fs::remove(Twine(file_pathname
)));
611 TEST_F(FileSystemTest
, CarriageReturn
) {
612 SmallString
<128> FilePathname(TestDirectory
);
614 path::append(FilePathname
, "test");
617 raw_fd_ostream
File(FilePathname
, EC
, sys::fs::F_Text
);
622 auto Buf
= MemoryBuffer::getFile(FilePathname
.str());
623 EXPECT_TRUE((bool)Buf
);
624 EXPECT_EQ(Buf
.get()->getBuffer(), "\r\n");
628 raw_fd_ostream
File(FilePathname
, EC
, sys::fs::F_None
);
633 auto Buf
= MemoryBuffer::getFile(FilePathname
.str());
634 EXPECT_TRUE((bool)Buf
);
635 EXPECT_EQ(Buf
.get()->getBuffer(), "\n");
637 ASSERT_NO_ERROR(fs::remove(Twine(FilePathname
)));
641 TEST_F(FileSystemTest
, Resize
) {
643 SmallString
<64> TempPath
;
644 ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD
, TempPath
));
645 ASSERT_NO_ERROR(fs::resize_file(FD
, 123));
646 fs::file_status Status
;
647 ASSERT_NO_ERROR(fs::status(FD
, Status
));
648 ASSERT_EQ(Status
.getSize(), 123U);
651 TEST_F(FileSystemTest
, FileMapping
) {
652 // Create a temp file.
654 SmallString
<64> TempPath
;
656 fs::createTemporaryFile("prefix", "temp", FileDescriptor
, TempPath
));
657 unsigned Size
= 4096;
658 ASSERT_NO_ERROR(fs::resize_file(FileDescriptor
, Size
));
660 // Map in temp file and add some content
662 StringRef
Val("hello there");
664 fs::mapped_file_region
mfr(FileDescriptor
,
665 fs::mapped_file_region::readwrite
, Size
, 0, EC
);
667 std::copy(Val
.begin(), Val
.end(), mfr
.data());
668 // Explicitly add a 0.
669 mfr
.data()[Val
.size()] = 0;
673 // Map it back in read-only
675 EC
= fs::openFileForRead(Twine(TempPath
), FD
);
677 fs::mapped_file_region
mfr(FD
, fs::mapped_file_region::readonly
, Size
, 0, EC
);
681 EXPECT_EQ(StringRef(mfr
.const_data()), Val
);
684 fs::mapped_file_region
m(FD
, fs::mapped_file_region::readonly
, Size
, 0, EC
);
686 ASSERT_EQ(close(FD
), 0);
689 TEST(Support
, NormalizePath
) {
690 #if defined(LLVM_ON_WIN32)
691 #define EXPECT_PATH_IS(path__, windows__, not_windows__) \
692 EXPECT_EQ(path__, windows__);
694 #define EXPECT_PATH_IS(path__, windows__, not_windows__) \
695 EXPECT_EQ(path__, not_windows__);
698 SmallString
<64> Path1("a");
699 SmallString
<64> Path2("a/b");
700 SmallString
<64> Path3("a\\b");
701 SmallString
<64> Path4("a\\\\b");
702 SmallString
<64> Path5("\\a");
703 SmallString
<64> Path6("a\\");
706 EXPECT_PATH_IS(Path1
, "a", "a");
709 EXPECT_PATH_IS(Path2
, "a\\b", "a/b");
712 EXPECT_PATH_IS(Path3
, "a\\b", "a/b");
715 EXPECT_PATH_IS(Path4
, "a\\\\b", "a\\\\b");
718 EXPECT_PATH_IS(Path5
, "\\a", "/a");
721 EXPECT_PATH_IS(Path6
, "a\\", "a/");
723 #undef EXPECT_PATH_IS
725 } // anonymous namespace