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