file_test_base_test.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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 "testing/file_test/file_test_base.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. #include "common/ostream.h"
  8. #include "llvm/ADT/StringExtras.h"
  9. #include "llvm/Support/FormatVariadic.h"
  10. namespace Carbon::Testing {
  11. namespace {
  12. class FileTestBaseTest : public FileTestBase {
  13. public:
  14. FileTestBaseTest(llvm::StringRef /*exe_path*/, llvm::StringRef test_name)
  15. : FileTestBase(test_name) {}
  16. auto Run(const llvm::SmallVector<llvm::StringRef>& test_args,
  17. llvm::vfs::InMemoryFileSystem& fs, llvm::raw_pwrite_stream& stdout,
  18. llvm::raw_pwrite_stream& stderr) -> ErrorOr<RunResult> override {
  19. llvm::ArrayRef<llvm::StringRef> args = test_args;
  20. llvm::ListSeparator sep;
  21. stdout << args.size() << " args: ";
  22. for (auto arg : args) {
  23. stdout << sep << "`" << arg << "`";
  24. }
  25. stdout << "\n";
  26. auto filename = std::filesystem::path(test_name().str()).filename();
  27. if (filename == "args.carbon") {
  28. // 'args.carbon' has custom arguments, so don't do regular argument
  29. // validation for it.
  30. return {{.success = true}};
  31. }
  32. if (args.empty() || args.front() != "default_args") {
  33. return ErrorBuilder() << "missing `default_args` argument";
  34. }
  35. args = args.drop_front();
  36. for (auto arg : args) {
  37. if (!fs.exists(arg)) {
  38. return ErrorBuilder() << "Missing file: " << arg;
  39. }
  40. }
  41. if (filename == "example.carbon") {
  42. int delta_line = 10;
  43. stdout << "something\n"
  44. << "\n"
  45. << "example.carbon:" << delta_line + 1 << ": Line delta\n"
  46. << "example.carbon:" << delta_line << ": Negative line delta\n"
  47. << "+*[]{}\n"
  48. << "Foo baz\n";
  49. return {{.success = true}};
  50. } else if (filename == "fail_example.carbon") {
  51. stderr << "Oops\n";
  52. return {{.success = false}};
  53. } else if (filename == "two_files.carbon" ||
  54. filename == "not_split.carbon") {
  55. for (auto arg : args) {
  56. // Describe file contents to stdout to validate splitting.
  57. auto file = fs.getBufferForFile(arg, /*FileSize=*/-1,
  58. /*RequiresNullTerminator=*/false);
  59. if (file.getError()) {
  60. return Error(file.getError().message());
  61. }
  62. llvm::StringRef content = file.get()->getBuffer();
  63. stdout << arg << ":1: starts with \"";
  64. stdout.write_escaped(content.take_front(40));
  65. stdout << "\", length " << content.count('\n') << " lines\n";
  66. }
  67. return {{.success = true}};
  68. } else if (filename == "alternating_files.carbon") {
  69. stdout << "unattached message 1\n"
  70. << "a.carbon:2: message 2\n"
  71. << "b.carbon:5: message 3\n"
  72. << "a.carbon:2: message 4\n"
  73. << "b.carbon:5: message 5\n"
  74. << "unattached message 6\n";
  75. stderr << "unattached message 1\n"
  76. << "a.carbon:2: message 2\n"
  77. << "b.carbon:5: message 3\n"
  78. << "a.carbon:2: message 4\n"
  79. << "b.carbon:5: message 5\n"
  80. << "unattached message 6\n";
  81. return {{.success = true}};
  82. } else if (filename == "unattached_multi_file.carbon") {
  83. stdout << "unattached message 1\n"
  84. << "unattached message 2\n";
  85. stderr << "unattached message 3\n"
  86. << "unattached message 4\n";
  87. return {{.success = true}};
  88. } else if (filename == "file_only_re_one_file.carbon") {
  89. stdout << "unattached message 1\n"
  90. << "file: file_only_re_one_file.carbon\n"
  91. << "line: 1\n"
  92. << "unattached message 2\n";
  93. return {{.success = true}};
  94. } else if (filename == "file_only_re_multi_file.carbon") {
  95. int msg_count = 0;
  96. stdout << "unattached message " << ++msg_count << "\n"
  97. << "file: a.carbon\n"
  98. << "unattached message " << ++msg_count << "\n"
  99. << "line: 3: attached message " << ++msg_count << "\n"
  100. << "unattached message " << ++msg_count << "\n"
  101. << "line: 8: late message " << ++msg_count << "\n"
  102. << "unattached message " << ++msg_count << "\n"
  103. << "file: b.carbon\n"
  104. << "line: 2: attached message " << ++msg_count << "\n"
  105. << "unattached message " << ++msg_count << "\n"
  106. << "line: 7: late message " << ++msg_count << "\n"
  107. << "unattached message " << ++msg_count << "\n";
  108. return {{.success = true}};
  109. } else if (filename == "fail_multi_success_overall_fail.carbon") {
  110. RunResult result = {.success = false};
  111. result.per_file_success.push_back({"a.carbon", true});
  112. result.per_file_success.push_back({"b.carbon", true});
  113. return result;
  114. } else if (filename == "multi_success.carbon") {
  115. RunResult result = {.success = true};
  116. result.per_file_success.push_back({"a.carbon", true});
  117. result.per_file_success.push_back({"b.carbon", true});
  118. return result;
  119. } else if (filename == "multi_success_and_fail.carbon") {
  120. RunResult result = {.success = false};
  121. result.per_file_success.push_back({"a.carbon", true});
  122. result.per_file_success.push_back({"fail_b.carbon", false});
  123. return result;
  124. } else {
  125. return ErrorBuilder() << "Unexpected file: " << filename;
  126. }
  127. }
  128. auto GetDefaultArgs() -> llvm::SmallVector<std::string> override {
  129. return {"default_args", "%s"};
  130. }
  131. auto GetDefaultFileRE(llvm::ArrayRef<llvm::StringRef> filenames)
  132. -> std::optional<RE2> override {
  133. return std::make_optional<RE2>(
  134. llvm::formatv(R"(file: ({0}))", llvm::join(filenames, "|")));
  135. }
  136. auto GetLineNumberReplacements(llvm::ArrayRef<llvm::StringRef> filenames)
  137. -> llvm::SmallVector<LineNumberReplacement> override {
  138. auto replacements = FileTestBase::GetLineNumberReplacements(filenames);
  139. auto filename = std::filesystem::path(test_name().str()).filename();
  140. if (llvm::StringRef(filename).starts_with("file_only_re_")) {
  141. replacements.push_back({.has_file = false,
  142. .re = std::make_shared<RE2>(R"(line: (\d+))"),
  143. .line_formatv = "{0}"});
  144. }
  145. return replacements;
  146. }
  147. };
  148. } // namespace
  149. CARBON_FILE_TEST_FACTORY(FileTestBaseTest)
  150. } // namespace Carbon::Testing