1 //===-- FileSpecTest.cpp ----------------------------------------*- C++ -*-===// 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 "gtest/gtest.h" 11 12 #include "lldb/Utility/FileSpec.h" 13 14 using namespace lldb_private; 15 16 TEST(FileSpecTest, FileAndDirectoryComponents) { 17 FileSpec fs_posix("/foo/bar", false, FileSpec::Style::posix); 18 EXPECT_STREQ("/foo/bar", fs_posix.GetCString()); 19 EXPECT_STREQ("/foo", fs_posix.GetDirectory().GetCString()); 20 EXPECT_STREQ("bar", fs_posix.GetFilename().GetCString()); 21 22 FileSpec fs_windows("F:\\bar", false, FileSpec::Style::windows); 23 EXPECT_STREQ("F:\\bar", fs_windows.GetCString()); 24 // EXPECT_STREQ("F:\\", fs_windows.GetDirectory().GetCString()); // It returns 25 // "F:/" 26 EXPECT_STREQ("bar", fs_windows.GetFilename().GetCString()); 27 28 FileSpec fs_posix_root("/", false, FileSpec::Style::posix); 29 EXPECT_STREQ("/", fs_posix_root.GetCString()); 30 EXPECT_EQ(nullptr, fs_posix_root.GetDirectory().GetCString()); 31 EXPECT_STREQ("/", fs_posix_root.GetFilename().GetCString()); 32 33 FileSpec fs_windows_drive("F:", false, FileSpec::Style::windows); 34 EXPECT_STREQ("F:", fs_windows_drive.GetCString()); 35 EXPECT_EQ(nullptr, fs_windows_drive.GetDirectory().GetCString()); 36 EXPECT_STREQ("F:", fs_windows_drive.GetFilename().GetCString()); 37 38 FileSpec fs_windows_root("F:\\", false, FileSpec::Style::windows); 39 EXPECT_STREQ("F:\\", fs_windows_root.GetCString()); 40 EXPECT_STREQ("F:", fs_windows_root.GetDirectory().GetCString()); 41 // EXPECT_STREQ("\\", fs_windows_root.GetFilename().GetCString()); // It 42 // returns "/" 43 44 FileSpec fs_posix_long("/foo/bar/baz", false, FileSpec::Style::posix); 45 EXPECT_STREQ("/foo/bar/baz", fs_posix_long.GetCString()); 46 EXPECT_STREQ("/foo/bar", fs_posix_long.GetDirectory().GetCString()); 47 EXPECT_STREQ("baz", fs_posix_long.GetFilename().GetCString()); 48 49 FileSpec fs_windows_long("F:\\bar\\baz", false, FileSpec::Style::windows); 50 EXPECT_STREQ("F:\\bar\\baz", fs_windows_long.GetCString()); 51 // EXPECT_STREQ("F:\\bar", fs_windows_long.GetDirectory().GetCString()); // It 52 // returns "F:/bar" 53 EXPECT_STREQ("baz", fs_windows_long.GetFilename().GetCString()); 54 55 FileSpec fs_posix_trailing_slash("/foo/bar/", false, FileSpec::Style::posix); 56 EXPECT_STREQ("/foo/bar", fs_posix_trailing_slash.GetCString()); 57 EXPECT_STREQ("/foo", fs_posix_trailing_slash.GetDirectory().GetCString()); 58 EXPECT_STREQ("bar", fs_posix_trailing_slash.GetFilename().GetCString()); 59 60 FileSpec fs_windows_trailing_slash("F:\\bar\\", false, 61 FileSpec::Style::windows); 62 EXPECT_STREQ("F:\\bar", fs_windows_trailing_slash.GetCString()); 63 EXPECT_STREQ("bar", fs_windows_trailing_slash.GetFilename().GetCString()); 64 } 65 66 TEST(FileSpecTest, AppendPathComponent) { 67 FileSpec fs_posix("/foo", false, FileSpec::Style::posix); 68 fs_posix.AppendPathComponent("bar"); 69 EXPECT_STREQ("/foo/bar", fs_posix.GetCString()); 70 EXPECT_STREQ("/foo", fs_posix.GetDirectory().GetCString()); 71 EXPECT_STREQ("bar", fs_posix.GetFilename().GetCString()); 72 73 FileSpec fs_posix_2("/foo", false, FileSpec::Style::posix); 74 fs_posix_2.AppendPathComponent("//bar/baz"); 75 EXPECT_STREQ("/foo/bar/baz", fs_posix_2.GetCString()); 76 EXPECT_STREQ("/foo/bar", fs_posix_2.GetDirectory().GetCString()); 77 EXPECT_STREQ("baz", fs_posix_2.GetFilename().GetCString()); 78 79 FileSpec fs_windows("F:\\bar", false, FileSpec::Style::windows); 80 fs_windows.AppendPathComponent("baz"); 81 EXPECT_STREQ("F:\\bar\\baz", fs_windows.GetCString()); 82 // EXPECT_STREQ("F:\\bar", fs_windows.GetDirectory().GetCString()); // It 83 // returns "F:/bar" 84 EXPECT_STREQ("baz", fs_windows.GetFilename().GetCString()); 85 86 FileSpec fs_posix_root("/", false, FileSpec::Style::posix); 87 fs_posix_root.AppendPathComponent("bar"); 88 EXPECT_STREQ("/bar", fs_posix_root.GetCString()); 89 EXPECT_STREQ("/", fs_posix_root.GetDirectory().GetCString()); 90 EXPECT_STREQ("bar", fs_posix_root.GetFilename().GetCString()); 91 92 FileSpec fs_windows_root("F:\\", false, FileSpec::Style::windows); 93 fs_windows_root.AppendPathComponent("bar"); 94 EXPECT_STREQ("F:\\bar", fs_windows_root.GetCString()); 95 // EXPECT_STREQ("F:\\", fs_windows_root.GetDirectory().GetCString()); // It 96 // returns "F:/" 97 EXPECT_STREQ("bar", fs_windows_root.GetFilename().GetCString()); 98 } 99 100 TEST(FileSpecTest, CopyByAppendingPathComponent) { 101 FileSpec fs = FileSpec("/foo", false, FileSpec::Style::posix) 102 .CopyByAppendingPathComponent("bar"); 103 EXPECT_STREQ("/foo/bar", fs.GetCString()); 104 EXPECT_STREQ("/foo", fs.GetDirectory().GetCString()); 105 EXPECT_STREQ("bar", fs.GetFilename().GetCString()); 106 } 107 108 TEST(FileSpecTest, PrependPathComponent) { 109 FileSpec fs_posix("foo", false, FileSpec::Style::posix); 110 fs_posix.PrependPathComponent("/bar"); 111 EXPECT_STREQ("/bar/foo", fs_posix.GetCString()); 112 113 FileSpec fs_posix_2("foo/bar", false, FileSpec::Style::posix); 114 fs_posix_2.PrependPathComponent("/baz"); 115 EXPECT_STREQ("/baz/foo/bar", fs_posix_2.GetCString()); 116 117 FileSpec fs_windows("baz", false, FileSpec::Style::windows); 118 fs_windows.PrependPathComponent("F:\\bar"); 119 EXPECT_STREQ("F:\\bar\\baz", fs_windows.GetCString()); 120 121 FileSpec fs_posix_root("bar", false, FileSpec::Style::posix); 122 fs_posix_root.PrependPathComponent("/"); 123 EXPECT_STREQ("/bar", fs_posix_root.GetCString()); 124 125 FileSpec fs_windows_root("bar", false, FileSpec::Style::windows); 126 fs_windows_root.PrependPathComponent("F:\\"); 127 EXPECT_STREQ("F:\\bar", fs_windows_root.GetCString()); 128 } 129 130 TEST(FileSpecTest, EqualSeparator) { 131 FileSpec backward("C:\\foo\\bar", false, FileSpec::Style::windows); 132 FileSpec forward("C:/foo/bar", false, FileSpec::Style::windows); 133 EXPECT_EQ(forward, backward); 134 } 135 136 TEST(FileSpecTest, EqualDotsWindows) { 137 std::pair<const char *, const char *> tests[] = { 138 {R"(C:\foo\bar\baz)", R"(C:\foo\foo\..\bar\baz)"}, 139 {R"(C:\bar\baz)", R"(C:\foo\..\bar\baz)"}, 140 {R"(C:\bar\baz)", R"(C:/foo/../bar/baz)"}, 141 {R"(C:/bar/baz)", R"(C:\foo\..\bar\baz)"}, 142 {R"(C:\bar)", R"(C:\foo\..\bar)"}, 143 {R"(C:\foo\bar)", R"(C:\foo\.\bar)"}, 144 {R"(C:\foo\bar)", R"(C:\foo\bar\.)"}, 145 }; 146 147 for (const auto &test : tests) { 148 FileSpec one(test.first, false, FileSpec::Style::windows); 149 FileSpec two(test.second, false, FileSpec::Style::windows); 150 EXPECT_EQ(one, two); 151 } 152 } 153 154 TEST(FileSpecTest, EqualDotsPosix) { 155 std::pair<const char *, const char *> tests[] = { 156 {R"(/foo/bar/baz)", R"(/foo/foo/../bar/baz)"}, 157 {R"(/bar/baz)", R"(/foo/../bar/baz)"}, 158 {R"(/bar)", R"(/foo/../bar)"}, 159 {R"(/foo/bar)", R"(/foo/./bar)"}, 160 {R"(/foo/bar)", R"(/foo/bar/.)"}, 161 }; 162 163 for (const auto &test : tests) { 164 FileSpec one(test.first, false, FileSpec::Style::posix); 165 FileSpec two(test.second, false, FileSpec::Style::posix); 166 EXPECT_EQ(one, two); 167 } 168 } 169 170 TEST(FileSpecTest, EqualDotsPosixRoot) { 171 std::pair<const char *, const char *> tests[] = { 172 {R"(/)", R"(/..)"}, 173 {R"(/)", R"(/.)"}, 174 {R"(/)", R"(/foo/..)"}, 175 }; 176 177 for (const auto &test : tests) { 178 FileSpec one(test.first, false, FileSpec::Style::posix); 179 FileSpec two(test.second, false, FileSpec::Style::posix); 180 EXPECT_EQ(one, two); 181 } 182 } 183 184 TEST(FileSpecTest, GetNormalizedPath) { 185 std::pair<const char *, const char *> posix_tests[] = { 186 {"/foo/.././bar", "/bar"}, 187 {"/foo/./../bar", "/bar"}, 188 {"/foo/../bar", "/bar"}, 189 {"/foo/./bar", "/foo/bar"}, 190 {"/foo/..", "/"}, 191 {"/foo/.", "/foo"}, 192 {"/foo//bar", "/foo/bar"}, 193 {"/foo//bar/baz", "/foo/bar/baz"}, 194 {"/foo//bar/./baz", "/foo/bar/baz"}, 195 {"/./foo", "/foo"}, 196 {"/", "/"}, 197 {"//", "/"}, 198 {"//net", "//net"}, 199 {"/..", "/"}, 200 {"/.", "/"}, 201 {"..", ".."}, 202 {".", ""}, 203 {"../..", "../.."}, 204 {"foo/..", ""}, 205 {"foo/../bar", "bar"}, 206 {"../foo/..", ".."}, 207 {"./foo", "foo"}, 208 {"././foo", "foo"}, 209 {"../foo", "../foo"}, 210 {"../../foo", "../../foo"}, 211 }; 212 for (auto test : posix_tests) { 213 SCOPED_TRACE(llvm::Twine("test.first = ") + test.first); 214 EXPECT_EQ(test.second, 215 FileSpec(test.first, false, FileSpec::Style::posix).GetPath()); 216 } 217 218 std::pair<const char *, const char *> windows_tests[] = { 219 {R"(c:\bar\..\bar)", R"(c:\bar)"}, 220 {R"(c:\bar\.\bar)", R"(c:\bar\bar)"}, 221 {R"(c:\bar\..)", R"(c:\)"}, 222 {R"(c:\bar\.)", R"(c:\bar)"}, 223 {R"(c:\.\bar)", R"(c:\bar)"}, 224 {R"(\)", R"(\)"}, 225 {R"(\\)", R"(\)"}, 226 {R"(\\net)", R"(\\net)"}, 227 {R"(c:\..)", R"(c:\)"}, 228 {R"(c:\.)", R"(c:\)"}, 229 // TODO: fix llvm::sys::path::remove_dots() to return "\" below. 230 {R"(\..)", R"(\..)"}, 231 // {R"(c:..)", R"(c:..)"}, 232 {R"(..)", R"(..)"}, 233 {R"(.)", R"()"}, 234 // TODO: fix llvm::sys::path::remove_dots() to return "c:\" below. 235 {R"(c:..\..)", R"(c:\..\..)"}, 236 {R"(..\..)", R"(..\..)"}, 237 {R"(foo\..)", R"()"}, 238 {R"(foo\..\bar)", R"(bar)"}, 239 {R"(..\foo\..)", R"(..)"}, 240 {R"(.\foo)", R"(foo)"}, 241 {R"(.\.\foo)", R"(foo)"}, 242 {R"(..\foo)", R"(..\foo)"}, 243 {R"(..\..\foo)", R"(..\..\foo)"}, 244 }; 245 for (auto test : windows_tests) { 246 EXPECT_EQ(test.second, 247 FileSpec(test.first, false, FileSpec::Style::windows).GetPath()) 248 << "Original path: " << test.first; 249 } 250 } 251 252 TEST(FileSpecTest, FormatFileSpec) { 253 auto win = FileSpec::Style::windows; 254 255 FileSpec F; 256 EXPECT_EQ("(empty)", llvm::formatv("{0}", F).str()); 257 EXPECT_EQ("(empty)", llvm::formatv("{0:D}", F).str()); 258 EXPECT_EQ("(empty)", llvm::formatv("{0:F}", F).str()); 259 260 F = FileSpec("C:\\foo\\bar.txt", false, win); 261 EXPECT_EQ("C:\\foo\\bar.txt", llvm::formatv("{0}", F).str()); 262 EXPECT_EQ("C:\\foo\\", llvm::formatv("{0:D}", F).str()); 263 EXPECT_EQ("bar.txt", llvm::formatv("{0:F}", F).str()); 264 265 F = FileSpec("foo\\bar.txt", false, win); 266 EXPECT_EQ("foo\\bar.txt", llvm::formatv("{0}", F).str()); 267 EXPECT_EQ("foo\\", llvm::formatv("{0:D}", F).str()); 268 EXPECT_EQ("bar.txt", llvm::formatv("{0:F}", F).str()); 269 270 F = FileSpec("foo", false, win); 271 EXPECT_EQ("foo", llvm::formatv("{0}", F).str()); 272 EXPECT_EQ("foo", llvm::formatv("{0:F}", F).str()); 273 EXPECT_EQ("(empty)", llvm::formatv("{0:D}", F).str()); 274 } 275 276