1 //===-- FileDistanceTests.cpp ------------------------*- C++ -*-----------===// 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 "FileDistance.h" 10 #include "TestFS.h" 11 #include "gmock/gmock.h" 12 #include "gtest/gtest.h" 13 14 namespace clang { 15 namespace clangd { 16 namespace { 17 18 TEST(FileDistanceTests, Distance) { 19 FileDistanceOptions Opts; 20 Opts.UpCost = 5; 21 Opts.DownCost = 3; 22 SourceParams CostTwo; 23 CostTwo.Cost = 2; 24 FileDistance D( 25 {{"tools/clang/lib/Format/FormatToken.cpp", SourceParams()}, 26 {"tools/clang/include/clang/Format/FormatToken.h", SourceParams()}, 27 {"include/llvm/ADT/StringRef.h", CostTwo}}, 28 Opts); 29 30 // Source 31 EXPECT_EQ(D.distance("tools/clang/lib/Format/FormatToken.cpp"), 0u); 32 EXPECT_EQ(D.distance("include/llvm/ADT/StringRef.h"), 2u); 33 // Parent 34 EXPECT_EQ(D.distance("tools/clang/lib/Format/"), 5u); 35 // Child 36 EXPECT_EQ(D.distance("tools/clang/lib/Format/FormatToken.cpp/Oops"), 3u); 37 // Ancestor (up+up+up+up) 38 EXPECT_EQ(D.distance("/"), 22u); 39 // Sibling (up+down) 40 EXPECT_EQ(D.distance("tools/clang/lib/Format/AnotherFile.cpp"), 8u); 41 // Cousin (up+up+down+down) 42 EXPECT_EQ(D.distance("include/llvm/Support/Allocator.h"), 18u); 43 // First cousin, once removed (up+up+up+down+down) 44 EXPECT_EQ(D.distance("include/llvm-c/Core.h"), 23u); 45 } 46 47 TEST(FileDistanceTests, BadSource) { 48 // We mustn't assume that paths above sources are best reached via them. 49 FileDistanceOptions Opts; 50 Opts.UpCost = 5; 51 Opts.DownCost = 3; 52 SourceParams CostLots; 53 CostLots.Cost = 100; 54 FileDistance D({{"a", SourceParams()}, {"b/b/b", CostLots}}, Opts); 55 EXPECT_EQ(D.distance("b"), 8u); // a+up+down, not b+up+up 56 EXPECT_EQ(D.distance("b/b/b"), 14u); // a+up+down+down+down, not b 57 EXPECT_EQ(D.distance("b/b/b/c"), 17u); // a+up+down+down+down+down, not b+down 58 } 59 60 // Force the unittest URI scheme to be linked, 61 static int LLVM_ATTRIBUTE_UNUSED UseUnittestScheme = UnittestSchemeAnchorSource; 62 63 TEST(FileDistanceTests, URI) { 64 FileDistanceOptions Opts; 65 Opts.UpCost = 5; 66 Opts.DownCost = 3; 67 SourceParams CostLots; 68 CostLots.Cost = 1000; 69 70 URIDistance D({{testPath("foo"), CostLots}, 71 {"/not/a/testpath", SourceParams()}, 72 {"C:\\not\\a\\testpath", SourceParams()}}, 73 Opts); 74 #ifdef _WIN32 75 EXPECT_EQ(D.distance("file:///C%3a/not/a/testpath/either"), 3u); 76 #else 77 EXPECT_EQ(D.distance("file:///not/a/testpath/either"), 3u); 78 #endif 79 EXPECT_EQ(D.distance("unittest:///foo"), 1000u); 80 EXPECT_EQ(D.distance("unittest:///bar"), 1008u); 81 } 82 83 TEST(FileDistance, LimitUpTraversals) { 84 FileDistanceOptions Opts; 85 Opts.UpCost = Opts.DownCost = 1; 86 SourceParams CheapButLimited, CostLots; 87 CheapButLimited.MaxUpTraversals = 1; 88 CostLots.Cost = 100; 89 90 FileDistance D({{"/", CostLots}, {"/a/b/c", CheapButLimited}}, Opts); 91 EXPECT_EQ(D.distance("/a"), 101u); 92 EXPECT_EQ(D.distance("/a/z"), 102u); 93 EXPECT_EQ(D.distance("/a/b"), 1u); 94 EXPECT_EQ(D.distance("/a/b/z"), 2u); 95 } 96 97 TEST(FileDistance, DisallowDownTraversalsFromRoot) { 98 FileDistanceOptions Opts; 99 Opts.UpCost = Opts.DownCost = 1; 100 Opts.AllowDownTraversalFromRoot = false; 101 SourceParams CostLots; 102 CostLots.Cost = 100; 103 104 FileDistance D({{"/", SourceParams()}, {"/a/b/c", CostLots}}, Opts); 105 EXPECT_EQ(D.distance("/"), 0u); 106 EXPECT_EQ(D.distance("/a"), 102u); 107 EXPECT_EQ(D.distance("/a/b"), 101u); 108 EXPECT_EQ(D.distance("/x"), FileDistance::Unreachable); 109 } 110 111 TEST(ScopeDistance, Smoke) { 112 ScopeDistance D({"x::y::z", "x::", "", "a::"}); 113 EXPECT_EQ(D.distance("x::y::z::"), 0u); 114 EXPECT_GT(D.distance("x::y::"), D.distance("x::y::z::")); 115 EXPECT_GT(D.distance("x::"), D.distance("x::y::")); 116 EXPECT_GT(D.distance("x::y::z::down::"), D.distance("x::y::")); 117 EXPECT_GT(D.distance(""), D.distance("a::")); 118 EXPECT_GT(D.distance("x::"), D.distance("a::")); 119 } 120 121 } // namespace 122 } // namespace clangd 123 } // namespace clang 124