file_test_base.h 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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_TESTING_FILE_TEST_FILE_TEST_BASE_H_
  5. #define CARBON_TESTING_FILE_TEST_FILE_TEST_BASE_H_
  6. #include <gmock/gmock.h>
  7. #include <gtest/gtest.h>
  8. #include <filesystem>
  9. #include <functional>
  10. #include <vector>
  11. #include "llvm/ADT/SmallVector.h"
  12. #include "llvm/ADT/StringRef.h"
  13. #include "llvm/Support/raw_ostream.h"
  14. namespace Carbon::Testing {
  15. // A framework for testing files. Children implement `RegisterTestFiles` with
  16. // calls to `RegisterTests` using a factory that constructs the child.
  17. // `RunWithFiles` must also be implemented and will be called as part of
  18. // individual test executions. This framework includes a `main` implementation,
  19. // so users must not provide one.
  20. //
  21. // Tests should have CHECK lines similar to `FileCheck` syntax:
  22. // https://llvm.org/docs/CommandGuide/FileCheck.html
  23. //
  24. // Special nuances are that stdout and stderr will look like `// CHECK:STDOUT:
  25. // ...` and `// CHECK:STDERR: ...` respectively. `[[@LINE+offset]` and
  26. // `{{regex}}` syntaxes should also work.
  27. //
  28. // `lit_autoupdate.py` automatically constructs compatible lines.
  29. class FileTestBase : public testing::Test {
  30. public:
  31. explicit FileTestBase(const std::filesystem::path& path);
  32. ~FileTestBase() override;
  33. // Used by children to register tests with gtest.
  34. static void RegisterTests(
  35. const char* fixture_label,
  36. const llvm::SmallVector<std::filesystem::path>& paths,
  37. std::function<FileTestBase*(const std::filesystem::path&)> factory);
  38. // Implemented by children to run the test. Called by the TestBody
  39. // implementation, which will validate stdout and stderr. The return value
  40. // should be false when "fail_" is in the filename.
  41. virtual auto RunWithFiles(const llvm::SmallVector<std::string>& test_files,
  42. llvm::raw_ostream& stdout,
  43. llvm::raw_ostream& stderr) -> bool = 0;
  44. // Runs a test and compares output. This keeps output split by line so that
  45. // issues are a little easier to identify by the different line.
  46. auto TestBody() -> void final;
  47. // Returns the full path of the file being tested.
  48. auto path() -> const std::filesystem::path& { return *path_; };
  49. private:
  50. // Sets TEST_TMPDIR as the working directory.
  51. auto SetTmpAsWorkingDir() -> void;
  52. // Processes the test input, producing test files and expected output.
  53. auto ProcessTestFile(
  54. llvm::SmallVector<std::string>& test_files,
  55. llvm::SmallVector<testing::Matcher<std::string>>& expected_stdout,
  56. llvm::SmallVector<testing::Matcher<std::string>>& expected_stderr)
  57. -> void;
  58. // Transforms an expectation on a given line from `FileCheck` syntax into a
  59. // standard regex matcher.
  60. static auto TransformExpectation(int line_index, llvm::StringRef in)
  61. -> testing::Matcher<std::string>;
  62. const std::filesystem::path* path_;
  63. };
  64. // Must be implemented by the individual file_test to initialize tests.
  65. extern auto RegisterFileTests(
  66. const llvm::SmallVector<std::filesystem::path>& paths) -> void;
  67. } // namespace Carbon::Testing
  68. #endif // CARBON_TESTING_FILE_TEST_FILE_TEST_BASE_H_