xref: /llvm-project/lldb/unittests/Utility/RealpathPrefixesTest.cpp (revision 26670e7fa4f032a019d23d56c6a02926e854e8af)
1 //===-- RealpathPrefixesTest.cpp
2 //--------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "gtest/gtest.h"
11 
12 #include "MockSymlinkFileSystem.h"
13 #include "lldb/Utility/FileSpecList.h"
14 #include "lldb/Utility/RealpathPrefixes.h"
15 
16 using namespace lldb_private;
17 
18 static FileSpec PosixSpec(llvm::StringRef path) {
19   return FileSpec(path, FileSpec::Style::posix);
20 }
21 
22 static FileSpec WindowsSpec(llvm::StringRef path) {
23   return FileSpec(path, FileSpec::Style::windows);
24 }
25 
26 // Should resolve a symlink which match an absolute prefix
27 TEST(RealpathPrefixesTest, MatchingAbsolutePrefix) {
28   // Prepare FS
29   llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
30       PosixSpec("/dir1/link.h"), PosixSpec("/dir2/real.h"),
31       FileSpec::Style::posix));
32 
33   // Prepare RealpathPrefixes
34   FileSpecList file_spec_list;
35   file_spec_list.Append(PosixSpec("/dir1"));
36   RealpathPrefixes prefixes(file_spec_list, fs);
37 
38   // Test
39   std::optional<FileSpec> ret =
40       prefixes.ResolveSymlinks(PosixSpec("/dir1/link.h"));
41   EXPECT_EQ(ret, PosixSpec("/dir2/real.h"));
42 }
43 
44 // Should resolve a symlink which match a relative prefix
45 TEST(RealpathPrefixesTest, MatchingRelativePrefix) {
46   // Prepare FS
47   llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
48       PosixSpec("dir1/link.h"), PosixSpec("dir2/real.h"),
49       FileSpec::Style::posix));
50 
51   // Prepare RealpathPrefixes
52   FileSpecList file_spec_list;
53   file_spec_list.Append(PosixSpec("dir1"));
54   RealpathPrefixes prefixes(file_spec_list, fs);
55 
56   // Test
57   std::optional<FileSpec> ret =
58       prefixes.ResolveSymlinks(PosixSpec("dir1/link.h"));
59   EXPECT_EQ(ret, PosixSpec("dir2/real.h"));
60 }
61 
62 // Should resolve in Windows and/or with a case-insensitive support file
63 TEST(RealpathPrefixesTest, WindowsAndCaseInsensitive) {
64   // Prepare FS
65   llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
66       WindowsSpec("f:\\dir1\\link.h"), WindowsSpec("f:\\dir2\\real.h"),
67       FileSpec::Style::windows));
68 
69   // Prepare RealpathPrefixes
70   FileSpecList file_spec_list;
71   file_spec_list.Append(WindowsSpec("f:\\dir1"));
72   RealpathPrefixes prefixes(file_spec_list, fs);
73 
74   // Test
75   std::optional<FileSpec> ret =
76       prefixes.ResolveSymlinks(WindowsSpec("F:\\DIR1\\LINK.H"));
77   EXPECT_EQ(ret, WindowsSpec("f:\\dir2\\real.h"));
78 }
79 
80 // Should resolve a symlink when there is mixture of matching and mismatching
81 // prefixex
82 TEST(RealpathPrefixesTest, MatchingAndMismatchingPrefix) {
83   // Prepare FS
84   llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
85       PosixSpec("/dir1/link.h"), PosixSpec("/dir2/real.h"),
86       FileSpec::Style::posix));
87 
88   // Prepare RealpathPrefixes
89   FileSpecList file_spec_list;
90   file_spec_list.Append(PosixSpec("/fake/path1"));
91   file_spec_list.Append(PosixSpec("/dir1")); // Matching prefix
92   file_spec_list.Append(PosixSpec("/fake/path2"));
93   RealpathPrefixes prefixes(file_spec_list, fs);
94 
95   // Test
96   std::optional<FileSpec> ret =
97       prefixes.ResolveSymlinks(PosixSpec("/dir1/link.h"));
98   EXPECT_EQ(ret, PosixSpec("/dir2/real.h"));
99 }
100 
101 // Should resolve a symlink when the prefixes matches after normalization
102 TEST(RealpathPrefixesTest, ComplexPrefixes) {
103   // Prepare FS
104   llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
105       PosixSpec("dir1/link.h"), PosixSpec("dir2/real.h"),
106       FileSpec::Style::posix));
107 
108   // Prepare RealpathPrefixes
109   FileSpecList file_spec_list;
110   file_spec_list.Append(
111       PosixSpec("./dir1/foo/../bar/..")); // Equivalent to "/dir1"
112   RealpathPrefixes prefixes(file_spec_list, fs);
113 
114   // Test
115   std::optional<FileSpec> ret =
116       prefixes.ResolveSymlinks(PosixSpec("dir1/link.h"));
117   EXPECT_EQ(ret, PosixSpec("dir2/real.h"));
118 }
119 
120 // Should not resolve a symlink which doesn't match any prefixes
121 TEST(RealpathPrefixesTest, MismatchingPrefixes) {
122   // Prepare FS
123   llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
124       PosixSpec("/dir1/link.h"), PosixSpec("/dir2/real.h"),
125       FileSpec::Style::posix));
126 
127   // Prepare RealpathPrefixes
128   FileSpecList file_spec_list;
129   file_spec_list.Append(PosixSpec("/dir3"));
130   RealpathPrefixes prefixes(file_spec_list, fs);
131 
132   // Test
133   std::optional<FileSpec> ret =
134       prefixes.ResolveSymlinks(PosixSpec("/dir1/link.h"));
135   EXPECT_EQ(ret, std::nullopt);
136 }
137 
138 // Should not resolve a realpath
139 TEST(RealpathPrefixesTest, Realpath) {
140   // Prepare FS
141   llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(
142       new MockSymlinkFileSystem());
143 
144   // Prepare RealpathPrefixes
145   FileSpecList file_spec_list;
146   file_spec_list.Append(PosixSpec("/symlink_dir"));
147   RealpathPrefixes prefixes(file_spec_list, fs);
148 
149   // Test
150   std::optional<FileSpec> ret =
151       prefixes.ResolveSymlinks(PosixSpec("/dir/real.h"));
152   EXPECT_EQ(ret, std::nullopt);
153 }
154