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
15using namespace lldb_private;
16
17static FileSpec PosixSpec(llvm::StringRef path) {
18 return FileSpec(path, FileSpec::Style::posix);
19}
20
21static FileSpec WindowsSpec(llvm::StringRef path) {
22 return FileSpec(path, FileSpec::Style::windows);
23}
24
25TEST(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
77TEST(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.
133TEST(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.
158TEST(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.
183TEST(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.
208TEST(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.
232TEST(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.
258TEST(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.
283TEST(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.
307TEST(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.
321TEST(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

source code of lldb/unittests/Utility/FileSpecListTest.cpp