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:
FixItDiag(llvm::StringRef msg,bool has_fixits)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) {}
HasFixIts() const25   bool HasFixIts() const override { return m_has_fixits; }
26 };
27 } // namespace
28 
29 namespace {
30 class TextDiag : public Diagnostic {
31 public:
TextDiag(llvm::StringRef msg,DiagnosticSeverity severity)32   TextDiag(llvm::StringRef msg, DiagnosticSeverity severity)
33       : Diagnostic(msg, severity, DiagnosticOrigin::eDiagnosticOriginLLDB,
34                    custom_diag_id) {}
35 };
36 } // namespace
37 
TEST(DiagnosticManagerTest,AddDiagnostic)38 TEST(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>(msg, severity, origin, custom_diag_id);
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 
TEST(DiagnosticManagerTest,HasFixits)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 
TEST(DiagnosticManagerTest,GetStringNoDiags)75 TEST(DiagnosticManagerTest, GetStringNoDiags) {
76   DiagnosticManager mgr;
77   EXPECT_EQ("", mgr.GetString());
78 }
79 
TEST(DiagnosticManagerTest,GetStringBasic)80 TEST(DiagnosticManagerTest, GetStringBasic) {
81   DiagnosticManager mgr;
82   mgr.AddDiagnostic(
83       std::make_unique<TextDiag>("abc", eDiagnosticSeverityError));
84   EXPECT_EQ("error: abc\n", mgr.GetString());
85 }
86 
TEST(DiagnosticManagerTest,GetStringMultiline)87 TEST(DiagnosticManagerTest, GetStringMultiline) {
88   DiagnosticManager mgr;
89 
90   // Multiline diagnostics should only get one severity label.
91   mgr.AddDiagnostic(
92       std::make_unique<TextDiag>("b\nc", eDiagnosticSeverityError));
93   EXPECT_EQ("error: b\nc\n", mgr.GetString());
94 }
95 
TEST(DiagnosticManagerTest,GetStringMultipleDiags)96 TEST(DiagnosticManagerTest, GetStringMultipleDiags) {
97   DiagnosticManager mgr;
98   mgr.AddDiagnostic(
99       std::make_unique<TextDiag>("abc", eDiagnosticSeverityError));
100   EXPECT_EQ("error: abc\n", mgr.GetString());
101   mgr.AddDiagnostic(
102       std::make_unique<TextDiag>("def", eDiagnosticSeverityError));
103   EXPECT_EQ("error: abc\nerror: def\n", mgr.GetString());
104 }
105 
TEST(DiagnosticManagerTest,GetStringSeverityLabels)106 TEST(DiagnosticManagerTest, GetStringSeverityLabels) {
107   DiagnosticManager mgr;
108 
109   // Different severities should cause different labels.
110   mgr.AddDiagnostic(
111       std::make_unique<TextDiag>("foo", eDiagnosticSeverityError));
112   mgr.AddDiagnostic(
113       std::make_unique<TextDiag>("bar", eDiagnosticSeverityWarning));
114   // Remarks have no labels.
115   mgr.AddDiagnostic(
116       std::make_unique<TextDiag>("baz", eDiagnosticSeverityRemark));
117   EXPECT_EQ("error: foo\nwarning: bar\nbaz\n", mgr.GetString());
118 }
119 
TEST(DiagnosticManagerTest,GetStringPreserveOrder)120 TEST(DiagnosticManagerTest, GetStringPreserveOrder) {
121   DiagnosticManager mgr;
122 
123   // Make sure we preserve the diagnostic order and do not sort them in any way.
124   mgr.AddDiagnostic(
125       std::make_unique<TextDiag>("baz", eDiagnosticSeverityRemark));
126   mgr.AddDiagnostic(
127       std::make_unique<TextDiag>("bar", eDiagnosticSeverityWarning));
128   mgr.AddDiagnostic(
129       std::make_unique<TextDiag>("foo", eDiagnosticSeverityError));
130   EXPECT_EQ("baz\nwarning: bar\nerror: foo\n", mgr.GetString());
131 }
132 
TEST(DiagnosticManagerTest,AppendMessageNoDiag)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 
TEST(DiagnosticManagerTest,AppendMessageAttachToLastDiag)141 TEST(DiagnosticManagerTest, AppendMessageAttachToLastDiag) {
142   DiagnosticManager mgr;
143 
144   mgr.AddDiagnostic(
145       std::make_unique<TextDiag>("foo", eDiagnosticSeverityError));
146   mgr.AddDiagnostic(
147       std::make_unique<TextDiag>("bar", eDiagnosticSeverityError));
148   // This should append to 'bar' and not to 'foo'.
149   mgr.AppendMessageToDiagnostic("message text");
150 
151   EXPECT_EQ("error: foo\nerror: bar\nmessage text\n", mgr.GetString());
152 }
153 
TEST(DiagnosticManagerTest,AppendMessageSubsequentDiags)154 TEST(DiagnosticManagerTest, AppendMessageSubsequentDiags) {
155   DiagnosticManager mgr;
156 
157   mgr.AddDiagnostic(
158       std::make_unique<TextDiag>("bar", eDiagnosticSeverityError));
159   mgr.AppendMessageToDiagnostic("message text");
160   // Pushing another diag after the message should work fine.
161   mgr.AddDiagnostic(
162       std::make_unique<TextDiag>("foo", eDiagnosticSeverityError));
163 
164   EXPECT_EQ("error: bar\nmessage text\nerror: foo\n", mgr.GetString());
165 }
166 
TEST(DiagnosticManagerTest,PutString)167 TEST(DiagnosticManagerTest, PutString) {
168   DiagnosticManager mgr;
169 
170   mgr.PutString(eDiagnosticSeverityError, "foo");
171   EXPECT_EQ(1U, mgr.Diagnostics().size());
172   EXPECT_EQ(eDiagnosticOriginLLDB, mgr.Diagnostics().front()->getKind());
173   EXPECT_EQ("error: foo\n", mgr.GetString());
174 }
175 
TEST(DiagnosticManagerTest,PutStringMultiple)176 TEST(DiagnosticManagerTest, PutStringMultiple) {
177   DiagnosticManager mgr;
178 
179   // Multiple PutString should behave like multiple diagnostics.
180   mgr.PutString(eDiagnosticSeverityError, "foo");
181   mgr.PutString(eDiagnosticSeverityError, "bar");
182   EXPECT_EQ(2U, mgr.Diagnostics().size());
183   EXPECT_EQ("error: foo\nerror: bar\n", mgr.GetString());
184 }
185 
TEST(DiagnosticManagerTest,PutStringSeverities)186 TEST(DiagnosticManagerTest, PutStringSeverities) {
187   DiagnosticManager mgr;
188 
189   // Multiple PutString with different severities should behave like we
190   // created multiple diagnostics.
191   mgr.PutString(eDiagnosticSeverityError, "foo");
192   mgr.PutString(eDiagnosticSeverityWarning, "bar");
193   EXPECT_EQ(2U, mgr.Diagnostics().size());
194   EXPECT_EQ("error: foo\nwarning: bar\n", mgr.GetString());
195 }
196 
TEST(DiagnosticManagerTest,FixedExpression)197 TEST(DiagnosticManagerTest, FixedExpression) {
198   DiagnosticManager mgr;
199 
200   // By default there should be no fixed expression.
201   EXPECT_EQ("", mgr.GetFixedExpression());
202 
203   // Setting the fixed expression should change it.
204   mgr.SetFixedExpression("foo");
205   EXPECT_EQ("foo", mgr.GetFixedExpression());
206 
207   // Setting the fixed expression again should also change it.
208   mgr.SetFixedExpression("bar");
209   EXPECT_EQ("bar", mgr.GetFixedExpression());
210 }
211