test_runner.cpp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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 <tree_sitter/api.h>
  5. #include <cstdlib>
  6. #include <filesystem>
  7. #include <fstream>
  8. #include <iostream>
  9. #include <sstream>
  10. #include <string>
  11. #include <vector>
  12. #include "utils/tree_sitter/src/tree_sitter/parser.h"
  13. extern "C" {
  14. auto tree_sitter_carbon() -> TSLanguage*;
  15. }
  16. // Reads a file to string.
  17. static auto ReadFile(std::filesystem::path path) -> std::string {
  18. std::ifstream file(path);
  19. std::stringstream buffer;
  20. buffer << file.rdbuf();
  21. file.close();
  22. return buffer.str();
  23. }
  24. // TODO: use file_test.cpp
  25. auto main(int argc, char** argv) -> int {
  26. if (argc < 2) {
  27. std::cerr << "Usage: test_runner <file>...\n";
  28. return 2;
  29. }
  30. auto* parser = ts_parser_new();
  31. ts_parser_set_language(parser, tree_sitter_carbon());
  32. bool fail_tests = std::getenv("FAIL_TESTS") != nullptr;
  33. std::vector<std::string> incorrect;
  34. for (int i = 1; i < argc; i++) {
  35. std::string file_path = argv[i];
  36. std::string source = ReadFile(file_path);
  37. auto* tree =
  38. ts_parser_parse_string(parser, nullptr, source.data(), source.size());
  39. auto root = ts_tree_root_node(tree);
  40. auto has_error = ts_node_has_error(root);
  41. char* node_debug = ts_node_string(root);
  42. std::cout << file_path << ":\n" << node_debug << "\n";
  43. if (has_error ^ fail_tests) {
  44. incorrect.push_back(file_path);
  45. }
  46. free(node_debug);
  47. ts_tree_delete(tree);
  48. }
  49. ts_parser_delete(parser);
  50. for (const auto& file : incorrect) {
  51. if (fail_tests) {
  52. std::cout << "INCORRECTLY PASSING " << file << "\n";
  53. } else {
  54. std::cout << "FAILED " << file << "\n";
  55. }
  56. }
  57. if (!incorrect.empty()) {
  58. if (fail_tests) {
  59. std::cout << incorrect.size() << " tests incorrectly passing.\n";
  60. } else {
  61. std::cout << incorrect.size() << " tests failing.\n";
  62. }
  63. return 1;
  64. }
  65. }