xref: /llvm-project/lldb/unittests/Utility/FileSpecListTest.cpp (revision 26670e7fa4f032a019d23d56c6a02926e854e8af)
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