file_test.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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 "explorer/parse_and_execute/parse_and_execute.h"
  5. #include "testing/file_test/file_test_base.h"
  6. #include "testing/util/test_raw_ostream.h"
  7. namespace Carbon::Testing {
  8. namespace {
  9. class ParseAndExecuteTestFile : public FileTestBase {
  10. public:
  11. explicit ParseAndExecuteTestFile(const std::filesystem::path& path,
  12. bool trace)
  13. : FileTestBase(path), trace_(trace) {}
  14. auto SetUp() -> void override {
  15. std::string path_str = path().string();
  16. llvm::StringRef path_ref = path_str;
  17. if (path_ref.find("trace_testdata") != llvm::StringRef::npos) {
  18. is_trace_test = true;
  19. }
  20. if (trace_) {
  21. if (path_ref.find("/limits/") != llvm::StringRef::npos) {
  22. GTEST_SKIP()
  23. << "`limits` tests check for various limit conditions (such as an "
  24. "infinite loop). The tests collectively don't test tracing "
  25. "because it creates substantial additional overhead.";
  26. } else if (path_ref.endswith(
  27. "testdata/assoc_const/rewrite_large_type.carbon") ||
  28. path_ref.endswith(
  29. "testdata/linked_list/typed_linked_list.carbon")) {
  30. GTEST_SKIP() << "Expensive test to trace";
  31. }
  32. } else {
  33. if (is_trace_test) {
  34. GTEST_SKIP() << "`trace` tests only check for trace output.";
  35. }
  36. }
  37. }
  38. auto RunWithFiles(const llvm::SmallVector<llvm::StringRef>& test_args,
  39. const llvm::SmallVector<TestFile>& test_files,
  40. llvm::raw_pwrite_stream& stdout,
  41. llvm::raw_pwrite_stream& stderr) -> bool override {
  42. CARBON_CHECK(test_args.empty())
  43. << "ARGS are not currently used in explorer's file_test.";
  44. if (test_files.size() != 1) {
  45. ADD_FAILURE() << "Only 1 file is supported: " << test_files.size()
  46. << " provided";
  47. return false;
  48. }
  49. // Capture trace streaming, but only when in debug mode.
  50. TraceStream trace_stream;
  51. TestRawOstream trace_stream_ostream;
  52. if (trace_) {
  53. trace_stream.set_stream(is_trace_test ? &stdout : &trace_stream_ostream);
  54. trace_stream.set_allowed_phases({ProgramPhase::All});
  55. trace_stream.set_allowed_file_kinds({FileKind::Main});
  56. }
  57. // Set the location of the prelude.
  58. char* test_srcdir = getenv("TEST_SRCDIR");
  59. CARBON_CHECK(test_srcdir != nullptr);
  60. std::string prelude_path(test_srcdir);
  61. prelude_path += "/carbon/explorer/data/prelude.carbon";
  62. // Run the parse. Parser debug output is always off because it's difficult
  63. // to redirect.
  64. auto result = ParseAndExecute(
  65. prelude_path, test_files[0].filename, test_files[0].content,
  66. /*parser_debug=*/false, &trace_stream, &stdout);
  67. // This mirrors printing currently done by main.cpp.
  68. if (result.ok()) {
  69. stdout << "result: " << *result << "\n";
  70. } else {
  71. stderr << result.error() << "\n";
  72. }
  73. // Skip trace test check as they use stdout stream instead of
  74. // trace_stream_ostream
  75. if (trace_ && !is_trace_test) {
  76. EXPECT_FALSE(trace_stream_ostream.TakeStr().empty())
  77. << "Tracing should always do something";
  78. }
  79. return result.ok();
  80. }
  81. auto GetDefaultArgs() -> llvm::SmallVector<std::string> override {
  82. return {};
  83. }
  84. private:
  85. bool trace_;
  86. bool is_trace_test = false;
  87. };
  88. } // namespace
  89. extern auto RegisterFileTests(
  90. const llvm::SmallVector<std::filesystem::path>& paths) -> void {
  91. ParseAndExecuteTestFile::RegisterTests(
  92. "ParseAndExecuteTestFile", paths, [](const std::filesystem::path& path) {
  93. return new ParseAndExecuteTestFile(path, /*trace=*/false);
  94. });
  95. ParseAndExecuteTestFile::RegisterTests("ParseAndExecuteTestFile.trace", paths,
  96. [](const std::filesystem::path& path) {
  97. return new ParseAndExecuteTestFile(
  98. path, /*trace=*/true);
  99. });
  100. }
  101. } // namespace Carbon::Testing