Browse Source

Additional language client tests

pipelines/353213535
eidheim 5 years ago
parent
commit
149e82a279
  1. 1
      tests/CMakeLists.txt
  2. 50
      tests/language_protocol_client_test.cpp
  3. 622
      tests/language_protocol_server_test.cpp
  4. 3
      tests/language_protocol_test_files/main.rs

1
tests/CMakeLists.txt

@ -90,6 +90,7 @@ if(BUILD_TESTING)
add_test(language_protocol_client_test language_protocol_client_test) add_test(language_protocol_client_test language_protocol_client_test)
add_executable(language_protocol_server_test language_protocol_server_test.cpp) add_executable(language_protocol_server_test language_protocol_server_test.cpp)
target_link_libraries(language_protocol_server_test Boost::filesystem)
endif() endif()
if(BUILD_FUZZING) if(BUILD_FUZZING)

50
tests/language_protocol_client_test.cpp

@ -1,4 +1,3 @@
#include "config.hpp"
#include "source_language_protocol.hpp" #include "source_language_protocol.hpp"
#include <glib.h> #include <glib.h>
@ -31,16 +30,61 @@ int main() {
view->get_buffer()->insert_at_cursor(" "); view->get_buffer()->insert_at_cursor(" ");
g_assert(view->get_buffer()->get_text() == R"( fn main() { g_assert(view->get_buffer()->get_text() == R"( fn main() {
println!("Hello, world!"); let a = 2;
println!("{}", a);
} }
)"); )");
view->format_style(false); view->format_style(false);
g_assert(view->get_buffer()->get_text() == R"(fn main() { g_assert(view->get_buffer()->get_text() == R"(fn main() {
println!("Hello, world!"); let a = 2;
println!("{}", a);
} }
)"); )");
g_assert(view->get_declaration_location);
auto location = view->get_declaration_location();
g_assert(location);
g_assert(location.file_path == "main.rs");
g_assert_cmpuint(location.line, ==, 0);
g_assert_cmpuint(location.index, ==, 3);
g_assert(view->get_type_declaration_location);
location = view->get_type_declaration_location();
g_assert(location);
g_assert(location.file_path == "main.rs");
g_assert_cmpuint(location.line, ==, 0);
g_assert_cmpuint(location.index, ==, 4);
g_assert(view->get_implementation_locations);
auto locations = view->get_implementation_locations();
g_assert(locations.size() == 2);
g_assert(locations[0].file_path == "main.rs");
g_assert(locations[1].file_path == "main.rs");
g_assert_cmpuint(locations[0].line, ==, 0);
g_assert_cmpuint(locations[0].index, ==, 0);
g_assert_cmpuint(locations[1].line, ==, 1);
g_assert_cmpuint(locations[1].index, ==, 0);
g_assert(view->get_usages);
auto usages = view->get_usages();
g_assert(usages.size() == 2);
g_assert(usages[0].first.file_path == view->file_path);
g_assert(usages[1].first.file_path == view->file_path);
g_assert_cmpuint(usages[0].first.line, ==, 1);
g_assert_cmpuint(usages[0].first.index, ==, 8);
g_assert_cmpuint(usages[1].first.line, ==, 2);
g_assert_cmpuint(usages[1].first.index, ==, 19);
g_assert(usages[0].second == "let <b>a</b> = 2;");
g_assert(usages[1].second == "println!(&quot;{}&quot;, <b>a</b>);");
g_assert(view->get_methods);
auto methods = view->get_methods();
g_assert(methods.size() == 1);
g_assert_cmpuint(methods[0].first.line, ==, 0);
g_assert_cmpuint(methods[0].first.index, ==, 0);
g_assert(methods[0].second == "1: <b>main</b>");
std::atomic<int> exit_status(-1); std::atomic<int> exit_status(-1);
view->client->on_exit_status = [&exit_status](int exit_status_) { view->client->on_exit_status = [&exit_status](int exit_status_) {
exit_status = exit_status_; exit_status = exit_status_;

622
tests/language_protocol_server_test.cpp

@ -1,3 +1,4 @@
#include <boost/filesystem.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <iostream> #include <iostream>
@ -12,6 +13,9 @@ int main() {
_setmode(_fileno(stdout), _O_BINARY); _setmode(_fileno(stdout), _O_BINARY);
#endif #endif
auto tests_path = boost::filesystem::canonical(JUCI_TESTS_PATH);
auto file_path = boost::filesystem::canonical(tests_path / "language_protocol_test_files" / "main.rs");
std::string line; std::string line;
try { try {
// Read initialize and respond // Read initialize and respond
@ -29,185 +33,172 @@ int main() {
return 1; return 1;
std::string result = R"({ std::string result = R"({
"jsonrpc": "2.0", "jsonrpc": "2.0",
"id": "0", "id": "0",
"result": { "result": {
"capabilities": { "capabilities": {
"textDocumentSync": { "textDocumentSync": {
"openClose": "true", "openClose": "true",
"change": "2", "change": "2",
"save": "" "save": ""
}, },
"selectionRangeProvider": "true", "selectionRangeProvider": "true",
"hoverProvider": "true", "hoverProvider": "true",
"completionProvider": { "completionProvider": {
"triggerCharacters": [ "triggerCharacters": [":", ".", "'"]
":", },
".", "signatureHelpProvider": {
"'" "triggerCharacters": ["(", ","]
] },
}, "definitionProvider": "true",
"signatureHelpProvider": { "typeDefinitionProvider": "true",
"triggerCharacters": [ "implementationProvider": "true",
"(", "referencesProvider": "true",
"," "documentHighlightProvider": "true",
] "documentSymbolProvider": "true",
}, "workspaceSymbolProvider": "true",
"definitionProvider": "true", "codeActionProvider": {
"typeDefinitionProvider": "true", "codeActionKinds": [
"implementationProvider": "true", "",
"referencesProvider": "true", "quickfix",
"documentHighlightProvider": "true", "refactor",
"documentSymbolProvider": "true", "refactor.extract",
"workspaceSymbolProvider": "true", "refactor.inline",
"codeActionProvider": { "refactor.rewrite"
"codeActionKinds": [ ],
"", "resolveProvider": "true"
"quickfix", },
"refactor", "codeLensProvider": {
"refactor.extract", "resolveProvider": "true"
"refactor.inline", },
"refactor.rewrite" "documentFormattingProvider": "true",
], "documentOnTypeFormattingProvider": {
"resolveProvider": "true" "firstTriggerCharacter": "=",
}, "moreTriggerCharacter": [".", ">", "{"]
"codeLensProvider": { },
"resolveProvider": "true" "renameProvider": {
}, "prepareProvider": "true"
"documentFormattingProvider": "true", },
"documentOnTypeFormattingProvider": { "foldingRangeProvider": "true",
"firstTriggerCharacter": "=", "workspace": {
"moreTriggerCharacter": [ "fileOperations": {
".", "willRename": {
">", "filters": [
"{" {
] "scheme": "file",
}, "pattern": {
"renameProvider": { "glob": "**/*.rs",
"prepareProvider": "true" "matches": "file"
},
"foldingRangeProvider": "true",
"workspace": {
"fileOperations": {
"willRename": {
"filters": [
{
"scheme": "file",
"pattern": {
"glob": "**\/*.rs",
"matches": "file"
}
},
{
"scheme": "file",
"pattern": {
"glob": "**",
"matches": "folder"
}
}
]
}
} }
}, },
"callHierarchyProvider": "true", {
"semanticTokensProvider": { "scheme": "file",
"legend": { "pattern": {
"tokenTypes": [ "glob": "**",
"comment", "matches": "folder"
"keyword",
"string",
"number",
"regexp",
"operator",
"namespace",
"type",
"struct",
"class",
"interface",
"enum",
"enumMember",
"typeParameter",
"function",
"method",
"property",
"macro",
"variable",
"parameter",
"angle",
"arithmetic",
"attribute",
"bitwise",
"boolean",
"brace",
"bracket",
"builtinType",
"characterLiteral",
"colon",
"comma",
"comparison",
"constParameter",
"dot",
"escapeSequence",
"formatSpecifier",
"generic",
"label",
"lifetime",
"logical",
"operator",
"parenthesis",
"punctuation",
"selfKeyword",
"semicolon",
"typeAlias",
"union",
"unresolvedReference"
],
"tokenModifiers": [
"documentation",
"declaration",
"definition",
"static",
"abstract",
"deprecated",
"readonly",
"constant",
"controlFlow",
"injected",
"mutable",
"consuming",
"async",
"unsafe",
"attribute",
"trait",
"callable",
"intraDocLink"
]
},
"range": "true",
"full": {
"delta": "true"
} }
}, }
"experimental": { ]
"joinLines": "true", }
"ssr": "true", }
"onEnter": "true", },
"parentModule": "true", "callHierarchyProvider": "true",
"runnables": { "semanticTokensProvider": {
"kinds": [ "legend": {
"cargo" "tokenTypes": [
] "comment",
}, "keyword",
"workspaceSymbolScopeKindFiltering": "true" "string",
} "number",
"regexp",
"operator",
"namespace",
"type",
"struct",
"class",
"interface",
"enum",
"enumMember",
"typeParameter",
"function",
"method",
"property",
"macro",
"variable",
"parameter",
"angle",
"arithmetic",
"attribute",
"bitwise",
"boolean",
"brace",
"bracket",
"builtinType",
"characterLiteral",
"colon",
"comma",
"comparison",
"constParameter",
"dot",
"escapeSequence",
"formatSpecifier",
"generic",
"label",
"lifetime",
"logical",
"operator",
"parenthesis",
"punctuation",
"selfKeyword",
"semicolon",
"typeAlias",
"union",
"unresolvedReference"
],
"tokenModifiers": [
"documentation",
"declaration",
"definition",
"static",
"abstract",
"deprecated",
"readonly",
"constant",
"controlFlow",
"injected",
"mutable",
"consuming",
"async",
"unsafe",
"attribute",
"trait",
"callable",
"intraDocLink"
]
}, },
"serverInfo": { "range": "true",
"name": "rust-analyzer", "full": {
"version": "3022a2c3a 2021-05-25 dev" "delta": "true"
}
},
"experimental": {
"joinLines": "true",
"ssr": "true",
"onEnter": "true",
"parentModule": "true",
"runnables": {
"kinds": ["cargo"]
}, },
"offsetEncoding": "utf-8" "workspaceSymbolScopeKindFiltering": "true"
}
},
"serverInfo": {
"name": "rust-analyzer",
"version": "3022a2c3a 2021-05-25 dev"
} }
})"; }
}
)";
std::cout << "Content-Length: " << result.size() << "\r\n\r\n" std::cout << "Content-Length: " << result.size() << "\r\n\r\n"
<< result; << result;
} }
@ -224,7 +215,7 @@ int main() {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt); boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "initialized") if(pt.get<std::string>("method") != "initialized")
return 2; return 1;
} }
// Read textDocument/didOpen // Read textDocument/didOpen
@ -239,7 +230,7 @@ int main() {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt); boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/didOpen") if(pt.get<std::string>("method") != "textDocument/didOpen")
return 3; return 1;
} }
// Read textDocument/didChange // Read textDocument/didChange
@ -254,7 +245,7 @@ int main() {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt); boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/didChange") if(pt.get<std::string>("method") != "textDocument/didChange")
return 4; return 1;
} }
// Read and write textDocument/formatting // Read and write textDocument/formatting
@ -269,27 +260,28 @@ int main() {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt); boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/formatting") if(pt.get<std::string>("method") != "textDocument/formatting")
return 5; return 1;
std::string result = R"({ std::string result = R"({
"jsonrpc": "2.0", "jsonrpc": "2.0",
"id": "1", "id": "1",
"result": [ "result": [
{ {
"range": { "range": {
"start": { "start": {
"line": "0", "line": "0",
"character": "0" "character": "0"
}, },
"end": { "end": {
"line": "0", "line": "0",
"character": "1" "character": "1"
}
},
"newText": ""
} }
] },
})"; "newText": ""
}
]
}
)";
std::cout << "Content-Length: " << result.size() << "\r\n\r\n" std::cout << "Content-Length: " << result.size() << "\r\n\r\n"
<< result; << result;
} }
@ -306,7 +298,231 @@ int main() {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt); boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/didChange") if(pt.get<std::string>("method") != "textDocument/didChange")
return 6; return 1;
}
// Read and write textDocument/definition
{
std::getline(std::cin, line);
auto size = std::atoi(line.substr(16).c_str());
std::getline(std::cin, line);
std::string buffer;
buffer.resize(size);
std::cin.read(&buffer[0], size);
std::stringstream ss(buffer);
boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/definition")
return 1;
std::string result = R"({
"jsonrpc": "2.0",
"id": "2",
"result": [
{
"uri": "file://main.rs",
"range": {
"start": {
"line": "0",
"character": "3"
},
"end": {
"line": "0",
"character": "7"
}
}
}
]
}
)";
std::cout << "Content-Length: " << result.size() << "\r\n\r\n"
<< result;
}
// Read and write textDocument/typeDefinition
{
std::getline(std::cin, line);
auto size = std::atoi(line.substr(16).c_str());
std::getline(std::cin, line);
std::string buffer;
buffer.resize(size);
std::cin.read(&buffer[0], size);
std::stringstream ss(buffer);
boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/typeDefinition")
return 1;
std::string result = R"({
"jsonrpc": "2.0",
"id": "3",
"result": [
{
"uri": "file://main.rs",
"range": {
"start": {
"line": "0",
"character": "4"
},
"end": {
"line": "0",
"character": "7"
}
}
}
]
}
)";
std::cout << "Content-Length: " << result.size() << "\r\n\r\n"
<< result;
}
// Read and write textDocument/implementation
{
std::getline(std::cin, line);
auto size = std::atoi(line.substr(16).c_str());
std::getline(std::cin, line);
std::string buffer;
buffer.resize(size);
std::cin.read(&buffer[0], size);
std::stringstream ss(buffer);
boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/implementation")
return 1;
std::string result = R"({
"jsonrpc": "2.0",
"id": "4",
"result": [
{
"uri": "file://main.rs",
"range": {
"start": {
"line": "0",
"character": "0"
},
"end": {
"line": "0",
"character": "1"
}
}
},
{
"uri": "file://main.rs",
"range": {
"start": {
"line": "1",
"character": "0"
},
"end": {
"line": "1",
"character": "1"
}
}
}
]
}
)";
std::cout << "Content-Length: " << result.size() << "\r\n\r\n"
<< result;
}
// Read and write textDocument/references
{
std::getline(std::cin, line);
auto size = std::atoi(line.substr(16).c_str());
std::getline(std::cin, line);
std::string buffer;
buffer.resize(size);
std::cin.read(&buffer[0], size);
std::stringstream ss(buffer);
boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/references")
return 1;
std::string result = R"({
"jsonrpc": "2.0",
"id": "5",
"result": [
{
"uri": "file://)" + file_path.string() +
R"(",
"range": {
"start": {
"line": "2",
"character": "19"
},
"end": {
"line": "2",
"character": "20"
}
}
},
{
"uri": "file://)" + file_path.string() +
R"(",
"range": {
"start": {
"line": "1",
"character": "8"
},
"end": {
"line": "1",
"character": "9"
}
}
}
]
}
)";
std::cout << "Content-Length: " << result.size() << "\r\n\r\n"
<< result;
}
// Read and write textDocument/references
{
std::getline(std::cin, line);
auto size = std::atoi(line.substr(16).c_str());
std::getline(std::cin, line);
std::string buffer;
buffer.resize(size);
std::cin.read(&buffer[0], size);
std::stringstream ss(buffer);
boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/documentSymbol")
return 1;
std::string result = R"({
"jsonrpc": "2.0",
"id": "6",
"result": [
{
"name": "main",
"kind": "12",
"tags": "",
"deprecated": "false",
"location": {
"uri": "file://main.rs",
"range": {
"start": {
"line": "0",
"character": "0"
},
"end": {
"line": "3",
"character": "1"
}
}
}
}
]
}
)";
std::cout << "Content-Length: " << result.size() << "\r\n\r\n"
<< result;
} }
// Read textDocument/didClose // Read textDocument/didClose
@ -321,7 +537,7 @@ int main() {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt); boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "textDocument/didClose") if(pt.get<std::string>("method") != "textDocument/didClose")
return 7; return 1;
} }
// Read shutdown and respond // Read shutdown and respond
@ -336,12 +552,12 @@ int main() {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt); boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "shutdown") if(pt.get<std::string>("method") != "shutdown")
return 8; return 1;
std::string result = R"({ std::string result = R"({
"jsonrpc": "2.0", "jsonrpc": "2.0",
"id": "2", "id": "7",
"result": {} "result": {}
})"; })";
std::cout << "Content-Length: " << result.size() << "\r\n\r\n" std::cout << "Content-Length: " << result.size() << "\r\n\r\n"
<< result; << result;
@ -359,11 +575,11 @@ int main() {
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
boost::property_tree::json_parser::read_json(ss, pt); boost::property_tree::json_parser::read_json(ss, pt);
if(pt.get<std::string>("method") != "exit") if(pt.get<std::string>("method") != "exit")
return 9; return 1;
} }
} }
catch(const std::exception &e) { catch(const std::exception &e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return 100; return 2;
} }
} }

3
tests/language_protocol_test_files/main.rs

@ -1,3 +1,4 @@
fn main() { fn main() {
println!("Hello, world!"); let a = 2;
println!("{}", a);
} }

Loading…
Cancel
Save