Some changes to index tests:

- Add EXTRA_FLAGS: which lets a test specify additional command line
flags to pass to clang.
- Show diagnostics in the terminal after indexing the file.
- Allow the user to pass a test filter/file on the command line (ie,
cquery --test-index foo.cc)
This commit is contained in:
Jacob Dufault 2017-12-20 09:10:57 -08:00
parent 4bf8dbe3ea
commit e26f1caaba
5 changed files with 89 additions and 16 deletions

View File

@ -1035,7 +1035,7 @@ int main(int argc, char** argv) {
if (HasOption(options, "--test-index")) { if (HasOption(options, "--test-index")) {
print_help = false; print_help = false;
RunIndexTests(); RunIndexTests(options["--test-index"]);
#if defined(_WIN32) #if defined(_WIN32)
std::cerr << std::endl << "[Enter] to exit" << std::endl; std::cerr << std::endl << "[Enter] to exit" << std::endl;
std::cin.get(); std::cin.get();
@ -1058,7 +1058,9 @@ Command line options:
Run as a language server. This implements the language server Run as a language server. This implements the language server
spec over STDIN and STDOUT. spec over STDIN and STDOUT.
--test-unit Run unit tests. --test-unit Run unit tests.
--test-index Run index tests. --test-index <opt_filter_path>
Run index tests. opt_filter_path can be used to specify which
test to run. If not provided all tests are run.
--log-stdin-stdout-to-stderr --log-stdin-stdout-to-stderr
Print stdin and stdout messages to stderr. This is a aid for Print stdin and stdout messages to stderr. This is a aid for
developing new language clients, as it makes it easier to figure developing new language clients, as it makes it easier to figure

View File

@ -107,7 +107,7 @@ IndexFile* FindDbForPathEnding(
return nullptr; return nullptr;
} }
void RunIndexTests() { void RunIndexTests(const std::string& filter_path) {
SetTestOutputMode(); SetTestOutputMode();
// TODO: Assert that we need to be on clang >= 3.9.1 // TODO: Assert that we need to be on clang >= 3.9.1
@ -120,7 +120,24 @@ void RunIndexTests() {
float memory_after = -1.; float memory_after = -1.;
{ {
// if (path != "tests/inheritance/multiple_base_functions.cc") continue; if (!EndsWith(path, filter_path))
continue;
// Parse expected output from the test, parse it into JSON document.
std::vector<std::string> flags;
std::unordered_map<std::string, std::string> all_expected_output =
ParseTestExpectation(path, &flags);
bool had_extra_flags = !flags.empty();
if (!AnyStartsWith(flags, "-x"))
flags.push_back("-xc++");
if (!AnyStartsWith(flags, "-std"))
flags.push_back("-std=c++11");
flags.push_back("-resource_dir=" + GetDefaultResourceDirectory());
if (had_extra_flags) {
std::cout << "For " << path << std::endl;
std::cout << " flags: " << StringJoin(flags) << std::endl;
}
Config config; Config config;
FileConsumer::SharedState file_consumer_shared; FileConsumer::SharedState file_consumer_shared;
@ -129,20 +146,49 @@ void RunIndexTests() {
// std::cout << "[START] " << path << std::endl; // std::cout << "[START] " << path << std::endl;
PerformanceImportFile perf; PerformanceImportFile perf;
std::vector<std::unique_ptr<IndexFile>> dbs = std::vector<std::unique_ptr<IndexFile>> dbs =
Parse(&config, &file_consumer_shared, path, Parse(&config, &file_consumer_shared, path, flags,
{"-xc++", "-std=c++11",
"-resource-dir=" + GetDefaultResourceDirectory()},
{}, &perf, &index, false /*dump_ast*/); {}, &perf, &index, false /*dump_ast*/);
// Parse expected output from the test, parse it into JSON document.
std::unordered_map<std::string, std::string> all_expected_output =
ParseTestExpectation(path);
for (auto& entry : all_expected_output) { for (auto& entry : all_expected_output) {
const std::string& expected_path = entry.first; const std::string& expected_path = entry.first;
const std::string& expected_output = entry.second; const std::string& expected_output = entry.second;
// FIXME: promote to utils, find and remove duplicates (ie,
// cquery_call_tree.cc, maybe something in project.cc).
auto basename = [](const std::string& path) {
size_t last_index = path.find_last_of('/');
if (last_index == std::string::npos)
return path;
return path.substr(last_index + 1);
};
auto severity_to_string = [](const lsDiagnosticSeverity& severity) {
switch (severity) {
case lsDiagnosticSeverity::Error:
return "error ";
case lsDiagnosticSeverity::Warning:
return "warning ";
case lsDiagnosticSeverity::Information:
return "information ";
case lsDiagnosticSeverity::Hint:
return "hint ";
}
assert(false && "not reached");
};
// Get output from index operation. // Get output from index operation.
IndexFile* db = FindDbForPathEnding(expected_path, dbs); IndexFile* db = FindDbForPathEnding(expected_path, dbs);
if (!db->diagnostics_.empty()) {
for (const lsDiagnostic& diagnostic : db->diagnostics_) {
std::cout << " ";
if (diagnostic.severity)
std::cout << severity_to_string(*diagnostic.severity);
std::cout << basename(db->path) << ":"
<< diagnostic.range.start.ToString() << "-"
<< diagnostic.range.end.ToString() << ": "
<< diagnostic.message << std::endl;
}
}
std::string actual_output = "{}"; std::string actual_output = "{}";
if (db) { if (db) {
VerifySerializeToFrom(db); VerifySerializeToFrom(db);

View File

@ -1,3 +1,5 @@
#pragma once #pragma once
void RunIndexTests(); #include <string>
void RunIndexTests(const std::string& filter_path);

View File

@ -281,9 +281,7 @@ std::vector<std::string> ToLines(const std::string& content,
} }
std::unordered_map<std::string, std::string> ParseTestExpectation( std::unordered_map<std::string, std::string> ParseTestExpectation(
std::string filename) { std::string filename, std::vector<std::string>* flags) {
bool in_output = false;
#if false #if false
#include "bar.h" #include "bar.h"
@ -292,6 +290,12 @@ std::unordered_map<std::string, std::string> ParseTestExpectation(
/* /*
// if no name is given assume to be this file name // if no name is given assume to be this file name
// no output section means we don't check that index. // no output section means we don't check that index.
// EXTRA_FLAGS parses until the first newline.
EXTRA_FLAGS:
-std=c++14
OUTPUT: bar.cc OUTPUT: bar.cc
{} {}
@ -305,11 +309,29 @@ std::unordered_map<std::string, std::string> ParseTestExpectation(
std::string active_output_filename; std::string active_output_filename;
std::string active_output_contents; std::string active_output_contents;
bool in_output = false;
for (std::string line_with_ending : ReadLinesWithEnding(filename)) {
if (StartsWith(line_with_ending, "EXTRA_FLAGS:")) {
assert(!in_output && "multiple EXTRA_FLAGS sections");
in_output = true;
continue;
}
Trim(line_with_ending);
if (in_output && line_with_ending.empty())
break;
if (in_output)
flags->push_back(line_with_ending);
}
in_output = false;
for (std::string line_with_ending : ReadLinesWithEnding(filename)) { for (std::string line_with_ending : ReadLinesWithEnding(filename)) {
if (StartsWith(line_with_ending, "*/")) if (StartsWith(line_with_ending, "*/"))
break; break;
if (StartsWith(line_with_ending, "OUTPUT:")) { if (StartsWith(line_with_ending, "OUTPUT:")) {
// Terminate the previous output section if we found a new one.
if (in_output) { if (in_output) {
result[active_output_filename] = active_output_contents; result[active_output_filename] = active_output_contents;
} }

View File

@ -79,7 +79,8 @@ std::vector<std::string> ToLines(const std::string& content,
bool trim_whitespace); bool trim_whitespace);
std::unordered_map<std::string, std::string> ParseTestExpectation( std::unordered_map<std::string, std::string> ParseTestExpectation(
std::string filename); std::string filename,
std::vector<std::string>* flags);
void UpdateTestExpectation(const std::string& filename, void UpdateTestExpectation(const std::string& filename,
const std::string& expectation, const std::string& expectation,
const std::string& actual); const std::string& actual);