blob: df11d74ca0f66f763c176962e73f0267066f7e72 [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001// Copyright 2020 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "src/tint/diagnostic/formatter.h"
16
17#include <utility>
18
19#include "gtest/gtest.h"
20#include "src/tint/diagnostic/diagnostic.h"
21
dan sinclair7bc9ba12022-04-07 17:22:26 +000022namespace tint::diag {
Ryan Harrisondbc13af2022-02-21 15:19:07 +000023namespace {
24
25Diagnostic Diag(Severity severity,
26 Source source,
27 std::string message,
28 System system,
29 const char* code = nullptr) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000030 Diagnostic d;
31 d.severity = severity;
32 d.source = source;
33 d.message = std::move(message);
34 d.system = system;
35 d.code = code;
36 return d;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000037}
38
39constexpr const char* ascii_content = // Note: words are tab-delimited
40 R"(the cat says meow
41the dog says woof
42the snake says quack
43the snail says ???
44)";
45
dan sinclair41e4d9a2022-05-01 14:40:55 +000046constexpr const char* utf8_content = // Note: words are tab-delimited
Ryan Harrisondbc13af2022-02-21 15:19:07 +000047 "the \xf0\x9f\x90\xb1 says meow\n" // NOLINT: tabs
48 "the \xf0\x9f\x90\x95 says woof\n" // NOLINT: tabs
49 "the \xf0\x9f\x90\x8d says quack\n" // NOLINT: tabs
50 "the \xf0\x9f\x90\x8c says ???\n"; // NOLINT: tabs
51
52class DiagFormatterTest : public testing::Test {
dan sinclair41e4d9a2022-05-01 14:40:55 +000053 public:
54 Source::File ascii_file{"file.name", ascii_content};
55 Source::File utf8_file{"file.name", utf8_content};
56 Diagnostic ascii_diag_note = Diag(Severity::Note,
57 Source{Source::Range{Source::Location{1, 14}}, &ascii_file},
58 "purr",
59 System::Test);
60 Diagnostic ascii_diag_warn = Diag(Severity::Warning,
61 Source{Source::Range{{2, 14}, {2, 18}}, &ascii_file},
62 "grrr",
63 System::Test);
64 Diagnostic ascii_diag_err = Diag(Severity::Error,
65 Source{Source::Range{{3, 16}, {3, 21}}, &ascii_file},
66 "hiss",
67 System::Test,
68 "abc123");
69 Diagnostic ascii_diag_ice = Diag(Severity::InternalCompilerError,
70 Source{Source::Range{{4, 16}, {4, 19}}, &ascii_file},
71 "unreachable",
72 System::Test);
73 Diagnostic ascii_diag_fatal = Diag(Severity::Fatal,
74 Source{Source::Range{{4, 16}, {4, 19}}, &ascii_file},
75 "nothing",
76 System::Test);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000077
dan sinclair41e4d9a2022-05-01 14:40:55 +000078 Diagnostic utf8_diag_note = Diag(Severity::Note,
79 Source{Source::Range{Source::Location{1, 15}}, &utf8_file},
80 "purr",
81 System::Test);
82 Diagnostic utf8_diag_warn = Diag(Severity::Warning,
83 Source{Source::Range{{2, 15}, {2, 19}}, &utf8_file},
84 "grrr",
85 System::Test);
86 Diagnostic utf8_diag_err = Diag(Severity::Error,
87 Source{Source::Range{{3, 15}, {3, 20}}, &utf8_file},
88 "hiss",
89 System::Test,
90 "abc123");
91 Diagnostic utf8_diag_ice = Diag(Severity::InternalCompilerError,
92 Source{Source::Range{{4, 15}, {4, 18}}, &utf8_file},
93 "unreachable",
94 System::Test);
95 Diagnostic utf8_diag_fatal = Diag(Severity::Fatal,
96 Source{Source::Range{{4, 15}, {4, 18}}, &utf8_file},
97 "nothing",
98 System::Test);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000099};
100
101TEST_F(DiagFormatterTest, Simple) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000102 Formatter fmt{{false, false, false, false}};
103 auto got = fmt.format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
104 auto* expect = R"(1:14: purr
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001052:14: grrr
1063:16 abc123: hiss)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000107 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000108}
109
110TEST_F(DiagFormatterTest, SimpleNewlineAtEnd) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000111 Formatter fmt{{false, false, false, true}};
112 auto got = fmt.format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
113 auto* expect = R"(1:14: purr
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001142:14: grrr
1153:16 abc123: hiss
116)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000117 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000118}
119
120TEST_F(DiagFormatterTest, SimpleNoSource) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000121 Formatter fmt{{false, false, false, false}};
122 auto diag = Diag(Severity::Note, Source{}, "no source!", System::Test);
123 auto got = fmt.format(List{diag});
124 auto* expect = "no source!";
125 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000126}
127
128TEST_F(DiagFormatterTest, WithFile) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000129 Formatter fmt{{true, false, false, false}};
130 auto got = fmt.format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
131 auto* expect = R"(file.name:1:14: purr
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000132file.name:2:14: grrr
133file.name:3:16 abc123: hiss)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000134 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000135}
136
137TEST_F(DiagFormatterTest, WithSeverity) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000138 Formatter fmt{{false, true, false, false}};
139 auto got = fmt.format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
140 auto* expect = R"(1:14 note: purr
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001412:14 warning: grrr
1423:16 error abc123: hiss)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000143 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000144}
145
146TEST_F(DiagFormatterTest, WithLine) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000147 Formatter fmt{{false, false, true, false}};
148 auto got = fmt.format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
149 auto* expect = R"(1:14: purr
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000150the cat says meow
151 ^
152
1532:14: grrr
154the dog says woof
155 ^^^^
156
1573:16 abc123: hiss
158the snake says quack
159 ^^^^^
160)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000161 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000162}
163
164TEST_F(DiagFormatterTest, UnicodeWithLine) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000165 Formatter fmt{{false, false, true, false}};
166 auto got = fmt.format(List{utf8_diag_note, utf8_diag_warn, utf8_diag_err});
167 auto* expect =
168 "1:15: purr\n"
169 "the \xf0\x9f\x90\xb1 says meow\n"
170 "\n"
171 "2:15: grrr\n"
172 "the \xf0\x9f\x90\x95 says woof\n"
173 "\n"
174 "3:15 abc123: hiss\n"
175 "the \xf0\x9f\x90\x8d says quack\n";
176 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000177}
178
179TEST_F(DiagFormatterTest, BasicWithFileSeverityLine) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000180 Formatter fmt{{true, true, true, false}};
181 auto got = fmt.format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
182 auto* expect = R"(file.name:1:14 note: purr
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000183the cat says meow
184 ^
185
186file.name:2:14 warning: grrr
187the dog says woof
188 ^^^^
189
190file.name:3:16 error abc123: hiss
191the snake says quack
192 ^^^^^
193)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000194 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000195}
196
197TEST_F(DiagFormatterTest, BasicWithMultiLine) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000198 auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &ascii_file},
199 "multiline", System::Test);
200 Formatter fmt{{false, false, true, false}};
201 auto got = fmt.format(List{multiline});
202 auto* expect = R"(2:9: multiline
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000203the dog says woof
204 ^^^^^^^^^^
205the snake says quack
206^^^^^^^^^^^^^^^^^^^^^^^
207the snail says ???
208^^^^^^^^^^^^^^^^
209)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000210 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000211}
212
213TEST_F(DiagFormatterTest, UnicodeWithMultiLine) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000214 auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &utf8_file},
215 "multiline", System::Test);
216 Formatter fmt{{false, false, true, false}};
217 auto got = fmt.format(List{multiline});
218 auto* expect =
219 "2:9: multiline\n"
220 "the \xf0\x9f\x90\x95 says woof\n"
221 "the \xf0\x9f\x90\x8d says quack\n"
222 "the \xf0\x9f\x90\x8c says ???\n";
223 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000224}
225
226TEST_F(DiagFormatterTest, BasicWithFileSeverityLineTab4) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000227 Formatter fmt{{true, true, true, false, 4u}};
228 auto got = fmt.format(List{ascii_diag_note, ascii_diag_warn, ascii_diag_err});
229 auto* expect = R"(file.name:1:14 note: purr
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000230the cat says meow
231 ^
232
233file.name:2:14 warning: grrr
234the dog says woof
235 ^^^^
236
237file.name:3:16 error abc123: hiss
238the snake says quack
239 ^^^^^
240)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000241 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000242}
243
244TEST_F(DiagFormatterTest, BasicWithMultiLineTab4) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000245 auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &ascii_file},
246 "multiline", System::Test);
247 Formatter fmt{{false, false, true, false, 4u}};
248 auto got = fmt.format(List{multiline});
249 auto* expect = R"(2:9: multiline
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000250the dog says woof
251 ^^^^^^^^^^^^
252the snake says quack
253^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
254the snail says ???
255^^^^^^^^^^^^^^^^^^^^
256)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000257 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000258}
259
260TEST_F(DiagFormatterTest, ICE) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000261 Formatter fmt{{}};
262 auto got = fmt.format(List{ascii_diag_ice});
263 auto* expect = R"(file.name:4:16 internal compiler error: unreachable
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000264the snail says ???
265 ^^^
266
267)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000268 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000269}
270
271TEST_F(DiagFormatterTest, Fatal) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000272 Formatter fmt{{}};
273 auto got = fmt.format(List{ascii_diag_fatal});
274 auto* expect = R"(file.name:4:16 fatal: nothing
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000275the snail says ???
276 ^^^
277
278)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000279 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000280}
281
282TEST_F(DiagFormatterTest, RangeOOB) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000283 Formatter fmt{{true, true, true, true}};
284 diag::List list;
285 list.add_error(System::Test, "oob", Source{{{10, 20}, {30, 20}}, &ascii_file});
286 auto got = fmt.format(list);
287 auto* expect = R"(file.name:10:20 error: oob
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000288
289)";
dan sinclair41e4d9a2022-05-01 14:40:55 +0000290 ASSERT_EQ(expect, got);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000291}
292
293} // namespace
dan sinclair7bc9ba12022-04-07 17:22:26 +0000294} // namespace tint::diag