Tests.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "Tests.h"
  7. #include "../FileDB.h"
  8. #include "CppComprehensionEngine.h"
  9. #include <AK/LexicalPath.h>
  10. #include <LibMain/Main.h>
  11. static bool s_some_test_failed = false;
  12. #define I_TEST(name) \
  13. { \
  14. printf("Testing " #name "... "); \
  15. fflush(stdout); \
  16. }
  17. #define PASS \
  18. do { \
  19. printf("PASS\n"); \
  20. fflush(stdout); \
  21. return; \
  22. } while (0)
  23. #define FAIL(reason) \
  24. do { \
  25. printf("FAIL: " #reason "\n"); \
  26. s_some_test_failed = true; \
  27. return; \
  28. } while (0)
  29. #define RUN(function) \
  30. function; \
  31. if (s_some_test_failed) { \
  32. return 1; \
  33. }
  34. constexpr auto TESTS_ROOT_DIR = "/home/anon/Tests/cpp-tests/comprehension"sv;
  35. class FileDB : public CodeComprehension::FileDB {
  36. public:
  37. FileDB() = default;
  38. void add(DeprecatedString filename, DeprecatedString content)
  39. {
  40. m_map.set(filename, content);
  41. }
  42. virtual Optional<DeprecatedString> get_or_read_from_filesystem(StringView filename) const override
  43. {
  44. DeprecatedString target_filename = filename;
  45. if (project_root().has_value() && filename.starts_with(*project_root())) {
  46. target_filename = LexicalPath::relative_path(filename, *project_root());
  47. }
  48. return m_map.get(target_filename);
  49. }
  50. private:
  51. HashMap<DeprecatedString, DeprecatedString> m_map;
  52. };
  53. static void test_complete_local_args();
  54. static void test_complete_local_vars();
  55. static void test_complete_type();
  56. static void test_find_variable_definition();
  57. static void test_find_array_variable_declaration_single();
  58. static void test_find_array_variable_declaration_single_empty();
  59. static void test_find_array_variable_declaration_double();
  60. static void test_complete_includes();
  61. static void test_parameters_hint();
  62. int run_tests()
  63. {
  64. RUN(test_complete_local_args());
  65. RUN(test_complete_local_vars());
  66. RUN(test_complete_type());
  67. RUN(test_find_variable_definition());
  68. RUN(test_find_array_variable_declaration_single());
  69. RUN(test_find_array_variable_declaration_single_empty());
  70. RUN(test_find_array_variable_declaration_double());
  71. RUN(test_complete_includes());
  72. RUN(test_parameters_hint());
  73. return 0;
  74. }
  75. static void add_file(FileDB& filedb, DeprecatedString const& name)
  76. {
  77. auto file = Core::File::open(LexicalPath::join(TESTS_ROOT_DIR, name).string(), Core::File::OpenMode::Read).release_value_but_fixme_should_propagate_errors();
  78. filedb.add(name, DeprecatedString::copy(MUST(file->read_until_eof())));
  79. }
  80. void test_complete_local_args()
  81. {
  82. I_TEST(Complete Local Args)
  83. FileDB filedb;
  84. add_file(filedb, "complete_local_args.cpp");
  85. CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
  86. auto suggestions = engine.get_suggestions("complete_local_args.cpp", { 2, 6 });
  87. if (suggestions.size() != 2)
  88. FAIL(bad size);
  89. if (suggestions[0].completion == "argc" && suggestions[1].completion == "argv")
  90. PASS;
  91. FAIL("wrong results");
  92. }
  93. void test_complete_local_vars()
  94. {
  95. I_TEST(Complete Local Vars)
  96. FileDB filedb;
  97. add_file(filedb, "complete_local_vars.cpp");
  98. CodeComprehension::Cpp::CppComprehensionEngine autocomplete(filedb);
  99. auto suggestions = autocomplete.get_suggestions("complete_local_vars.cpp", { 3, 7 });
  100. if (suggestions.size() != 1)
  101. FAIL(bad size);
  102. if (suggestions[0].completion == "myvar1")
  103. PASS;
  104. FAIL("wrong results");
  105. }
  106. void test_complete_type()
  107. {
  108. I_TEST(Complete Type)
  109. FileDB filedb;
  110. add_file(filedb, "complete_type.cpp");
  111. CodeComprehension::Cpp::CppComprehensionEngine autocomplete(filedb);
  112. auto suggestions = autocomplete.get_suggestions("complete_type.cpp", { 5, 7 });
  113. if (suggestions.size() != 1)
  114. FAIL(bad size);
  115. if (suggestions[0].completion == "MyStruct")
  116. PASS;
  117. FAIL("wrong results");
  118. }
  119. void test_find_variable_definition()
  120. {
  121. I_TEST(Find Variable Declaration)
  122. FileDB filedb;
  123. add_file(filedb, "find_variable_declaration.cpp");
  124. CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
  125. auto position = engine.find_declaration_of("find_variable_declaration.cpp", { 2, 5 });
  126. if (!position.has_value())
  127. FAIL("declaration not found");
  128. if (position.value().file == "find_variable_declaration.cpp" && position.value().line == 0 && position.value().column >= 19)
  129. PASS;
  130. FAIL("wrong declaration location");
  131. }
  132. void test_find_array_variable_declaration_single()
  133. {
  134. I_TEST(Find 1D Array as a Variable Declaration)
  135. FileDB filedb;
  136. auto filename = "find_array_variable_declaration.cpp";
  137. add_file(filedb, filename);
  138. CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
  139. auto position = engine.find_declaration_of(filename, { 3, 6 });
  140. if (!position.has_value())
  141. FAIL("declaration not found");
  142. if (position.value().file == filename && position.value().line == 2 && position.value().column >= 4)
  143. PASS;
  144. printf("Found at position %zu %zu\n", position.value().line, position.value().column);
  145. FAIL("wrong declaration location");
  146. }
  147. void test_find_array_variable_declaration_single_empty()
  148. {
  149. I_TEST(Find 1D Empty size Array as a Variable Declaration)
  150. FileDB filedb;
  151. auto filename = "find_array_variable_declaration.cpp";
  152. add_file(filedb, filename);
  153. CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
  154. auto position = engine.find_declaration_of(filename, { 6, 6 });
  155. if (!position.has_value())
  156. FAIL("declaration not found");
  157. if (position.value().file == filename && position.value().line == 5 && position.value().column >= 4)
  158. PASS;
  159. printf("Found at position %zu %zu\n", position.value().line, position.value().column);
  160. FAIL("wrong declaration location");
  161. }
  162. void test_find_array_variable_declaration_double()
  163. {
  164. I_TEST(Find 2D Array as a Variable Declaration)
  165. FileDB filedb;
  166. auto filename = "find_array_variable_declaration.cpp";
  167. add_file(filedb, filename);
  168. CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
  169. auto position = engine.find_declaration_of(filename, { 9, 6 });
  170. if (!position.has_value())
  171. FAIL("declaration not found");
  172. if (position.value().file == filename && position.value().line == 8 && position.value().column >= 4)
  173. PASS;
  174. printf("Found at position %zu %zu\n", position.value().line, position.value().column);
  175. FAIL("wrong declaration location");
  176. }
  177. void test_complete_includes()
  178. {
  179. I_TEST(Complete include statements)
  180. FileDB filedb;
  181. filedb.set_project_root(TESTS_ROOT_DIR);
  182. add_file(filedb, "complete_includes.cpp");
  183. add_file(filedb, "sample_header.h");
  184. CodeComprehension::Cpp::CppComprehensionEngine autocomplete(filedb);
  185. auto suggestions = autocomplete.get_suggestions("complete_includes.cpp", { 0, 22 });
  186. if (suggestions.size() != 1)
  187. FAIL(project include - bad size);
  188. if (suggestions[0].completion != "\"sample_header.h\"")
  189. FAIL("project include - wrong results");
  190. suggestions = autocomplete.get_suggestions("complete_includes.cpp", { 1, 18 });
  191. if (suggestions.size() != 1)
  192. FAIL(global include - bad size);
  193. if (suggestions[0].completion != "<sys/cdefs.h>")
  194. FAIL("global include - wrong results");
  195. PASS;
  196. }
  197. void test_parameters_hint()
  198. {
  199. I_TEST(Function Parameters hint)
  200. FileDB filedb;
  201. filedb.set_project_root(TESTS_ROOT_DIR);
  202. add_file(filedb, "parameters_hint1.cpp");
  203. CodeComprehension::Cpp::CppComprehensionEngine engine(filedb);
  204. auto result = engine.get_function_params_hint("parameters_hint1.cpp", { 4, 9 });
  205. if (!result.has_value())
  206. FAIL("failed to get parameters hint (1)");
  207. if (result->params != Vector<DeprecatedString> { "int x", "char y" } || result->current_index != 0)
  208. FAIL("bad result (1)");
  209. result = engine.get_function_params_hint("parameters_hint1.cpp", { 5, 15 });
  210. if (!result.has_value())
  211. FAIL("failed to get parameters hint (2)");
  212. if (result->params != Vector<DeprecatedString> { "int x", "char y" } || result->current_index != 1)
  213. FAIL("bad result (2)");
  214. result = engine.get_function_params_hint("parameters_hint1.cpp", { 6, 8 });
  215. if (!result.has_value())
  216. FAIL("failed to get parameters hint (3)");
  217. if (result->params != Vector<DeprecatedString> { "int x", "char y" } || result->current_index != 0)
  218. FAIL("bad result (3)");
  219. PASS;
  220. }
  221. ErrorOr<int> serenity_main(Main::Arguments)
  222. {
  223. return run_tests();
  224. }