coverage_helper.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. #ifndef CARBON_TOOLCHAIN_TESTING_COVERAGE_HELPER_H_
  5. #define CARBON_TOOLCHAIN_TESTING_COVERAGE_HELPER_H_
  6. #include <gtest/gtest.h>
  7. #include <fstream>
  8. #include <string>
  9. #include "common/set.h"
  10. #include "llvm/ADT/StringExtras.h"
  11. #include "re2/re2.h"
  12. namespace Carbon::Testing {
  13. // Looks for kinds that aren't covered by a file_test in the manifest path.
  14. // Kinds are identified by the provided regular expression kind_pattern.
  15. //
  16. // should_be_covered should return false when a kind is either untestable or not
  17. // yet tested.
  18. //
  19. // TODO: Switch `kind_pattern` to `llvm::StringLiteral` if
  20. // `llvm::StringLiteral::c_str` is added.
  21. template <typename KindT>
  22. auto TestKindCoverage(const std::string& manifest_path,
  23. const char* kind_pattern, llvm::ArrayRef<KindT> kinds,
  24. llvm::ArrayRef<KindT> untested_kinds) {
  25. std::ifstream manifest_in(manifest_path.c_str());
  26. ASSERT_TRUE(manifest_in.good());
  27. RE2 kind_re(kind_pattern);
  28. ASSERT_TRUE(kind_re.ok()) << kind_re.error();
  29. Set<std::string> covered_kinds;
  30. std::string test_filename;
  31. while (std::getline(manifest_in, test_filename)) {
  32. std::ifstream test_in(test_filename);
  33. ASSERT_TRUE(test_in.good());
  34. std::string line;
  35. while (std::getline(test_in, line)) {
  36. std::string kind;
  37. if (RE2::PartialMatch(line, kind_re, &kind)) {
  38. covered_kinds.Insert(kind);
  39. }
  40. }
  41. }
  42. llvm::SmallVector<llvm::StringRef> missing_kinds;
  43. for (auto kind : kinds) {
  44. if (llvm::find(untested_kinds, kind) != untested_kinds.end()) {
  45. EXPECT_FALSE(covered_kinds.Erase(kind.name()))
  46. << "Kind " << kind
  47. << " has coverage even though none was expected. If this has "
  48. "changed, update the coverage test.";
  49. continue;
  50. }
  51. if (!covered_kinds.Erase(kind.name())) {
  52. missing_kinds.push_back(kind.name());
  53. }
  54. }
  55. constexpr llvm::StringLiteral Bullet = "\n - ";
  56. llvm::sort(missing_kinds);
  57. EXPECT_TRUE(missing_kinds.empty()) << "Some kinds have no tests:" << Bullet
  58. << llvm::join(missing_kinds, Bullet);
  59. llvm::SmallVector<std::string> unexpected_matches;
  60. covered_kinds.ForEach(
  61. [&](const std::string& match) { unexpected_matches.push_back(match); });
  62. llvm::sort(unexpected_matches);
  63. EXPECT_TRUE(unexpected_matches.empty())
  64. << "Matched things that aren't in the kind list:" << Bullet
  65. << llvm::join(unexpected_matches, Bullet);
  66. }
  67. } // namespace Carbon::Testing
  68. #endif // CARBON_TOOLCHAIN_TESTING_COVERAGE_HELPER_H_