clang-tools  10.0.0git
URITests.cpp
Go to the documentation of this file.
1 //===-- URITests.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 "Matchers.h"
10 #include "TestFS.h"
11 #include "URI.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14 
15 namespace clang {
16 namespace clangd {
17 
18 // Force the unittest URI scheme to be linked,
19 static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest =
21 
22 namespace {
23 
24 using ::testing::AllOf;
25 
26 MATCHER_P(Scheme, S, "") { return arg.scheme() == S; }
27 MATCHER_P(Authority, A, "") { return arg.authority() == A; }
28 MATCHER_P(Body, B, "") { return arg.body() == B; }
29 
30 std::string createOrDie(llvm::StringRef AbsolutePath,
31  llvm::StringRef Scheme = "file") {
32  auto Uri = URI::create(AbsolutePath, Scheme);
33  if (!Uri)
34  llvm_unreachable(toString(Uri.takeError()).c_str());
35  return Uri->toString();
36 }
37 
38 URI parseOrDie(llvm::StringRef Uri) {
39  auto U = URI::parse(Uri);
40  if (!U)
41  llvm_unreachable(toString(U.takeError()).c_str());
42  return *U;
43 }
44 
45 TEST(PercentEncodingTest, Encode) {
46  EXPECT_EQ(URI("x", /*Authority=*/"", "a/b/c").toString(), "x:a/b/c");
47  EXPECT_EQ(URI("x", /*Authority=*/"", "a!b;c~").toString(), "x:a%21b%3Bc~");
48  EXPECT_EQ(URI("x", /*Authority=*/"", "a123b").toString(), "x:a123b");
49  EXPECT_EQ(URI("x", /*Authority=*/"", "a:b;c").toString(), "x:a:b%3Bc");
50 }
51 
52 TEST(PercentEncodingTest, Decode) {
53  EXPECT_EQ(parseOrDie("x:a/b/c").body(), "a/b/c");
54 
55  EXPECT_EQ(parseOrDie("s%2b://%3a/%3").scheme(), "s+");
56  EXPECT_EQ(parseOrDie("s%2b://%3a/%3").authority(), ":");
57  EXPECT_EQ(parseOrDie("s%2b://%3a/%3").body(), "/%3");
58 
59  EXPECT_EQ(parseOrDie("x:a%21b%3ac~").body(), "a!b:c~");
60  EXPECT_EQ(parseOrDie("x:a:b%3bc").body(), "a:b;c");
61 }
62 
63 std::string resolveOrDie(const URI &U, llvm::StringRef HintPath = "") {
64  auto Path = URI::resolve(U, HintPath);
65  if (!Path)
66  llvm_unreachable(toString(Path.takeError()).c_str());
67  return *Path;
68 }
69 
70 TEST(URITest, Create) {
71 #ifdef _WIN32
72  EXPECT_THAT(createOrDie("c:\\x\\y\\z"), "file:///c:/x/y/z");
73 #else
74  EXPECT_THAT(createOrDie("/x/y/z"), "file:///x/y/z");
75  EXPECT_THAT(createOrDie("/(x)/y/\\ z"), "file:///%28x%29/y/%5C%20z");
76 #endif
77 }
78 
79 TEST(URITest, FailedCreate) {
80  EXPECT_ERROR(URI::create("/x/y/z", "no"));
81  // Path has to be absolute.
82  EXPECT_ERROR(URI::create("x/y/z", "file"));
83 }
84 
85 TEST(URITest, Parse) {
86  EXPECT_THAT(parseOrDie("file://auth/x/y/z"),
87  AllOf(Scheme("file"), Authority("auth"), Body("/x/y/z")));
88 
89  EXPECT_THAT(parseOrDie("file://au%3dth/%28x%29/y/%5c%20z"),
90  AllOf(Scheme("file"), Authority("au=th"), Body("/(x)/y/\\ z")));
91 
92  EXPECT_THAT(parseOrDie("file:///%28x%29/y/%5c%20z"),
93  AllOf(Scheme("file"), Authority(""), Body("/(x)/y/\\ z")));
94  EXPECT_THAT(parseOrDie("file:///x/y/z"),
95  AllOf(Scheme("file"), Authority(""), Body("/x/y/z")));
96  EXPECT_THAT(parseOrDie("file:"),
97  AllOf(Scheme("file"), Authority(""), Body("")));
98  EXPECT_THAT(parseOrDie("file:///x/y/z%2"),
99  AllOf(Scheme("file"), Authority(""), Body("/x/y/z%2")));
100  EXPECT_THAT(parseOrDie("http://llvm.org"),
101  AllOf(Scheme("http"), Authority("llvm.org"), Body("")));
102  EXPECT_THAT(parseOrDie("http://llvm.org/"),
103  AllOf(Scheme("http"), Authority("llvm.org"), Body("/")));
104  EXPECT_THAT(parseOrDie("http://llvm.org/D"),
105  AllOf(Scheme("http"), Authority("llvm.org"), Body("/D")));
106  EXPECT_THAT(parseOrDie("http:/"),
107  AllOf(Scheme("http"), Authority(""), Body("/")));
108  EXPECT_THAT(parseOrDie("urn:isbn:0451450523"),
109  AllOf(Scheme("urn"), Authority(""), Body("isbn:0451450523")));
110  EXPECT_THAT(
111  parseOrDie("file:///c:/windows/system32/"),
112  AllOf(Scheme("file"), Authority(""), Body("/c:/windows/system32/")));
113 }
114 
115 TEST(URITest, ParseFailed) {
116  // Expect ':' in URI.
117  EXPECT_ERROR(URI::parse("file//x/y/z"));
118  // Empty.
120  EXPECT_ERROR(URI::parse(":/a/b/c"));
121  EXPECT_ERROR(URI::parse("\"/a/b/c\" IWYU pragma: abc"));
122 }
123 
124 TEST(URITest, Resolve) {
125 #ifdef _WIN32
126  EXPECT_THAT(resolveOrDie(parseOrDie("file:///c%3a/x/y/z")), "c:\\x\\y\\z");
127  EXPECT_THAT(resolveOrDie(parseOrDie("file:///c:/x/y/z")), "c:\\x\\y\\z");
128 #else
129  EXPECT_EQ(resolveOrDie(parseOrDie("file:/a/b/c")), "/a/b/c");
130  EXPECT_EQ(resolveOrDie(parseOrDie("file://auth/a/b/c")), "/a/b/c");
131  EXPECT_THAT(resolveOrDie(parseOrDie("file://au%3dth/%28x%29/y/%20z")),
132  "/(x)/y/ z");
133  EXPECT_THAT(resolveOrDie(parseOrDie("file:///c:/x/y/z")), "c:/x/y/z");
134 #endif
135  EXPECT_EQ(resolveOrDie(parseOrDie("unittest:///a"), testPath("x")),
136  testPath("a"));
137 }
138 
139 std::string resolvePathOrDie(llvm::StringRef AbsPath,
140  llvm::StringRef HintPath = "") {
141  auto Path = URI::resolvePath(AbsPath, HintPath);
142  if (!Path)
143  llvm_unreachable(toString(Path.takeError()).c_str());
144  return *Path;
145 }
146 
147 TEST(URITest, ResolvePath) {
148  StringRef FilePath =
149 #ifdef _WIN32
150  "c:\\x\\y\\z";
151 #else
152  "/a/b/c";
153 #endif
154  EXPECT_EQ(resolvePathOrDie(FilePath), FilePath);
155  EXPECT_EQ(resolvePathOrDie(testPath("x"), testPath("hint")), testPath("x"));
156  // HintPath is not in testRoot(); resolution fails.
157  auto Resolve = URI::resolvePath(testPath("x"), FilePath);
158  EXPECT_FALSE(Resolve);
159  llvm::consumeError(Resolve.takeError());
160 }
161 
162 TEST(URITest, Platform) {
163  auto Path = testPath("x");
164  auto U = URI::create(Path, "file");
165  EXPECT_TRUE(static_cast<bool>(U));
166  EXPECT_THAT(resolveOrDie(*U), Path);
167 }
168 
169 TEST(URITest, ResolveFailed) {
170  auto FailedResolve = [](StringRef Uri) {
171  auto Path = URI::resolve(parseOrDie(Uri));
172  if (!Path) {
173  consumeError(Path.takeError());
174  return true;
175  }
176  return false;
177  };
178 
179  // Invalid scheme.
180  EXPECT_TRUE(FailedResolve("no:/a/b/c"));
181  // File path needs to be absolute.
182  EXPECT_TRUE(FailedResolve("file:a/b/c"));
183 }
184 
185 } // namespace
186 } // namespace clangd
187 } // namespace clang
MATCHER_P(Named, N, "")
static int LLVM_ATTRIBUTE_UNUSED UnittestSchemeAnchorDest
#define EXPECT_ERROR(expectedValue)
TEST(BackgroundQueueTest, Priority)
std::string testPath(PathRef File)
Definition: TestFS.cpp:82
static llvm::Expected< std::string > resolvePath(llvm::StringRef AbsPath, llvm::StringRef HintPath="")
Resolves AbsPath into a canonical path of its URI, by converting AbsPath to URI and resolving the URI...
Definition: URI.cpp:241
static const char * toString(OffsetEncoding OE)
Definition: Protocol.cpp:1030
std::string Path
A typedef to represent a file path.
Definition: Path.h:20
volatile int UnittestSchemeAnchorSource
Definition: TestFS.cpp:132
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
Definition: URI.cpp:197
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
A URI describes the location of a source file.
Definition: URI.h:28
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
Definition: URI.cpp:233
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
Definition: URI.cpp:164