1 //===-- FileSpecListTest.cpp ----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "gtest/gtest.h" 10 11 #include "MockSymlinkFileSystem.h" 12 #include "lldb/Utility/FileSpecList.h" 13 #include "lldb/Utility/RealpathPrefixes.h" 14 15 using namespace lldb_private; 16 17 static FileSpec PosixSpec(llvm::StringRef path) { 18 return FileSpec(path, FileSpec::Style::posix); 19 } 20 21 static FileSpec WindowsSpec(llvm::StringRef path) { 22 return FileSpec(path, FileSpec::Style::windows); 23 } 24 25 TEST(SupportFileListTest, RelativePathMatchesPosix) { 26 27 const FileSpec fullpath = PosixSpec("/build/src/main.cpp"); 28 const FileSpec relative = PosixSpec("./src/main.cpp"); 29 const FileSpec basename = PosixSpec("./main.cpp"); 30 const FileSpec full_wrong = PosixSpec("/other/wrong/main.cpp"); 31 const FileSpec rel_wrong = PosixSpec("./wrong/main.cpp"); 32 // Make sure these don't match "src/main.cpp" as we want to match full 33 // directories only 34 const FileSpec rel2_wrong = PosixSpec("asrc/main.cpp"); 35 const FileSpec rel3_wrong = PosixSpec("rc/main.cpp"); 36 37 SupportFileList files; 38 files.Append(fullpath); 39 files.Append(relative); 40 files.Append(basename); 41 files.Append(full_wrong); 42 files.Append(rel_wrong); 43 files.Append(rel2_wrong); 44 files.Append(rel3_wrong); 45 46 // Make sure the full path only matches the first entry 47 EXPECT_EQ((size_t)0, files.FindCompatibleIndex(0, fullpath)); 48 EXPECT_EQ((size_t)1, files.FindCompatibleIndex(1, fullpath)); 49 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(2, fullpath)); 50 EXPECT_EQ((size_t)UINT32_MAX, files.FindCompatibleIndex(3, fullpath)); 51 // Make sure the relative path matches the all of the entries that contain 52 // the relative path 53 EXPECT_EQ((size_t)0, files.FindCompatibleIndex(0, relative)); 54 EXPECT_EQ((size_t)1, files.FindCompatibleIndex(1, relative)); 55 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(2, relative)); 56 EXPECT_EQ((size_t)UINT32_MAX, files.FindCompatibleIndex(3, relative)); 57 58 // Make sure looking file a file using the basename matches all entries 59 EXPECT_EQ((size_t)0, files.FindCompatibleIndex(0, basename)); 60 EXPECT_EQ((size_t)1, files.FindCompatibleIndex(1, basename)); 61 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(2, basename)); 62 EXPECT_EQ((size_t)3, files.FindCompatibleIndex(3, basename)); 63 EXPECT_EQ((size_t)4, files.FindCompatibleIndex(4, basename)); 64 EXPECT_EQ((size_t)5, files.FindCompatibleIndex(5, basename)); 65 EXPECT_EQ((size_t)6, files.FindCompatibleIndex(6, basename)); 66 67 // Make sure that paths that have a common suffix don't return values that 68 // don't match on directory delimiters. 69 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(0, rel2_wrong)); 70 EXPECT_EQ((size_t)5, files.FindCompatibleIndex(3, rel2_wrong)); 71 EXPECT_EQ((size_t)UINT32_MAX, files.FindCompatibleIndex(6, rel2_wrong)); 72 73 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(0, rel3_wrong)); 74 EXPECT_EQ((size_t)6, files.FindCompatibleIndex(3, rel3_wrong)); 75 } 76 77 TEST(SupportFileListTest, RelativePathMatchesWindows) { 78 79 const FileSpec fullpath = WindowsSpec(R"(C:\build\src\main.cpp)"); 80 const FileSpec relative = WindowsSpec(R"(.\src\main.cpp)"); 81 const FileSpec basename = WindowsSpec(R"(.\main.cpp)"); 82 const FileSpec full_wrong = WindowsSpec(R"(\other\wrong\main.cpp)"); 83 const FileSpec rel_wrong = WindowsSpec(R"(.\wrong\main.cpp)"); 84 // Make sure these don't match "src\main.cpp" as we want to match full 85 // directories only 86 const FileSpec rel2_wrong = WindowsSpec(R"(asrc\main.cpp)"); 87 const FileSpec rel3_wrong = WindowsSpec(R"("rc\main.cpp)"); 88 89 SupportFileList files; 90 files.Append(fullpath); 91 files.Append(relative); 92 files.Append(basename); 93 files.Append(full_wrong); 94 files.Append(rel_wrong); 95 files.Append(rel2_wrong); 96 files.Append(rel3_wrong); 97 98 // Make sure the full path only matches the first entry 99 EXPECT_EQ((size_t)0, files.FindCompatibleIndex(0, fullpath)); 100 EXPECT_EQ((size_t)1, files.FindCompatibleIndex(1, fullpath)); 101 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(2, fullpath)); 102 EXPECT_EQ((size_t)UINT32_MAX, files.FindCompatibleIndex(3, fullpath)); 103 // Make sure the relative path matches the all of the entries that contain 104 // the relative path 105 EXPECT_EQ((size_t)0, files.FindCompatibleIndex(0, relative)); 106 EXPECT_EQ((size_t)1, files.FindCompatibleIndex(1, relative)); 107 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(2, relative)); 108 EXPECT_EQ((size_t)UINT32_MAX, files.FindCompatibleIndex(3, relative)); 109 110 // Make sure looking file a file using the basename matches all entries 111 EXPECT_EQ((size_t)0, files.FindCompatibleIndex(0, basename)); 112 EXPECT_EQ((size_t)1, files.FindCompatibleIndex(1, basename)); 113 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(2, basename)); 114 EXPECT_EQ((size_t)3, files.FindCompatibleIndex(3, basename)); 115 EXPECT_EQ((size_t)4, files.FindCompatibleIndex(4, basename)); 116 EXPECT_EQ((size_t)5, files.FindCompatibleIndex(5, basename)); 117 EXPECT_EQ((size_t)6, files.FindCompatibleIndex(6, basename)); 118 119 // Make sure that paths that have a common suffix don't return values that 120 // don't match on directory delimiters. 121 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(0, rel2_wrong)); 122 EXPECT_EQ((size_t)5, files.FindCompatibleIndex(3, rel2_wrong)); 123 EXPECT_EQ((size_t)UINT32_MAX, files.FindCompatibleIndex(6, rel2_wrong)); 124 125 EXPECT_EQ((size_t)2, files.FindCompatibleIndex(0, rel3_wrong)); 126 EXPECT_EQ((size_t)6, files.FindCompatibleIndex(3, rel3_wrong)); 127 } 128 129 // Support file is a symlink to the breakpoint file. 130 // Absolute paths are used. 131 // A matching prefix is set. 132 // Should find it compatible. 133 TEST(SupportFileListTest, SymlinkedAbsolutePaths) { 134 // Prepare FS 135 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem( 136 PosixSpec("/symlink_dir/foo.h"), PosixSpec("/real_dir/foo.h"), 137 FileSpec::Style::posix)); 138 139 // Prepare RealpathPrefixes 140 FileSpecList file_spec_list; 141 file_spec_list.Append(PosixSpec("/symlink_dir")); 142 RealpathPrefixes prefixes(file_spec_list, fs); 143 144 // Prepare support file list 145 SupportFileList support_file_list; 146 support_file_list.Append(PosixSpec("/symlink_dir/foo.h")); 147 148 // Test 149 size_t ret = support_file_list.FindCompatibleIndex( 150 0, PosixSpec("/real_dir/foo.h"), &prefixes); 151 EXPECT_EQ(ret, (size_t)0); 152 } 153 154 // Support file is a symlink to the breakpoint file. 155 // Absolute paths are used. 156 // A matching prefix is set, which is the root directory. 157 // Should find it compatible. 158 TEST(SupportFileListTest, RootDirectory) { 159 // Prepare FS 160 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem( 161 PosixSpec("/symlink_dir/foo.h"), PosixSpec("/real_dir/foo.h"), 162 FileSpec::Style::posix)); 163 164 // Prepare RealpathPrefixes 165 FileSpecList file_spec_list; 166 file_spec_list.Append(PosixSpec("/")); 167 RealpathPrefixes prefixes(file_spec_list, fs); 168 169 // Prepare support file list 170 SupportFileList support_file_list; 171 support_file_list.Append(PosixSpec("/symlink_dir/foo.h")); 172 173 // Test 174 size_t ret = support_file_list.FindCompatibleIndex( 175 0, PosixSpec("/real_dir/foo.h"), &prefixes); 176 EXPECT_EQ(ret, (size_t)0); 177 } 178 179 // Support file is a symlink to the breakpoint file. 180 // Relative paths are used. 181 // A matching prefix is set. 182 // Should find it compatible. 183 TEST(SupportFileListTest, SymlinkedRelativePaths) { 184 // Prepare FS 185 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem( 186 PosixSpec("symlink_dir/foo.h"), PosixSpec("real_dir/foo.h"), 187 FileSpec::Style::posix)); 188 189 // Prepare RealpathPrefixes 190 FileSpecList file_spec_list; 191 file_spec_list.Append(PosixSpec("symlink_dir")); 192 RealpathPrefixes prefixes(file_spec_list, fs); 193 194 // Prepare support file list 195 SupportFileList support_file_list; 196 support_file_list.Append(PosixSpec("symlink_dir/foo.h")); 197 198 // Test 199 size_t ret = support_file_list.FindCompatibleIndex( 200 0, PosixSpec("real_dir/foo.h"), &prefixes); 201 EXPECT_EQ(ret, (size_t)0); 202 } 203 204 // Support file is a symlink to the breakpoint file. 205 // A matching prefix is set. 206 // Input file only match basename and not directory. 207 // Should find it incompatible. 208 TEST(SupportFileListTest, RealpathOnlyMatchFileName) { 209 // Prepare FS 210 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem( 211 PosixSpec("symlink_dir/foo.h"), PosixSpec("real_dir/foo.h"), 212 FileSpec::Style::posix)); 213 214 // Prepare RealpathPrefixes 215 FileSpecList file_spec_list; 216 file_spec_list.Append(PosixSpec("symlink_dir")); 217 RealpathPrefixes prefixes(file_spec_list, fs); 218 219 // Prepare support file list 220 SupportFileList support_file_list; 221 support_file_list.Append(PosixSpec("symlink_dir/foo.h")); 222 223 // Test 224 size_t ret = support_file_list.FindCompatibleIndex( 225 0, PosixSpec("some_other_dir/foo.h"), &prefixes); 226 EXPECT_EQ(ret, UINT32_MAX); 227 } 228 229 // Support file is a symlink to the breakpoint file. 230 // A prefix is set, which is a matching string prefix, but not a path prefix. 231 // Should find it incompatible. 232 TEST(SupportFileListTest, DirectoryMatchStringPrefixButNotWholeDirectoryName) { 233 // Prepare FS 234 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem( 235 PosixSpec("symlink_dir/foo.h"), PosixSpec("real_dir/foo.h"), 236 FileSpec::Style::posix)); 237 238 // Prepare RealpathPrefixes 239 FileSpecList file_spec_list; 240 file_spec_list.Append(PosixSpec("symlink")); // This is a string prefix of the 241 // symlink but not a path prefix. 242 RealpathPrefixes prefixes(file_spec_list, fs); 243 244 // Prepare support file list 245 SupportFileList support_file_list; 246 support_file_list.Append(PosixSpec("symlink_dir/foo.h")); 247 248 // Test 249 size_t ret = support_file_list.FindCompatibleIndex( 250 0, PosixSpec("real_dir/foo.h"), &prefixes); 251 EXPECT_EQ(ret, UINT32_MAX); 252 } 253 254 // Support file is a symlink to the breakpoint file. 255 // A matching prefix is set. 256 // However, the breakpoint is set with a partial path. 257 // Should find it compatible. 258 TEST(SupportFileListTest, PartialBreakpointPath) { 259 // Prepare FS 260 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem( 261 PosixSpec("symlink_dir/foo.h"), PosixSpec("/real_dir/foo.h"), 262 FileSpec::Style::posix)); 263 264 // Prepare RealpathPrefixes 265 FileSpecList file_spec_list; 266 file_spec_list.Append(PosixSpec("symlink_dir")); 267 RealpathPrefixes prefixes(file_spec_list, fs); 268 269 // Prepare support file list 270 SupportFileList support_file_list; 271 support_file_list.Append(PosixSpec("symlink_dir/foo.h")); 272 273 // Test 274 size_t ret = support_file_list.FindCompatibleIndex( 275 0, PosixSpec("real_dir/foo.h"), &prefixes); 276 EXPECT_EQ(ret, (size_t)0); 277 } 278 279 // Support file is a symlink to the breakpoint file. 280 // A matching prefix is set. 281 // However, the basename is different between the symlink and its target. 282 // Should find it incompatible. 283 TEST(SupportFileListTest, DifferentBasename) { 284 // Prepare FS 285 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem( 286 PosixSpec("/symlink_dir/foo.h"), PosixSpec("/real_dir/bar.h"), 287 FileSpec::Style::posix)); 288 289 // Prepare RealpathPrefixes 290 FileSpecList file_spec_list; 291 file_spec_list.Append(PosixSpec("/symlink_dir")); 292 RealpathPrefixes prefixes(file_spec_list, fs); 293 294 // Prepare support file list 295 SupportFileList support_file_list; 296 support_file_list.Append(PosixSpec("/symlink_dir/foo.h")); 297 298 // Test 299 size_t ret = support_file_list.FindCompatibleIndex( 300 0, PosixSpec("real_dir/bar.h"), &prefixes); 301 EXPECT_EQ(ret, UINT32_MAX); 302 } 303 304 // No prefixes are configured. 305 // The support file and the breakpoint file are different. 306 // Should find it incompatible. 307 TEST(SupportFileListTest, NoPrefixes) { 308 // Prepare support file list 309 SupportFileList support_file_list; 310 support_file_list.Append(PosixSpec("/real_dir/bar.h")); 311 312 // Test 313 size_t ret = support_file_list.FindCompatibleIndex( 314 0, PosixSpec("/real_dir/foo.h"), nullptr); 315 EXPECT_EQ(ret, UINT32_MAX); 316 } 317 318 // No prefixes are configured. 319 // The support file and the breakpoint file are the same. 320 // Should find it compatible. 321 TEST(SupportFileListTest, SameFile) { 322 // Prepare support file list 323 SupportFileList support_file_list; 324 support_file_list.Append(PosixSpec("/real_dir/foo.h")); 325 326 // Test 327 size_t ret = support_file_list.FindCompatibleIndex( 328 0, PosixSpec("/real_dir/foo.h"), nullptr); 329 EXPECT_EQ(ret, (size_t)0); 330 } 331