ccls/src/test.cc

207 lines
6.6 KiB
C++
Raw Normal View History

2017-03-10 07:06:01 +00:00
#include "test.h"
2017-02-27 07:28:33 +00:00
#include "indexer.h"
2017-03-25 20:15:00 +00:00
#include "platform.h"
2017-03-01 04:12:57 +00:00
#include "serializer.h"
2017-03-01 08:36:11 +00:00
#include "utils.h"
2017-02-27 07:28:33 +00:00
void Write(const std::vector<std::string>& strs) {
2017-03-01 04:12:57 +00:00
for (const std::string& str : strs)
2017-02-27 07:28:33 +00:00
std::cout << str << std::endl;
}
std::string ToString(const rapidjson::Document& document) {
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
writer.SetFormatOptions(
2017-09-22 01:14:57 +00:00
rapidjson::PrettyFormatOptions::kFormatSingleLineArray);
2017-02-27 07:28:33 +00:00
writer.SetIndent(' ', 2);
buffer.Clear();
document.Accept(writer);
return buffer.GetString();
}
2017-09-22 01:14:57 +00:00
void DiffDocuments(std::string path,
std::string path_section,
rapidjson::Document& expected,
rapidjson::Document& actual) {
2017-04-03 01:34:15 +00:00
std::string joined_actual_output = ToString(actual);
2017-09-22 01:14:57 +00:00
std::vector<std::string> actual_output =
SplitString(joined_actual_output, "\n");
2017-04-03 01:34:15 +00:00
std::string joined_expected_output = ToString(expected);
2017-09-22 01:14:57 +00:00
std::vector<std::string> expected_output =
SplitString(joined_expected_output, "\n");
2017-02-27 07:28:33 +00:00
2017-09-22 01:14:57 +00:00
std::cout << "[FAILED] " << path << " (section " << path_section << ")"
<< std::endl;
std::cout << "Expected output for " << path << " (section " << path_section
<< "):" << std::endl;
2017-04-03 01:34:15 +00:00
std::cout << joined_expected_output << std::endl;
2017-09-22 01:14:57 +00:00
std::cout << "Actual output for " << path << " (section " << path_section
<< "):" << std::endl;
2017-04-03 01:34:15 +00:00
std::cout << joined_actual_output << std::endl;
std::cout << std::endl;
int max_diff = 5;
2017-02-27 07:28:33 +00:00
size_t len = std::min(actual_output.size(), expected_output.size());
2017-02-27 07:28:33 +00:00
for (int i = 0; i < len; ++i) {
if (actual_output[i] != expected_output[i]) {
2017-04-03 01:34:15 +00:00
if (--max_diff < 0) {
std::cout << "(... more lines may differ ...)" << std::endl;
break;
}
2017-02-27 07:28:33 +00:00
std::cout << "Line " << i << " differs:" << std::endl;
std::cout << " expected: " << expected_output[i] << std::endl;
std::cout << " actual: " << actual_output[i] << std::endl;
}
}
if (actual_output.size() > len) {
std::cout << "Additional output in actual:" << std::endl;
for (size_t i = len; i < actual_output.size(); ++i)
2017-02-27 07:28:33 +00:00
std::cout << " " << actual_output[i] << std::endl;
}
if (expected_output.size() > len) {
std::cout << "Additional output in expected:" << std::endl;
for (size_t i = len; i < expected_output.size(); ++i)
2017-02-27 07:28:33 +00:00
std::cout << " " << expected_output[i] << std::endl;
}
}
void VerifySerializeToFrom(IndexFile* file) {
std::string expected = file->ToString();
2017-09-22 01:14:57 +00:00
std::unique_ptr<IndexFile> result =
Deserialize("--.cc", Serialize(*file), nullopt /*expected_version*/);
std::string actual = result->ToString();
2017-03-01 04:12:57 +00:00
if (expected != actual) {
2017-09-22 01:14:57 +00:00
std::cerr << "Serialization failure" << std::endl;
2017-03-01 04:12:57 +00:00
assert(false);
}
}
2017-09-22 01:14:57 +00:00
std::string FindExpectedOutputForFilename(
std::string filename,
const std::unordered_map<std::string, std::string>& expected) {
2017-04-08 22:54:36 +00:00
for (const auto& entry : expected) {
if (EndsWith(entry.first, filename))
return entry.second;
}
2017-02-27 07:28:33 +00:00
2017-04-08 22:54:36 +00:00
std::cerr << "Couldn't find expected output for " << filename << std::endl;
std::cin.get();
2017-02-27 07:28:33 +00:00
std::cin.get();
2017-04-08 22:54:36 +00:00
return "{}";
}
2017-09-22 01:14:57 +00:00
IndexFile* FindDbForPathEnding(
const std::string& path,
const std::vector<std::unique_ptr<IndexFile>>& dbs) {
2017-04-08 22:54:36 +00:00
for (auto& db : dbs) {
if (EndsWith(db->path, path))
return db.get();
}
return nullptr;
}
void RunIndexTests() {
SetTestOutputMode();
2017-04-08 22:54:36 +00:00
// TODO: Assert that we need to be on clang >= 3.9.1
bool update_all = false;
ClangIndex index;
2017-02-27 07:28:33 +00:00
2017-09-22 01:14:57 +00:00
for (std::string path : GetFilesInFolder("tests", true /*recursive*/,
true /*add_folder_to_path*/)) {
float memory_before = GetProcessMemoryUsedInMb();
float memory_after = -1.;
{
2017-12-19 06:15:46 +00:00
// if (path != "tests/inheritance/multiple_base_functions.cc") continue;
Config config;
FileConsumer::SharedState file_consumer_shared;
// Run test.
2017-09-22 01:14:57 +00:00
// std::cout << "[START] " << path << std::endl;
PerformanceImportFile perf;
2017-12-02 01:11:27 +00:00
std::vector<std::unique_ptr<IndexFile>> dbs =
Parse(&config, &file_consumer_shared, path,
{"-xc++", "-std=c++11",
"-resource-dir=" + GetDefaultResourceDirectory()},
2017-12-02 01:11:27 +00:00
{}, &perf, &index, false /*dump_ast*/);
// Parse expected output from the test, parse it into JSON document.
2017-09-22 01:14:57 +00:00
std::unordered_map<std::string, std::string> 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;
// Get output from index operation.
IndexFile* db = FindDbForPathEnding(expected_path, dbs);
std::string actual_output = "{}";
if (db) {
VerifySerializeToFrom(db);
actual_output = db->ToString();
}
// Compare output via rapidjson::Document to ignore any formatting
// differences.
rapidjson::Document actual;
actual.Parse(actual_output.c_str());
rapidjson::Document expected;
expected.Parse(expected_output.c_str());
if (actual == expected) {
std::cout << "[PASSED] " << path << std::endl;
2017-09-22 01:14:57 +00:00
} else {
DiffDocuments(path, expected_path, expected, actual);
std::cout << std::endl;
std::cout << std::endl;
2017-09-22 01:14:57 +00:00
std::cout
<< "[Enter to continue - type u to update test, a to update all]";
char c = 'u';
if (!update_all) {
c = (char)std::cin.get();
std::cin.get();
}
if (c == 'a')
update_all = true;
if (update_all || c == 'u') {
2017-09-22 01:14:57 +00:00
UpdateTestExpectation(path, expected_output,
ToString(actual) + "\n");
}
}
2017-04-08 22:54:36 +00:00
}
memory_after = GetProcessMemoryUsedInMb();
2017-02-27 07:28:33 +00:00
}
float memory_cleanup = GetProcessMemoryUsedInMb();
2017-09-22 01:14:57 +00:00
std::cerr << "[memory] before=" << memory_before
<< "mb, after=" << memory_after
<< "mb, cleanup=" << memory_cleanup << "mb" << std::endl;
2017-02-27 07:28:33 +00:00
}
2017-09-22 01:14:57 +00:00
std::cerr << "[final presleep] " << GetProcessMemoryUsedInMb() << "mb"
<< std::endl;
// std::this_thread::sleep_for(std::chrono::seconds(10));
// std::cerr << "[final postsleep] " << GetProcessMemoryUsedInMb() << "mb" <<
// std::endl;
std::cerr << std::endl;
std::cerr << std::endl;
std::cerr << std::endl;
std::cerr << std::endl;
std::cerr << std::endl;
2017-02-27 07:28:33 +00:00
}
// TODO: ctor/dtor, copy ctor
2017-09-22 01:14:57 +00:00
// TODO: Always pass IndexFile by pointer, ie, search and remove all IndexFile&
// refs.