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
16using namespace lldb_private;
17
18static FileSpec PosixSpec(llvm::StringRef path) {
19 return FileSpec(path, FileSpec::Style::posix);
20}
21
22static FileSpec WindowsSpec(llvm::StringRef path) {
23 return FileSpec(path, FileSpec::Style::windows);
24}
25
26// Should resolve a symlink which match an absolute prefix
27TEST(RealpathPrefixesTest, MatchingAbsolutePrefix) {
28 // Prepare FS
29 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
30 PosixSpec(path: "/dir1/link.h"), PosixSpec(path: "/dir2/real.h"),
31 FileSpec::Style::posix));
32
33 // Prepare RealpathPrefixes
34 FileSpecList file_spec_list;
35 file_spec_list.Append(file: PosixSpec(path: "/dir1"));
36 RealpathPrefixes prefixes(file_spec_list, fs);
37
38 // Test
39 std::optional<FileSpec> ret =
40 prefixes.ResolveSymlinks(file_spec: PosixSpec(path: "/dir1/link.h"));
41 EXPECT_EQ(ret, PosixSpec("/dir2/real.h"));
42}
43
44// Should resolve a symlink which match a relative prefix
45TEST(RealpathPrefixesTest, MatchingRelativePrefix) {
46 // Prepare FS
47 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
48 PosixSpec(path: "dir1/link.h"), PosixSpec(path: "dir2/real.h"),
49 FileSpec::Style::posix));
50
51 // Prepare RealpathPrefixes
52 FileSpecList file_spec_list;
53 file_spec_list.Append(file: PosixSpec(path: "dir1"));
54 RealpathPrefixes prefixes(file_spec_list, fs);
55
56 // Test
57 std::optional<FileSpec> ret =
58 prefixes.ResolveSymlinks(file_spec: PosixSpec(path: "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
63TEST(RealpathPrefixesTest, WindowsAndCaseInsensitive) {
64 // Prepare FS
65 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
66 WindowsSpec(path: "f:\\dir1\\link.h"), WindowsSpec(path: "f:\\dir2\\real.h"),
67 FileSpec::Style::windows));
68
69 // Prepare RealpathPrefixes
70 FileSpecList file_spec_list;
71 file_spec_list.Append(file: WindowsSpec(path: "f:\\dir1"));
72 RealpathPrefixes prefixes(file_spec_list, fs);
73
74 // Test
75 std::optional<FileSpec> ret =
76 prefixes.ResolveSymlinks(file_spec: WindowsSpec(path: "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
82TEST(RealpathPrefixesTest, MatchingAndMismatchingPrefix) {
83 // Prepare FS
84 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
85 PosixSpec(path: "/dir1/link.h"), PosixSpec(path: "/dir2/real.h"),
86 FileSpec::Style::posix));
87
88 // Prepare RealpathPrefixes
89 FileSpecList file_spec_list;
90 file_spec_list.Append(file: PosixSpec(path: "/fake/path1"));
91 file_spec_list.Append(file: PosixSpec(path: "/dir1")); // Matching prefix
92 file_spec_list.Append(file: PosixSpec(path: "/fake/path2"));
93 RealpathPrefixes prefixes(file_spec_list, fs);
94
95 // Test
96 std::optional<FileSpec> ret =
97 prefixes.ResolveSymlinks(file_spec: PosixSpec(path: "/dir1/link.h"));
98 EXPECT_EQ(ret, PosixSpec("/dir2/real.h"));
99}
100
101// Should resolve a symlink when the prefixes matches after normalization
102TEST(RealpathPrefixesTest, ComplexPrefixes) {
103 // Prepare FS
104 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
105 PosixSpec(path: "dir1/link.h"), PosixSpec(path: "dir2/real.h"),
106 FileSpec::Style::posix));
107
108 // Prepare RealpathPrefixes
109 FileSpecList file_spec_list;
110 file_spec_list.Append(
111 file: PosixSpec(path: "./dir1/foo/../bar/..")); // Equivalent to "/dir1"
112 RealpathPrefixes prefixes(file_spec_list, fs);
113
114 // Test
115 std::optional<FileSpec> ret =
116 prefixes.ResolveSymlinks(file_spec: PosixSpec(path: "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
121TEST(RealpathPrefixesTest, MismatchingPrefixes) {
122 // Prepare FS
123 llvm::IntrusiveRefCntPtr<MockSymlinkFileSystem> fs(new MockSymlinkFileSystem(
124 PosixSpec(path: "/dir1/link.h"), PosixSpec(path: "/dir2/real.h"),
125 FileSpec::Style::posix));
126
127 // Prepare RealpathPrefixes
128 FileSpecList file_spec_list;
129 file_spec_list.Append(file: PosixSpec(path: "/dir3"));
130 RealpathPrefixes prefixes(file_spec_list, fs);
131
132 // Test
133 std::optional<FileSpec> ret =
134 prefixes.ResolveSymlinks(file_spec: PosixSpec(path: "/dir1/link.h"));
135 EXPECT_EQ(ret, std::nullopt);
136}
137
138// Should not resolve a realpath
139TEST(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(file: PosixSpec(path: "/symlink_dir"));
147 RealpathPrefixes prefixes(file_spec_list, fs);
148
149 // Test
150 std::optional<FileSpec> ret =
151 prefixes.ResolveSymlinks(file_spec: PosixSpec(path: "/dir/real.h"));
152 EXPECT_EQ(ret, std::nullopt);
153}
154

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