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(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 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 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 TEST(DiagnosticManagerTest, GetStringNoDiags) { 76 DiagnosticManager mgr; 77 EXPECT_EQ("", mgr.GetString()); 78 } 79 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 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 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 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 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 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( 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 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 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 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 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 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