#include "lldb/Utility/DiagnosticsRendering.h" #include "lldb/Utility/StreamString.h" #include "gtest/gtest.h" using namespace lldb_private; using namespace lldb; using llvm::StringRef; namespace { class ErrorDisplayTest : public ::testing::Test {}; std::string Render(std::vector details) { StreamString stream; RenderDiagnosticDetails(stream, 0, true, details); return stream.GetData(); } } // namespace TEST_F(ErrorDisplayTest, RenderStatus) { using SourceLocation = DiagnosticDetail::SourceLocation; { SourceLocation inline_loc; inline_loc.in_user_input = true; std::string result = Render({DiagnosticDetail{inline_loc, eSeverityError, "foo", ""}}); ASSERT_TRUE(StringRef(result).contains("error:")); ASSERT_TRUE(StringRef(result).contains("foo")); } { // Test that diagnostics on the same column can be handled and all // three errors are diagnosed. SourceLocation loc1 = {FileSpec{"a.c"}, 13, 5, 0, false, true}; SourceLocation loc2 = {FileSpec{"a.c"}, 13, 7, 0, false, true}; SourceLocation loc3 = {FileSpec{"a.c"}, 13, 9, 0, false, true}; std::string result = Render({DiagnosticDetail{loc1, eSeverityError, "1", "1"}, DiagnosticDetail{loc2, eSeverityError, "2a", "2a"}, DiagnosticDetail{loc2, eSeverityInfo, "2b", "2b"}, DiagnosticDetail{loc3, eSeverityError, "3", "3"}}); llvm::SmallVector lines; StringRef(result).split(lines, '\n'); // 1234567890123 ASSERT_EQ(lines[0], " ^ ^ ^"); ASSERT_EQ(lines[1], " | | error: 3"); ASSERT_EQ(lines[2], " | error: 2a"); ASSERT_EQ(lines[3], " | note: 2b"); ASSERT_EQ(lines[4], " error: 1"); } { // Test that diagnostics in reverse order are emitted correctly. SourceLocation loc1 = {FileSpec{"a.c"}, 1, 20, 0, false, true}; SourceLocation loc2 = {FileSpec{"a.c"}, 2, 10, 0, false, true}; std::string result = Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"}, DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}}); // Unintuitively the later diagnostic appears first in the string: // ^ ^ // | second // first ASSERT_GT(StringRef(result).find("Y"), StringRef(result).find("X")); } { // Test that diagnostics in reverse order are emitted correctly. SourceLocation loc1 = {FileSpec{"a.c"}, 1, 10, 0, false, true}; SourceLocation loc2 = {FileSpec{"a.c"}, 1, 20, 0, false, true}; std::string result = Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"}, DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}}); ASSERT_GT(StringRef(result).find("Y"), StringRef(result).find("X")); } { // Test that range diagnostics are emitted correctly. SourceLocation loc1 = {FileSpec{"a.c"}, 1, 1, 3, false, true}; SourceLocation loc2 = {FileSpec{"a.c"}, 1, 5, 3, false, true}; std::string result = Render({DiagnosticDetail{loc1, eSeverityError, "X", "X"}, DiagnosticDetail{loc2, eSeverityError, "Y", "Y"}}); llvm::SmallVector lines; StringRef(result).split(lines, '\n'); // 1234567 ASSERT_EQ(lines[0], "^~~ ^~~"); ASSERT_EQ(lines[1], "| error: Y"); ASSERT_EQ(lines[2], "error: X"); } { // Test diagnostics on the same line are emitted correctly. SourceLocation loc1 = {FileSpec{"a.c"}, 1, 2, 0, false, true}; SourceLocation loc2 = {FileSpec{"a.c"}, 1, 6, 0, false, true}; std::string result = Render({DiagnosticDetail{loc1, eSeverityError, "X", "X"}, DiagnosticDetail{loc2, eSeverityError, "Y", "Y"}}); llvm::SmallVector lines; StringRef(result).split(lines, '\n'); // 1234567 ASSERT_EQ(lines[0], " ^ ^"); ASSERT_EQ(lines[1], " | error: Y"); ASSERT_EQ(lines[2], " error: X"); } }