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