aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/DebugInfo/Symbolizer/MarkupTest.cpp
blob: a93d9deb2f2de67ba6fc50b5ca96c5e0e6a13b32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

//===- unittest/DebugInfo/Symbolizer/MarkupTest.cpp - Markup parser tests -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/Symbolize/Markup.h"

#include "llvm/ADT/Twine.h"
#include "llvm/Support/FormatVariadic.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace {

using namespace llvm;
using namespace llvm::symbolize;
using namespace testing;

Matcher<MarkupNode> isNode(StringRef Text, StringRef Tag = "",
                           Matcher<SmallVector<StringRef>> Fields = IsEmpty()) {
  return AllOf(Field("Text", &MarkupNode::Text, Text),
               Field("Tag", &MarkupNode::Tag, Tag),
               Field("Fields", &MarkupNode::Fields, Fields));
}

TEST(SymbolizerMarkup, NoLines) {
  EXPECT_EQ(MarkupParser{}.nextNode(), std::nullopt);
}

TEST(SymbolizerMarkup, LinesWithoutMarkup) {
  MarkupParser Parser;

  Parser.parseLine("text");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("text")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("discarded");
  Parser.parseLine("kept");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("kept")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("text\n");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("text\n")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("text\r\n");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("text\r\n")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{}}")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{}}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{}}}")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{}}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{}}}")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{:field}}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{:field}}}")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{tag:");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag:")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{tag:field}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag:field}}")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("a\033[2mb");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("a\033[2mb")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("a\033[38mb");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("a\033[38mb")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("a\033[4mb");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("a\033[4mb")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
}

TEST(SymbolizerMarkup, LinesWithMarkup) {
  MarkupParser Parser;

  Parser.parseLine("{{{tag}}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag}}}", "tag")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{tag:f1:f2:f3}}}");
  EXPECT_THAT(Parser.nextNode(),
              testing::Optional(isNode("{{{tag:f1:f2:f3}}}", "tag",
                                       ElementsAre("f1", "f2", "f3"))));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{tag:}}}");
  EXPECT_THAT(Parser.nextNode(),
              testing::Optional(isNode("{{{tag:}}}", "tag", ElementsAre(""))));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{tag:}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag:}}")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{t2g}}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{t2g}}}", "t2g")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{tAg}}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tAg}}}", "tAg")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("a{{{b}}}c{{{d}}}e");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("a")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{b}}}", "b")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("c")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{d}}}", "d")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("e")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{}}}{{{tag}}}");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{}}}")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag}}}", "tag")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("\033[0mA\033[1mB\033[30mC\033[37m");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\033[0m")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("A")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\033[1m")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("B")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\033[30m")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("C")));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\033[37m")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{tag:\033[0m}}}");
  EXPECT_THAT(Parser.nextNode(),
              testing::Optional(
                  isNode("{{{tag:\033[0m}}}", "tag", ElementsAre("\033[0m"))));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
}

TEST(SymbolizerMarkup, MultilineElements) {
  MarkupParser Parser(/*MultilineTags=*/{"first", "second"});

  Parser.parseLine("{{{tag:");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{tag:")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{first:");
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
  Parser.parseLine("}}}{{{second:");
  EXPECT_THAT(
      Parser.nextNode(),
      testing::Optional(isNode("{{{first:}}}", "first", ElementsAre(""))));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
  Parser.parseLine("}}}");
  EXPECT_THAT(
      Parser.nextNode(),
      testing::Optional(isNode("{{{second:}}}", "second", ElementsAre(""))));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{before{{{first:");
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{before")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
  Parser.parseLine("line");
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
  Parser.parseLine("}}}after");
  EXPECT_THAT(Parser.nextNode(),
              testing::Optional(
                  isNode("{{{first:line}}}", "first", ElementsAre("line"))));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("after")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{first:");
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
  Parser.flush();
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("{{{first:")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{first:\n");
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
  Parser.parseLine("}}}\n");
  EXPECT_THAT(
      Parser.nextNode(),
      testing::Optional(isNode("{{{first:\n}}}", "first", ElementsAre("\n"))));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\n")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{first:\r\n");
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
  Parser.parseLine("}}}\r\n");
  EXPECT_THAT(Parser.nextNode(),
              testing::Optional(
                  isNode("{{{first:\r\n}}}", "first", ElementsAre("\r\n"))));
  EXPECT_THAT(Parser.nextNode(), testing::Optional(isNode("\r\n")));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);

  Parser.parseLine("{{{first:");
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
  Parser.parseLine("\033[0m}}}");
  EXPECT_THAT(Parser.nextNode(),
              testing::Optional(isNode("{{{first:\033[0m}}}", "first",
                                       ElementsAre("\033[0m"))));
  EXPECT_THAT(Parser.nextNode(), std::nullopt);
}

} // namespace