diff --git a/src/command_line.cc b/src/command_line.cc index f262a88c..77955238 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -1035,7 +1035,7 @@ int main(int argc, char** argv) { if (HasOption(options, "--test-index")) { print_help = false; - RunIndexTests(); + RunIndexTests(options["--test-index"]); #if defined(_WIN32) std::cerr << std::endl << "[Enter] to exit" << std::endl; std::cin.get(); @@ -1058,7 +1058,9 @@ Command line options: Run as a language server. This implements the language server spec over STDIN and STDOUT. --test-unit Run unit tests. - --test-index Run index tests. + --test-index + 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 Print stdin and stdout messages to stderr. This is a aid for developing new language clients, as it makes it easier to figure diff --git a/src/test.cc b/src/test.cc index d2a791bf..e1dcaefd 100644 --- a/src/test.cc +++ b/src/test.cc @@ -107,7 +107,7 @@ IndexFile* FindDbForPathEnding( return nullptr; } -void RunIndexTests() { +void RunIndexTests(const std::string& filter_path) { SetTestOutputMode(); // TODO: Assert that we need to be on clang >= 3.9.1 @@ -120,7 +120,24 @@ void RunIndexTests() { 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 flags; + std::unordered_map 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; FileConsumer::SharedState file_consumer_shared; @@ -129,20 +146,49 @@ void RunIndexTests() { // std::cout << "[START] " << path << std::endl; PerformanceImportFile perf; std::vector> dbs = - Parse(&config, &file_consumer_shared, path, - {"-xc++", "-std=c++11", - "-resource-dir=" + GetDefaultResourceDirectory()}, + Parse(&config, &file_consumer_shared, path, flags, {}, &perf, &index, false /*dump_ast*/); - // Parse expected output from the test, parse it into JSON document. - std::unordered_map all_expected_output = - ParseTestExpectation(path); for (auto& entry : all_expected_output) { const std::string& expected_path = entry.first; 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. 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 = "{}"; if (db) { VerifySerializeToFrom(db); diff --git a/src/test.h b/src/test.h index 7f7aee84..3e88f02c 100644 --- a/src/test.h +++ b/src/test.h @@ -1,3 +1,5 @@ #pragma once -void RunIndexTests(); \ No newline at end of file +#include + +void RunIndexTests(const std::string& filter_path); diff --git a/src/utils.cc b/src/utils.cc index fa7f618d..d7d4ca33 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -281,9 +281,7 @@ std::vector ToLines(const std::string& content, } std::unordered_map ParseTestExpectation( - std::string filename) { - bool in_output = false; - + std::string filename, std::vector* flags) { #if false #include "bar.h" @@ -292,6 +290,12 @@ std::unordered_map ParseTestExpectation( /* // if no name is given assume to be this file name // 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 {} @@ -305,11 +309,29 @@ std::unordered_map ParseTestExpectation( std::string active_output_filename; 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)) { if (StartsWith(line_with_ending, "*/")) break; if (StartsWith(line_with_ending, "OUTPUT:")) { + // Terminate the previous output section if we found a new one. if (in_output) { result[active_output_filename] = active_output_contents; } diff --git a/src/utils.h b/src/utils.h index f67775d5..a9b33f87 100644 --- a/src/utils.h +++ b/src/utils.h @@ -79,7 +79,8 @@ std::vector ToLines(const std::string& content, bool trim_whitespace); std::unordered_map ParseTestExpectation( - std::string filename); + std::string filename, + std::vector* flags); void UpdateTestExpectation(const std::string& filename, const std::string& expectation, const std::string& actual); @@ -163,4 +164,4 @@ float GetProcessMemoryUsedInMb(); std::string FormatMicroseconds(long long microseconds); -std::string GetDefaultResourceDirectory(); \ No newline at end of file +std::string GetDefaultResourceDirectory();