1//===-- DiagnosticManagerTest.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 "lldb/Expression/DiagnosticManager.h"
10#include "gtest/gtest.h"
11
12using namespace lldb_private;
13
14static const uint32_t custom_diag_id = 42;
15
16namespace {
17class FixItDiag : public Diagnostic {
18 bool m_has_fixits;
19
20public:
21 FixItDiag(llvm::StringRef msg, bool has_fixits)
22 : Diagnostic(msg, DiagnosticSeverity::eDiagnosticSeverityError,
23 DiagnosticOrigin::eDiagnosticOriginLLDB, custom_diag_id),
24 m_has_fixits(has_fixits) {}
25 bool HasFixIts() const override { return m_has_fixits; }
26};
27} // namespace
28
29namespace {
30class TextDiag : public Diagnostic {
31public:
32 TextDiag(llvm::StringRef msg, DiagnosticSeverity severity)
33 : Diagnostic(msg, severity, DiagnosticOrigin::eDiagnosticOriginLLDB,
34 custom_diag_id) {}
35};
36} // namespace
37
38TEST(DiagnosticManagerTest, AddDiagnostic) {
39 DiagnosticManager mgr;
40 EXPECT_EQ(0U, mgr.Diagnostics().size());
41
42 std::string msg = "foo bar has happened";
43 DiagnosticSeverity severity = DiagnosticSeverity::eDiagnosticSeverityError;
44 DiagnosticOrigin origin = DiagnosticOrigin::eDiagnosticOriginLLDB;
45 auto diag =
46 std::make_unique<Diagnostic>(args&: msg, args&: severity, args&: origin, args: custom_diag_id);
47 mgr.AddDiagnostic(diagnostic: std::move(diag));
48 EXPECT_EQ(1U, mgr.Diagnostics().size());
49 const Diagnostic *got = mgr.Diagnostics().front().get();
50 EXPECT_EQ(DiagnosticOrigin::eDiagnosticOriginLLDB, got->getKind());
51 EXPECT_EQ(msg, got->GetMessage());
52 EXPECT_EQ(severity, got->GetSeverity());
53 EXPECT_EQ(custom_diag_id, got->GetCompilerID());
54 EXPECT_EQ(false, got->HasFixIts());
55}
56
57TEST(DiagnosticManagerTest, HasFixits) {
58 DiagnosticManager mgr;
59 // By default we shouldn't have any fixits.
60 EXPECT_FALSE(mgr.HasFixIts());
61 // Adding a diag without fixits shouldn't make HasFixIts return true.
62 mgr.AddDiagnostic(diagnostic: std::make_unique<FixItDiag>(args: "no fixit", args: false));
63 EXPECT_FALSE(mgr.HasFixIts());
64 // Adding a diag with fixits will mark the manager as containing fixits.
65 mgr.AddDiagnostic(diagnostic: std::make_unique<FixItDiag>(args: "fixit", args: true));
66 EXPECT_TRUE(mgr.HasFixIts());
67 // Adding another diag without fixit shouldn't make it return false.
68 mgr.AddDiagnostic(diagnostic: std::make_unique<FixItDiag>(args: "no fixit", args: false));
69 EXPECT_TRUE(mgr.HasFixIts());
70 // Adding a diag with fixits. The manager should still return true.
71 mgr.AddDiagnostic(diagnostic: std::make_unique<FixItDiag>(args: "fixit", args: true));
72 EXPECT_TRUE(mgr.HasFixIts());
73}
74
75TEST(DiagnosticManagerTest, GetStringNoDiags) {
76 DiagnosticManager mgr;
77 EXPECT_EQ("", mgr.GetString());
78 std::unique_ptr<Diagnostic> empty;
79 mgr.AddDiagnostic(diagnostic: std::move(empty));
80 EXPECT_EQ("", mgr.GetString());
81}
82
83TEST(DiagnosticManagerTest, GetStringBasic) {
84 DiagnosticManager mgr;
85 mgr.AddDiagnostic(
86 diagnostic: std::make_unique<TextDiag>(args: "abc", args: eDiagnosticSeverityError));
87 EXPECT_EQ("error: abc\n", mgr.GetString());
88}
89
90TEST(DiagnosticManagerTest, GetStringMultiline) {
91 DiagnosticManager mgr;
92
93 // Multiline diagnostics should only get one severity label.
94 mgr.AddDiagnostic(
95 diagnostic: std::make_unique<TextDiag>(args: "b\nc", args: eDiagnosticSeverityError));
96 EXPECT_EQ("error: b\nc\n", mgr.GetString());
97}
98
99TEST(DiagnosticManagerTest, GetStringMultipleDiags) {
100 DiagnosticManager mgr;
101 mgr.AddDiagnostic(
102 diagnostic: std::make_unique<TextDiag>(args: "abc", args: eDiagnosticSeverityError));
103 EXPECT_EQ("error: abc\n", mgr.GetString());
104 mgr.AddDiagnostic(
105 diagnostic: std::make_unique<TextDiag>(args: "def", args: eDiagnosticSeverityError));
106 EXPECT_EQ("error: abc\nerror: def\n", mgr.GetString());
107}
108
109TEST(DiagnosticManagerTest, GetStringSeverityLabels) {
110 DiagnosticManager mgr;
111
112 // Different severities should cause different labels.
113 mgr.AddDiagnostic(
114 diagnostic: std::make_unique<TextDiag>(args: "foo", args: eDiagnosticSeverityError));
115 mgr.AddDiagnostic(
116 diagnostic: std::make_unique<TextDiag>(args: "bar", args: eDiagnosticSeverityWarning));
117 // Remarks have no labels.
118 mgr.AddDiagnostic(
119 diagnostic: std::make_unique<TextDiag>(args: "baz", args: eDiagnosticSeverityRemark));
120 EXPECT_EQ("error: foo\nwarning: bar\nbaz\n", mgr.GetString());
121}
122
123TEST(DiagnosticManagerTest, GetStringPreserveOrder) {
124 DiagnosticManager mgr;
125
126 // Make sure we preserve the diagnostic order and do not sort them in any way.
127 mgr.AddDiagnostic(
128 diagnostic: std::make_unique<TextDiag>(args: "baz", args: eDiagnosticSeverityRemark));
129 mgr.AddDiagnostic(
130 diagnostic: std::make_unique<TextDiag>(args: "bar", args: eDiagnosticSeverityWarning));
131 mgr.AddDiagnostic(
132 diagnostic: std::make_unique<TextDiag>(args: "foo", args: eDiagnosticSeverityError));
133 EXPECT_EQ("baz\nwarning: bar\nerror: foo\n", mgr.GetString());
134}
135
136TEST(DiagnosticManagerTest, AppendMessageNoDiag) {
137 DiagnosticManager mgr;
138
139 // FIXME: This *really* should not just fail silently.
140 mgr.AppendMessageToDiagnostic(str: "no diag has been pushed yet");
141 EXPECT_EQ(0U, mgr.Diagnostics().size());
142}
143
144TEST(DiagnosticManagerTest, AppendMessageAttachToLastDiag) {
145 DiagnosticManager mgr;
146
147 mgr.AddDiagnostic(
148 diagnostic: std::make_unique<TextDiag>(args: "foo", args: eDiagnosticSeverityError));
149 mgr.AddDiagnostic(
150 diagnostic: std::make_unique<TextDiag>(args: "bar", args: eDiagnosticSeverityError));
151 // This should append to 'bar' and not to 'foo'.
152 mgr.AppendMessageToDiagnostic(str: "message text");
153
154 EXPECT_EQ("error: foo\nerror: bar\nmessage text\n", mgr.GetString());
155}
156
157TEST(DiagnosticManagerTest, AppendMessageSubsequentDiags) {
158 DiagnosticManager mgr;
159
160 mgr.AddDiagnostic(
161 diagnostic: std::make_unique<TextDiag>(args: "bar", args: eDiagnosticSeverityError));
162 mgr.AppendMessageToDiagnostic(str: "message text");
163 // Pushing another diag after the message should work fine.
164 mgr.AddDiagnostic(
165 diagnostic: std::make_unique<TextDiag>(args: "foo", args: eDiagnosticSeverityError));
166
167 EXPECT_EQ("error: bar\nmessage text\nerror: foo\n", mgr.GetString());
168}
169
170TEST(DiagnosticManagerTest, PutString) {
171 DiagnosticManager mgr;
172
173 mgr.PutString(severity: eDiagnosticSeverityError, str: "foo");
174 EXPECT_EQ(1U, mgr.Diagnostics().size());
175 EXPECT_EQ(eDiagnosticOriginLLDB, mgr.Diagnostics().front()->getKind());
176 EXPECT_EQ("error: foo\n", mgr.GetString());
177}
178
179TEST(DiagnosticManagerTest, PutStringMultiple) {
180 DiagnosticManager mgr;
181
182 // Multiple PutString should behave like multiple diagnostics.
183 mgr.PutString(severity: eDiagnosticSeverityError, str: "foo");
184 mgr.PutString(severity: eDiagnosticSeverityError, str: "bar");
185 EXPECT_EQ(2U, mgr.Diagnostics().size());
186 EXPECT_EQ("error: foo\nerror: bar\n", mgr.GetString());
187}
188
189TEST(DiagnosticManagerTest, PutStringSeverities) {
190 DiagnosticManager mgr;
191
192 // Multiple PutString with different severities should behave like we
193 // created multiple diagnostics.
194 mgr.PutString(severity: eDiagnosticSeverityError, str: "foo");
195 mgr.PutString(severity: eDiagnosticSeverityWarning, str: "bar");
196 EXPECT_EQ(2U, mgr.Diagnostics().size());
197 EXPECT_EQ("error: foo\nwarning: bar\n", mgr.GetString());
198}
199
200TEST(DiagnosticManagerTest, FixedExpression) {
201 DiagnosticManager mgr;
202
203 // By default there should be no fixed expression.
204 EXPECT_EQ("", mgr.GetFixedExpression());
205
206 // Setting the fixed expression should change it.
207 mgr.SetFixedExpression("foo");
208 EXPECT_EQ("foo", mgr.GetFixedExpression());
209
210 // Setting the fixed expression again should also change it.
211 mgr.SetFixedExpression("bar");
212 EXPECT_EQ("bar", mgr.GetFixedExpression());
213}
214

source code of lldb/unittests/Expression/DiagnosticManagerTest.cpp