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