1
2 //===- unittest/DebugInfo/Symbolizer/MarkupTest.cpp - Markup parser tests -===//
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 "llvm/DebugInfo/Symbolize/Markup.h"
11
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/Support/FormatVariadic.h"
14
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17
18 namespace {
19
20 using namespace llvm;
21 using namespace llvm::symbolize;
22 using namespace testing;
23
isNode(StringRef Text,StringRef Tag="",Matcher<SmallVector<StringRef>> Fields=IsEmpty ())24 Matcher<MarkupNode> isNode(StringRef Text, StringRef Tag = "",
25 Matcher<SmallVector<StringRef>> Fields = IsEmpty()) {
26 return AllOf(Field("Text", &MarkupNode::Text, Text),
27 Field("Tag", &MarkupNode::Tag, Tag),
28 Field("Fields", &MarkupNode::Fields, Fields));
29 }
30
TEST(SymbolizerMarkup,NoLines)31 TEST(SymbolizerMarkup, NoLines) {
32 EXPECT_EQ(MarkupParser{}.nextNode(), std::nullopt);
33 }
34
TEST(SymbolizerMarkup,LinesWithoutMarkup)35 TEST(SymbolizerMarkup, LinesWithoutMarkup) {
36 MarkupParser Parser;
37
38 Parser.parseLine("text");
39 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("text")));
40 EXPECT_THAT(Parser.nextNode(), std::nullopt);
41
42 Parser.parseLine("discarded");
43 Parser.parseLine("kept");
44 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("kept")));
45 EXPECT_THAT(Parser.nextNode(), std::nullopt);
46
47 Parser.parseLine("text\n");
48 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("text\n")));
49 EXPECT_THAT(Parser.nextNode(), std::nullopt);
50
51 Parser.parseLine("text\r\n");
52 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("text\r\n")));
53 EXPECT_THAT(Parser.nextNode(), std::nullopt);
54
55 Parser.parseLine("{{{");
56 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{")));
57 EXPECT_THAT(Parser.nextNode(), std::nullopt);
58
59 Parser.parseLine("{{{}}");
60 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{}}")));
61 EXPECT_THAT(Parser.nextNode(), std::nullopt);
62
63 Parser.parseLine("{{}}}");
64 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{}}}")));
65 EXPECT_THAT(Parser.nextNode(), std::nullopt);
66
67 Parser.parseLine("{{{}}}");
68 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{}}}")));
69 EXPECT_THAT(Parser.nextNode(), std::nullopt);
70
71 Parser.parseLine("{{{:field}}}");
72 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{:field}}}")));
73 EXPECT_THAT(Parser.nextNode(), std::nullopt);
74
75 Parser.parseLine("{{{tag:");
76 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag:")));
77 EXPECT_THAT(Parser.nextNode(), std::nullopt);
78
79 Parser.parseLine("{{{tag:field}}");
80 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag:field}}")));
81 EXPECT_THAT(Parser.nextNode(), std::nullopt);
82
83 Parser.parseLine("a\033[2mb");
84 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("a\033[2mb")));
85 EXPECT_THAT(Parser.nextNode(), std::nullopt);
86
87 Parser.parseLine("a\033[38mb");
88 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("a\033[38mb")));
89 EXPECT_THAT(Parser.nextNode(), std::nullopt);
90
91 Parser.parseLine("a\033[4mb");
92 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("a\033[4mb")));
93 EXPECT_THAT(Parser.nextNode(), std::nullopt);
94 }
95
TEST(SymbolizerMarkup,LinesWithMarkup)96 TEST(SymbolizerMarkup, LinesWithMarkup) {
97 MarkupParser Parser;
98
99 Parser.parseLine("{{{tag}}}");
100 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag}}}", "tag")));
101 EXPECT_THAT(Parser.nextNode(), std::nullopt);
102
103 Parser.parseLine("{{{tag:f1:f2:f3}}}");
104 EXPECT_THAT(Parser.nextNode(),
105 testing::Optional(isNode("{{{tag:f1:f2:f3}}}", "tag",
106 ElementsAre("f1", "f2", "f3"))));
107 EXPECT_THAT(Parser.nextNode(), std::nullopt);
108
109 Parser.parseLine("{{{tag:}}}");
110 EXPECT_THAT(Parser.nextNode(),
111 testing::Optional(isNode("{{{tag:}}}", "tag", ElementsAre(""))));
112 EXPECT_THAT(Parser.nextNode(), std::nullopt);
113
114 Parser.parseLine("{{{tag:}}");
115 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag:}}")));
116 EXPECT_THAT(Parser.nextNode(), std::nullopt);
117
118 Parser.parseLine("{{{t2g}}}");
119 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{t2g}}}", "t2g")));
120 EXPECT_THAT(Parser.nextNode(), std::nullopt);
121
122 Parser.parseLine("{{{tAg}}}");
123 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tAg}}}", "tAg")));
124 EXPECT_THAT(Parser.nextNode(), std::nullopt);
125
126 Parser.parseLine("a{{{b}}}c{{{d}}}e");
127 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("a")));
128 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{b}}}", "b")));
129 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("c")));
130 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{d}}}", "d")));
131 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("e")));
132 EXPECT_THAT(Parser.nextNode(), std::nullopt);
133
134 Parser.parseLine("{{{}}}{{{tag}}}");
135 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{}}}")));
136 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag}}}", "tag")));
137 EXPECT_THAT(Parser.nextNode(), std::nullopt);
138
139 Parser.parseLine("\033[0mA\033[1mB\033[30mC\033[37m");
140 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\033[0m")));
141 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("A")));
142 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\033[1m")));
143 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("B")));
144 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\033[30m")));
145 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("C")));
146 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\033[37m")));
147 EXPECT_THAT(Parser.nextNode(), std::nullopt);
148
149 Parser.parseLine("{{{tag:\033[0m}}}");
150 EXPECT_THAT(Parser.nextNode(),
151 testing::Optional(
152 isNode("{{{tag:\033[0m}}}", "tag", ElementsAre("\033[0m"))));
153 EXPECT_THAT(Parser.nextNode(), std::nullopt);
154 }
155
TEST(SymbolizerMarkup,MultilineElements)156 TEST(SymbolizerMarkup, MultilineElements) {
157 MarkupParser Parser(/*MultilineTags=*/{"first", "second"});
158
159 Parser.parseLine("{{{tag:");
160 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag:")));
161 EXPECT_THAT(Parser.nextNode(), std::nullopt);
162
163 Parser.parseLine("{{{first:");
164 EXPECT_THAT(Parser.nextNode(), std::nullopt);
165 Parser.parseLine("}}}{{{second:");
166 EXPECT_THAT(
167 Parser.nextNode(),
168 testing::Optional(isNode("{{{first:}}}", "first", ElementsAre(""))));
169 EXPECT_THAT(Parser.nextNode(), std::nullopt);
170 Parser.parseLine("}}}");
171 EXPECT_THAT(
172 Parser.nextNode(),
173 testing::Optional(isNode("{{{second:}}}", "second", ElementsAre(""))));
174 EXPECT_THAT(Parser.nextNode(), std::nullopt);
175
176 Parser.parseLine("{{{before{{{first:");
177 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{before")));
178 EXPECT_THAT(Parser.nextNode(), std::nullopt);
179 Parser.parseLine("line");
180 EXPECT_THAT(Parser.nextNode(), std::nullopt);
181 Parser.parseLine("}}}after");
182 EXPECT_THAT(Parser.nextNode(),
183 testing::Optional(
184 isNode("{{{first:line}}}", "first", ElementsAre("line"))));
185 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("after")));
186 EXPECT_THAT(Parser.nextNode(), std::nullopt);
187
188 Parser.parseLine("{{{first:");
189 EXPECT_THAT(Parser.nextNode(), std::nullopt);
190 Parser.flush();
191 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{first:")));
192 EXPECT_THAT(Parser.nextNode(), std::nullopt);
193
194 Parser.parseLine("{{{first:\n");
195 EXPECT_THAT(Parser.nextNode(), std::nullopt);
196 Parser.parseLine("}}}\n");
197 EXPECT_THAT(
198 Parser.nextNode(),
199 testing::Optional(isNode("{{{first:\n}}}", "first", ElementsAre("\n"))));
200 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\n")));
201 EXPECT_THAT(Parser.nextNode(), std::nullopt);
202
203 Parser.parseLine("{{{first:\r\n");
204 EXPECT_THAT(Parser.nextNode(), std::nullopt);
205 Parser.parseLine("}}}\r\n");
206 EXPECT_THAT(Parser.nextNode(),
207 testing::Optional(
208 isNode("{{{first:\r\n}}}", "first", ElementsAre("\r\n"))));
209 EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\r\n")));
210 EXPECT_THAT(Parser.nextNode(), std::nullopt);
211
212 Parser.parseLine("{{{first:");
213 EXPECT_THAT(Parser.nextNode(), std::nullopt);
214 Parser.parseLine("\033[0m}}}");
215 EXPECT_THAT(Parser.nextNode(),
216 testing::Optional(isNode("{{{first:\033[0m}}}", "first",
217 ElementsAre("\033[0m"))));
218 EXPECT_THAT(Parser.nextNode(), std::nullopt);
219 }
220
221 } // namespace
222