1 //===- llvm/unittest/Support/Path.cpp - Path 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/FileSystem.h" 11 #include "llvm/Support/PathV2.h" 12 #include "llvm/Support/ErrorHandling.h" 13 14 #include "gtest/gtest.h" 15 16 using namespace llvm; 17 using namespace llvm::sys; 18 19 namespace { 20 21 TEST(Support, Path) { 22 SmallVector<StringRef, 40> paths; 23 paths.push_back(""); 24 paths.push_back("."); 25 paths.push_back(".."); 26 paths.push_back("foo"); 27 paths.push_back("/"); 28 paths.push_back("/foo"); 29 paths.push_back("foo/"); 30 paths.push_back("/foo/"); 31 paths.push_back("foo/bar"); 32 paths.push_back("/foo/bar"); 33 paths.push_back("//net"); 34 paths.push_back("//net/foo"); 35 paths.push_back("///foo///"); 36 paths.push_back("///foo///bar"); 37 paths.push_back("/."); 38 paths.push_back("./"); 39 paths.push_back("/.."); 40 paths.push_back("../"); 41 paths.push_back("foo/."); 42 paths.push_back("foo/.."); 43 paths.push_back("foo/./"); 44 paths.push_back("foo/./bar"); 45 paths.push_back("foo/.."); 46 paths.push_back("foo/../"); 47 paths.push_back("foo/../bar"); 48 paths.push_back("c:"); 49 paths.push_back("c:/"); 50 paths.push_back("c:foo"); 51 paths.push_back("c:/foo"); 52 paths.push_back("c:foo/"); 53 paths.push_back("c:/foo/"); 54 paths.push_back("c:/foo/bar"); 55 paths.push_back("prn:"); 56 paths.push_back("c:\\"); 57 paths.push_back("c:foo"); 58 paths.push_back("c:\\foo"); 59 paths.push_back("c:foo\\"); 60 paths.push_back("c:\\foo\\"); 61 paths.push_back("c:\\foo/"); 62 paths.push_back("c:/foo\\bar"); 63 64 for (SmallVector<StringRef, 40>::const_iterator i = paths.begin(), 65 e = paths.end(); 66 i != e; 67 ++i) { 68 for (sys::path::const_iterator ci = sys::path::begin(*i), 69 ce = sys::path::end(*i); 70 ci != ce; 71 ++ci) { 72 ASSERT_FALSE(ci->empty()); 73 } 74 75 #if 0 // Valgrind is whining about this. 76 outs() << " Reverse Iteration: ["; 77 for (sys::path::reverse_iterator ci = sys::path::rbegin(*i), 78 ce = sys::path::rend(*i); 79 ci != ce; 80 ++ci) { 81 outs() << *ci << ','; 82 } 83 outs() << "]\n"; 84 #endif 85 86 bool bres; 87 StringRef sfres; 88 path::has_root_path(*i, bres); 89 path::root_path(*i, sfres); 90 path::has_root_name(*i, bres); 91 path::root_name(*i, sfres); 92 path::has_root_directory(*i, bres); 93 path::root_directory(*i, sfres); 94 path::has_parent_path(*i, bres); 95 path::parent_path(*i, sfres); 96 path::has_filename(*i, bres); 97 path::filename(*i, sfres); 98 path::has_stem(*i, bres); 99 path::stem(*i, sfres); 100 path::has_extension(*i, bres); 101 path::extension(*i, sfres); 102 path::is_absolute(*i, bres); 103 path::is_relative(*i, bres); 104 105 SmallString<16> temp_store; 106 temp_store = *i; 107 ASSERT_FALSE(fs::make_absolute(temp_store)); 108 temp_store = *i; 109 path::remove_filename(temp_store); 110 111 temp_store = *i; 112 path::replace_extension(temp_store, "ext"); 113 StringRef filename(temp_store.begin(), temp_store.size()), stem, ext; 114 path::stem(filename, stem); 115 path::extension(filename, ext); 116 EXPECT_EQ(*(--sys::path::end(filename)), (stem + ext).str()); 117 118 path::native(*i, temp_store); 119 120 outs().flush(); 121 } 122 123 // Create a temp file. 124 int FileDescriptor; 125 SmallString<64> TempPath; 126 ASSERT_FALSE(fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath)); 127 128 // Make sure it exists. 129 bool TempFileExists; 130 ASSERT_FALSE(sys::fs::exists(Twine(TempPath), TempFileExists)); 131 EXPECT_TRUE(TempFileExists); 132 133 // Create another temp tile. 134 int FD2; 135 SmallString<64> TempPath2; 136 ASSERT_FALSE(fs::unique_file("%%-%%-%%-%%.temp", FD2, TempPath2)); 137 ASSERT_NE(TempPath.str(), TempPath2.str()); 138 139 // Try to copy the first to the second. 140 EXPECT_EQ(fs::copy_file(Twine(TempPath), Twine(TempPath2)), errc::file_exists); 141 142 ::close(FD2); 143 // Try again with the proper options. 144 ASSERT_FALSE(fs::copy_file(Twine(TempPath), Twine(TempPath2), 145 fs::copy_option::overwrite_if_exists)); 146 // Remove Temp2. 147 ASSERT_FALSE(fs::remove(Twine(TempPath2), TempFileExists)); 148 EXPECT_TRUE(TempFileExists); 149 150 // Make sure Temp2 doesn't exist. 151 ASSERT_FALSE(fs::exists(Twine(TempPath2), TempFileExists)); 152 EXPECT_FALSE(TempFileExists); 153 154 // Create a hard link to Temp1. 155 ASSERT_FALSE(fs::create_hard_link(Twine(TempPath), Twine(TempPath2))); 156 bool equal; 157 ASSERT_FALSE(fs::equivalent(Twine(TempPath), Twine(TempPath2), equal)); 158 EXPECT_TRUE(equal); 159 160 // Remove Temp1. 161 ::close(FileDescriptor); 162 ASSERT_FALSE(fs::remove(Twine(TempPath), TempFileExists)); 163 EXPECT_TRUE(TempFileExists); 164 165 // Remove the hard link. 166 ASSERT_FALSE(fs::remove(Twine(TempPath2), TempFileExists)); 167 EXPECT_TRUE(TempFileExists); 168 169 // Make sure Temp1 doesn't exist. 170 ASSERT_FALSE(fs::exists(Twine(TempPath), TempFileExists)); 171 EXPECT_FALSE(TempFileExists); 172 173 // I've yet to do directory iteration on Unix. 174 #ifdef LLVM_ON_WIN32 175 error_code ec; 176 for (fs::directory_iterator i(".", ec), e; i != e; i.increment(ec)) { 177 if (ec) { 178 errs() << ec.message() << '\n'; 179 errs().flush(); 180 report_fatal_error("Directory iteration failed!"); 181 } 182 } 183 #endif 184 } 185 186 } // anonymous namespace 187