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(path: "/build/src/main.cpp" ); |
28 | const FileSpec relative = PosixSpec(path: "./src/main.cpp" ); |
29 | const FileSpec basename = PosixSpec(path: "./main.cpp" ); |
30 | const FileSpec full_wrong = PosixSpec(path: "/other/wrong/main.cpp" ); |
31 | const FileSpec rel_wrong = PosixSpec(path: "./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(path: "asrc/main.cpp" ); |
35 | const FileSpec rel3_wrong = PosixSpec(path: "rc/main.cpp" ); |
36 | |
37 | SupportFileList files; |
38 | files.Append(file: fullpath); |
39 | files.Append(file: relative); |
40 | files.Append(file: basename); |
41 | files.Append(file: full_wrong); |
42 | files.Append(file: rel_wrong); |
43 | files.Append(file: rel2_wrong); |
44 | files.Append(file: 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(path: R"(C:\build\src\main.cpp)" ); |
80 | const FileSpec relative = WindowsSpec(path: R"(.\src\main.cpp)" ); |
81 | const FileSpec basename = WindowsSpec(path: R"(.\main.cpp)" ); |
82 | const FileSpec full_wrong = WindowsSpec(path: R"(\other\wrong\main.cpp)" ); |
83 | const FileSpec rel_wrong = WindowsSpec(path: 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(path: R"(asrc\main.cpp)" ); |
87 | const FileSpec rel3_wrong = WindowsSpec(path: R"("rc\main.cpp)" ); |
88 | |
89 | SupportFileList files; |
90 | files.Append(file: fullpath); |
91 | files.Append(file: relative); |
92 | files.Append(file: basename); |
93 | files.Append(file: full_wrong); |
94 | files.Append(file: rel_wrong); |
95 | files.Append(file: rel2_wrong); |
96 | files.Append(file: 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(path: "/symlink_dir/foo.h" ), PosixSpec(path: "/real_dir/foo.h" ), |
137 | FileSpec::Style::posix)); |
138 | |
139 | // Prepare RealpathPrefixes |
140 | FileSpecList file_spec_list; |
141 | file_spec_list.Append(file: PosixSpec(path: "/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(file: PosixSpec(path: "/symlink_dir/foo.h" )); |
147 | |
148 | // Test |
149 | size_t ret = support_file_list.FindCompatibleIndex( |
150 | idx: 0, file: PosixSpec(path: "/real_dir/foo.h" ), realpath_prefixes: &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(path: "/symlink_dir/foo.h" ), PosixSpec(path: "/real_dir/foo.h" ), |
162 | FileSpec::Style::posix)); |
163 | |
164 | // Prepare RealpathPrefixes |
165 | FileSpecList file_spec_list; |
166 | file_spec_list.Append(file: PosixSpec(path: "/" )); |
167 | RealpathPrefixes prefixes(file_spec_list, fs); |
168 | |
169 | // Prepare support file list |
170 | SupportFileList support_file_list; |
171 | support_file_list.Append(file: PosixSpec(path: "/symlink_dir/foo.h" )); |
172 | |
173 | // Test |
174 | size_t ret = support_file_list.FindCompatibleIndex( |
175 | idx: 0, file: PosixSpec(path: "/real_dir/foo.h" ), realpath_prefixes: &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(path: "symlink_dir/foo.h" ), PosixSpec(path: "real_dir/foo.h" ), |
187 | FileSpec::Style::posix)); |
188 | |
189 | // Prepare RealpathPrefixes |
190 | FileSpecList file_spec_list; |
191 | file_spec_list.Append(file: PosixSpec(path: "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(file: PosixSpec(path: "symlink_dir/foo.h" )); |
197 | |
198 | // Test |
199 | size_t ret = support_file_list.FindCompatibleIndex( |
200 | idx: 0, file: PosixSpec(path: "real_dir/foo.h" ), realpath_prefixes: &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(path: "symlink_dir/foo.h" ), PosixSpec(path: "real_dir/foo.h" ), |
212 | FileSpec::Style::posix)); |
213 | |
214 | // Prepare RealpathPrefixes |
215 | FileSpecList file_spec_list; |
216 | file_spec_list.Append(file: PosixSpec(path: "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(file: PosixSpec(path: "symlink_dir/foo.h" )); |
222 | |
223 | // Test |
224 | size_t ret = support_file_list.FindCompatibleIndex( |
225 | idx: 0, file: PosixSpec(path: "some_other_dir/foo.h" ), realpath_prefixes: &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(path: "symlink_dir/foo.h" ), PosixSpec(path: "real_dir/foo.h" ), |
236 | FileSpec::Style::posix)); |
237 | |
238 | // Prepare RealpathPrefixes |
239 | FileSpecList file_spec_list; |
240 | file_spec_list.Append(file: PosixSpec(path: "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(file: PosixSpec(path: "symlink_dir/foo.h" )); |
247 | |
248 | // Test |
249 | size_t ret = support_file_list.FindCompatibleIndex( |
250 | idx: 0, file: PosixSpec(path: "real_dir/foo.h" ), realpath_prefixes: &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(path: "symlink_dir/foo.h" ), PosixSpec(path: "/real_dir/foo.h" ), |
262 | FileSpec::Style::posix)); |
263 | |
264 | // Prepare RealpathPrefixes |
265 | FileSpecList file_spec_list; |
266 | file_spec_list.Append(file: PosixSpec(path: "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(file: PosixSpec(path: "symlink_dir/foo.h" )); |
272 | |
273 | // Test |
274 | size_t ret = support_file_list.FindCompatibleIndex( |
275 | idx: 0, file: PosixSpec(path: "real_dir/foo.h" ), realpath_prefixes: &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(path: "/symlink_dir/foo.h" ), PosixSpec(path: "/real_dir/bar.h" ), |
287 | FileSpec::Style::posix)); |
288 | |
289 | // Prepare RealpathPrefixes |
290 | FileSpecList file_spec_list; |
291 | file_spec_list.Append(file: PosixSpec(path: "/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(file: PosixSpec(path: "/symlink_dir/foo.h" )); |
297 | |
298 | // Test |
299 | size_t ret = support_file_list.FindCompatibleIndex( |
300 | idx: 0, file: PosixSpec(path: "real_dir/bar.h" ), realpath_prefixes: &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(file: PosixSpec(path: "/real_dir/bar.h" )); |
311 | |
312 | // Test |
313 | size_t ret = support_file_list.FindCompatibleIndex( |
314 | idx: 0, file: PosixSpec(path: "/real_dir/foo.h" ), realpath_prefixes: 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(file: PosixSpec(path: "/real_dir/foo.h" )); |
325 | |
326 | // Test |
327 | size_t ret = support_file_list.FindCompatibleIndex( |
328 | idx: 0, file: PosixSpec(path: "/real_dir/foo.h" ), realpath_prefixes: nullptr); |
329 | EXPECT_EQ(ret, (size_t)0); |
330 | } |
331 | |