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