clang-tools  14.0.0git
ConfigYAMLTests.cpp
Go to the documentation of this file.
1 //===-- ConfigYAMLTests.cpp -----------------------------------------------===//
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 "Annotations.h"
10 #include "ConfigFragment.h"
11 #include "ConfigTesting.h"
12 #include "Protocol.h"
13 #include "llvm/ADT/None.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/SMLoc.h"
16 #include "llvm/Support/ScopedPrinter.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "llvm/Testing/Support/SupportHelpers.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 
22 namespace clang {
23 namespace clangd {
24 namespace config {
25 template <typename T> void PrintTo(const Located<T> &V, std::ostream *OS) {
26  *OS << ::testing::PrintToString(*V);
27 }
28 
29 namespace {
30 using ::testing::AllOf;
31 using ::testing::ElementsAre;
32 using ::testing::IsEmpty;
33 
34 MATCHER_P(Val, Value, "") {
35  if (*arg == Value)
36  return true;
37  *result_listener << "value is " << *arg;
38  return false;
39 }
40 
41 MATCHER_P2(PairVal, Value1, Value2, "") {
42  if (*arg.first == Value1 && *arg.second == Value2)
43  return true;
44  *result_listener << "values are [" << *arg.first << ", " << *arg.second
45  << "]";
46  return false;
47 }
48 
49 TEST(ParseYAML, SyntacticForms) {
50  CapturedDiags Diags;
51  const char *YAML = R"yaml(
52 If:
53  PathMatch:
54  - 'abc'
55 CompileFlags: { Add: [foo, bar] }
56 ---
57 CompileFlags:
58  Add: |
59  b
60  az
61 ---
62 Index:
63  Background: Skip
64 ---
65 Diagnostics:
66  ClangTidy:
67  CheckOptions:
68  IgnoreMacros: true
69  example-check.ExampleOption: 0
70  UnusedIncludes: Strict
71  )yaml";
72  auto Results = Fragment::parseYAML(YAML, "config.yaml", Diags.callback());
73  EXPECT_THAT(Diags.Diagnostics, IsEmpty());
74  EXPECT_THAT(Diags.Files, ElementsAre("config.yaml"));
75  ASSERT_EQ(Results.size(), 4u);
76  EXPECT_FALSE(Results[0].If.HasUnrecognizedCondition);
77  EXPECT_THAT(Results[0].If.PathMatch, ElementsAre(Val("abc")));
78  EXPECT_THAT(Results[0].CompileFlags.Add, ElementsAre(Val("foo"), Val("bar")));
79 
80  EXPECT_THAT(Results[1].CompileFlags.Add, ElementsAre(Val("b\naz\n")));
81 
82  ASSERT_TRUE(Results[2].Index.Background);
83  EXPECT_EQ("Skip", *Results[2].Index.Background.getValue());
84  EXPECT_THAT(Results[3].Diagnostics.ClangTidy.CheckOptions,
85  ElementsAre(PairVal("IgnoreMacros", "true"),
86  PairVal("example-check.ExampleOption", "0")));
87  EXPECT_TRUE(Results[3].Diagnostics.UnusedIncludes);
88  EXPECT_EQ("Strict", *Results[3].Diagnostics.UnusedIncludes.getValue());
89 }
90 
91 TEST(ParseYAML, Locations) {
92  CapturedDiags Diags;
93  Annotations YAML(R"yaml(
94 If:
95  PathMatch: [['???bad***regex(((']]
96  )yaml");
97  auto Results =
98  Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
99  EXPECT_THAT(Diags.Diagnostics, IsEmpty());
100  ASSERT_EQ(Results.size(), 1u);
101  ASSERT_NE(Results.front().Source.Manager, nullptr);
102  EXPECT_EQ(toRange(Results.front().If.PathMatch.front().Range,
103  *Results.front().Source.Manager),
104  YAML.range());
105 }
106 
107 TEST(ParseYAML, ConfigDiagnostics) {
108  CapturedDiags Diags;
109  Annotations YAML(R"yaml(
110 If:
111  $unknown[[UnknownCondition]]: "foo"
112 CompileFlags:
113  Add: 'first'
114 ---
115 CompileFlags: {$unexpected^
116 )yaml");
117  auto Results =
118  Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
119 
120  ASSERT_THAT(
122  ElementsAre(AllOf(DiagMessage("Unknown If key 'UnknownCondition'"),
123  DiagKind(llvm::SourceMgr::DK_Warning),
124  DiagPos(YAML.range("unknown").start),
125  DiagRange(YAML.range("unknown"))),
126  AllOf(DiagMessage("Unexpected token. Expected Key, Flow "
127  "Entry, or Flow Mapping End."),
128  DiagKind(llvm::SourceMgr::DK_Error),
129  DiagPos(YAML.point("unexpected")),
130  DiagRange(llvm::None))));
131 
132  ASSERT_EQ(Results.size(), 1u); // invalid fragment discarded.
133  EXPECT_THAT(Results.front().CompileFlags.Add, ElementsAre(Val("first")));
134  EXPECT_TRUE(Results.front().If.HasUnrecognizedCondition);
135 }
136 
137 TEST(ParseYAML, Invalid) {
138  CapturedDiags Diags;
139  const char *YAML = R"yaml(
140 If:
141 
142 horrible
143 ---
144 - 1
145  )yaml";
146  auto Results = Fragment::parseYAML(YAML, "config.yaml", Diags.callback());
147  EXPECT_THAT(Diags.Diagnostics,
148  ElementsAre(DiagMessage("If should be a dictionary"),
149  DiagMessage("Config should be a dictionary")));
150  ASSERT_THAT(Results, IsEmpty());
151 }
152 
153 TEST(ParseYAML, ExternalBlockNone) {
154  CapturedDiags Diags;
155  Annotations YAML(R"yaml(
156 Index:
157  External: None
158  )yaml");
159  auto Results =
160  Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
161  ASSERT_THAT(Diags.Diagnostics, IsEmpty());
162  ASSERT_EQ(Results.size(), 1u);
163  ASSERT_TRUE(Results[0].Index.External);
164  EXPECT_FALSE(Results[0].Index.External.getValue()->File.hasValue());
165  EXPECT_FALSE(Results[0].Index.External.getValue()->MountPoint.hasValue());
166  EXPECT_FALSE(Results[0].Index.External.getValue()->Server.hasValue());
167  EXPECT_THAT(*Results[0].Index.External.getValue()->IsNone, testing::Eq(true));
168 }
169 
170 TEST(ParseYAML, ExternalBlock) {
171  CapturedDiags Diags;
172  Annotations YAML(R"yaml(
173 Index:
174  External:
175  File: "foo"
176  Server: ^"bar"
177  MountPoint: "baz"
178  )yaml");
179  auto Results =
180  Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
181  ASSERT_EQ(Results.size(), 1u);
182  ASSERT_TRUE(Results[0].Index.External);
183  EXPECT_THAT(*Results[0].Index.External.getValue()->File, Val("foo"));
184  EXPECT_THAT(*Results[0].Index.External.getValue()->MountPoint, Val("baz"));
185  ASSERT_THAT(Diags.Diagnostics, IsEmpty());
186  EXPECT_THAT(*Results[0].Index.External.getValue()->Server, Val("bar"));
187 }
188 
189 TEST(ParseYAML, AllScopes) {
190  CapturedDiags Diags;
191  Annotations YAML(R"yaml(
192 Completion:
193  AllScopes: True
194  )yaml");
195  auto Results =
196  Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
197  ASSERT_THAT(Diags.Diagnostics, IsEmpty());
198  ASSERT_EQ(Results.size(), 1u);
199  EXPECT_THAT(Results[0].Completion.AllScopes, llvm::ValueIs(Val(true)));
200 }
201 
202 TEST(ParseYAML, AllScopesWarn) {
203  CapturedDiags Diags;
204  Annotations YAML(R"yaml(
205 Completion:
206  AllScopes: $diagrange[[Truex]]
207  )yaml");
208  auto Results =
209  Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
210  EXPECT_THAT(Diags.Diagnostics,
211  ElementsAre(AllOf(DiagMessage("AllScopes should be a boolean"),
212  DiagKind(llvm::SourceMgr::DK_Warning),
213  DiagPos(YAML.range("diagrange").start),
214  DiagRange(YAML.range("diagrange")))));
215  ASSERT_EQ(Results.size(), 1u);
216  EXPECT_THAT(Results[0].Completion.AllScopes, testing::Eq(llvm::None));
217 }
218 } // namespace
219 } // namespace config
220 } // namespace clangd
221 } // namespace clang
clang::clangd::IndexFileFormat::YAML
@ YAML
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:751
clang::clangd::MATCHER_P2
MATCHER_P2(hasFlag, Flag, Path, "")
Definition: GlobalCompilationDatabaseTests.cpp:450
clang::clangd::config::Fragment::parseYAML
static std::vector< Fragment > parseYAML(llvm::StringRef YAML, llvm::StringRef BufferName, DiagnosticCallback)
Parses fragments from a YAML file (one from each — delimited document).
Definition: ConfigYAML.cpp:357
Diagnostics
WantDiagnostics Diagnostics
Definition: TUScheduler.cpp:567
clang::clangd::config::CapturedDiags::callback
std::function< void(const llvm::SMDiagnostic &)> callback()
Definition: ConfigTesting.h:25
clang::clangd::config::Located
An entity written in config along, with its optional location in the file.
Definition: ConfigFragment.h:49
Protocol.h
clang::clangd::config::MATCHER_P
MATCHER_P(DiagMessage, M, "")
Definition: ConfigTesting.h:68
ConfigTesting.h
Results
std::vector< CodeCompletionResult > Results
Definition: CodeComplete.cpp:765
Annotations.h
clang::clangd::config::CapturedDiags::Files
std::vector< std::string > Files
Definition: ConfigTesting.h:60
Index
const SymbolIndex * Index
Definition: Dexp.cpp:99
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
OS
llvm::raw_string_ostream OS
Definition: TraceTests.cpp:163
Diags
CapturedDiags Diags
Definition: ConfigCompileTests.cpp:38
clang::clangd::config::PrintTo
void PrintTo(const Located< T > &V, std::ostream *OS)
Definition: ConfigYAMLTests.cpp:25
clang::clangd::config::CapturedDiags::Diagnostics
std::vector< Diag > Diagnostics
Definition: ConfigTesting.h:59
clang::clangd::config::toRange
Range toRange(llvm::SMRange R, const llvm::SourceMgr &SM)
Definition: ConfigTesting.h:81
ConfigFragment.h