sorting_consumer_test.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/diagnostics/sorting_consumer.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. #include "llvm/ADT/StringRef.h"
  8. #include "toolchain/diagnostics/emitter.h"
  9. #include "toolchain/diagnostics/mocks.h"
  10. namespace Carbon::Diagnostics {
  11. namespace {
  12. using ::Carbon::Testing::IsSingleDiagnostic;
  13. using ::testing::_;
  14. using ::testing::ElementsAreArray;
  15. CARBON_DIAGNOSTIC(TestDiagnostic, Error, "Diag{0}", int);
  16. CARBON_DIAGNOSTIC_ON_SCOPE(TestDiagnosticOnScope, Error, "DiagOnScope{0}", int);
  17. // Sorting-related locations, consumed by `FakeEmitter::ConvertLoc`.
  18. struct TestLoc {
  19. int32_t last_byte_offset;
  20. int32_t line_number;
  21. int32_t column_number;
  22. };
  23. // Emits a diagnostic with the requested location.
  24. class FakeEmitter : public Emitter<TestLoc> {
  25. public:
  26. using Emitter::Emitter;
  27. protected:
  28. auto ConvertLoc(TestLoc test_loc, ContextFnT /*context_fn*/) const
  29. -> ConvertedLoc override {
  30. return {.loc = {.line_number = test_loc.line_number,
  31. .column_number = test_loc.column_number},
  32. .last_byte_offset = test_loc.last_byte_offset};
  33. }
  34. };
  35. // Stores diagnostics in a vector for `ElementsArray` matching.
  36. class VectorConsumer : public Consumer {
  37. public:
  38. auto HandleDiagnostic(Diagnostic diagnostic) -> void override {
  39. diagnostics_.push_back(std::move(diagnostic));
  40. }
  41. auto Flush() -> void override {}
  42. auto diagnostics() const -> llvm::ArrayRef<Diagnostic> {
  43. return diagnostics_;
  44. }
  45. private:
  46. llvm::SmallVector<Diagnostic> diagnostics_;
  47. };
  48. TEST(SortedEmitterTest, SortErrors) {
  49. VectorConsumer consumer;
  50. SortingConsumer sorting_consumer(consumer);
  51. FakeEmitter emitter(&sorting_consumer);
  52. emitter.Emit({1, 10, 1}, TestDiagnostic, 1);
  53. emitter.Emit({-1, 11, 1}, TestDiagnostic, 2);
  54. emitter.Emit({0, 12, 1}, TestDiagnostic, 3);
  55. emitter.Emit({4, 13, 1}, TestDiagnostic, 4);
  56. emitter.Emit({3, 14, 1}, TestDiagnostic, 5);
  57. emitter.Emit({3, 15, 1}, TestDiagnostic, 6);
  58. EXPECT_TRUE(consumer.diagnostics().empty());
  59. sorting_consumer.Flush();
  60. EXPECT_THAT(
  61. consumer.diagnostics(),
  62. ElementsAreArray({
  63. IsSingleDiagnostic(Kind::TestDiagnostic, Level::Error, _, _, "Diag2"),
  64. IsSingleDiagnostic(Kind::TestDiagnostic, Level::Error, _, _, "Diag3"),
  65. IsSingleDiagnostic(Kind::TestDiagnostic, Level::Error, _, _, "Diag1"),
  66. IsSingleDiagnostic(Kind::TestDiagnostic, Level::Error, _, _, "Diag5"),
  67. IsSingleDiagnostic(Kind::TestDiagnostic, Level::Error, _, _, "Diag6"),
  68. IsSingleDiagnostic(Kind::TestDiagnostic, Level::Error, _, _, "Diag4"),
  69. }));
  70. }
  71. TEST(SortedEmitterTest, SortOnScope) {
  72. VectorConsumer consumer;
  73. SortingConsumer sorting_consumer(consumer);
  74. FakeEmitter emitter(&sorting_consumer);
  75. emitter.Emit({2, 15, 1}, TestDiagnosticOnScope, 1);
  76. emitter.Emit({4, 1, 1}, TestDiagnosticOnScope, 2);
  77. // Same `last_byte_offset`, should sort by line/column.
  78. emitter.Emit({3, 10, 5}, TestDiagnosticOnScope, 3);
  79. emitter.Emit({3, 10, 1}, TestDiagnosticOnScope, 4);
  80. emitter.Emit({3, 5, 20}, TestDiagnosticOnScope, 5);
  81. emitter.Emit({3, 10, 3}, TestDiagnosticOnScope, 6);
  82. EXPECT_TRUE(consumer.diagnostics().empty());
  83. sorting_consumer.Flush();
  84. EXPECT_THAT(consumer.diagnostics(),
  85. ElementsAreArray({
  86. IsSingleDiagnostic(Kind::TestDiagnosticOnScope, Level::Error,
  87. _, _, "DiagOnScope1"),
  88. IsSingleDiagnostic(Kind::TestDiagnosticOnScope, Level::Error,
  89. _, _, "DiagOnScope5"),
  90. IsSingleDiagnostic(Kind::TestDiagnosticOnScope, Level::Error,
  91. _, _, "DiagOnScope4"),
  92. IsSingleDiagnostic(Kind::TestDiagnosticOnScope, Level::Error,
  93. _, _, "DiagOnScope6"),
  94. IsSingleDiagnostic(Kind::TestDiagnosticOnScope, Level::Error,
  95. _, _, "DiagOnScope3"),
  96. IsSingleDiagnostic(Kind::TestDiagnosticOnScope, Level::Error,
  97. _, _, "DiagOnScope2"),
  98. }));
  99. }
  100. TEST(SortedEmitterTest, MixedScope) {
  101. VectorConsumer consumer;
  102. SortingConsumer sorting_consumer(consumer);
  103. FakeEmitter emitter(&sorting_consumer);
  104. // Difference in on-scope means only `last_byte_offset` is used.
  105. emitter.Emit({3, 3, 1}, TestDiagnosticOnScope, 1);
  106. emitter.Emit({3, 10, 1}, TestDiagnostic, 2);
  107. EXPECT_TRUE(consumer.diagnostics().empty());
  108. sorting_consumer.Flush();
  109. EXPECT_THAT(
  110. consumer.diagnostics(),
  111. ElementsAreArray({
  112. IsSingleDiagnostic(Kind::TestDiagnostic, Level::Error, _, _, "Diag2"),
  113. IsSingleDiagnostic(Kind::TestDiagnosticOnScope, Level::Error, _, _,
  114. "DiagOnScope1"),
  115. }));
  116. }
  117. } // namespace
  118. } // namespace Carbon::Diagnostics