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