| #include <cstddef> |
| #include <iostream> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "cmsys/FStream.hxx" |
| |
| #include "cmGccDepfileReader.h" |
| #include "cmGccDepfileReaderTypes.h" // for cmGccDepfileContent, cmGccStyle... |
| #include "cmSystemTools.h" |
| |
| namespace { |
| |
| cmGccDepfileContent readPlainDepfile(const char* filePath) |
| { |
| cmGccDepfileContent result; |
| cmsys::ifstream is(filePath); |
| if (!is.is_open()) |
| return result; |
| std::string line; |
| |
| cmGccStyleDependency dep; |
| bool readingRules = true; |
| while (cmSystemTools::GetLineFromStream(is, line)) { |
| if (line == "--RULES--") { |
| if (!dep.rules.empty()) { |
| result.push_back(std::move(dep)); |
| dep = cmGccStyleDependency(); |
| } |
| readingRules = true; |
| } else if (line == "--DEPENDENCIES--") { |
| readingRules = false; |
| } else { |
| std::vector<std::string>& dst = readingRules ? dep.rules : dep.paths; |
| dst.push_back(std::move(line)); |
| line = std::string(); |
| } |
| } |
| |
| if (!dep.rules.empty()) { |
| result.push_back(std::move(dep)); |
| } |
| |
| return result; |
| } |
| |
| bool compare(const std::vector<std::string>& actual, |
| const std::vector<std::string>& expected, const char* msg) |
| { |
| if (actual.size() != expected.size()) { |
| std::cerr << msg << "expected " << expected.size() << " entries." |
| << std::endl |
| << "Actual number of entries: " << actual.size() << std::endl; |
| return false; |
| } |
| for (std::size_t i = 0; i < actual.size(); ++i) { |
| if (actual[i] != expected[i]) { |
| std::cerr << msg << std::endl |
| << "expected: " << expected[i] << std::endl |
| << "actual: " << actual[i] << std::endl; |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| bool compare(const cmGccDepfileContent& actual, |
| const cmGccDepfileContent& expected) |
| { |
| if (actual.size() != expected.size()) { |
| std::cerr << "Expected " << expected.size() << " entries." << std::endl |
| << "Actual number of entries: " << actual.size() << std::endl; |
| return false; |
| } |
| for (std::size_t i = 0; i < actual.size(); ++i) { |
| if (!compare(actual[i].rules, expected[i].rules, "Rules differ: ") || |
| !compare(actual[i].paths, expected[i].paths, "Paths differ: ")) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| void dump(const char* label, const cmGccDepfileContent& dfc) |
| { |
| std::cerr << label << std::endl; |
| for (const auto& entry : dfc) { |
| auto rit = entry.rules.cbegin(); |
| if (rit != entry.rules.cend()) { |
| std::cerr << *rit; |
| for (++rit; rit != entry.rules.cend(); ++rit) { |
| std::cerr << " " << *rit; |
| } |
| std::cerr << ": " << std::endl; |
| } |
| for (const auto& path : entry.paths) { |
| std::cerr << " " << path << std::endl; |
| } |
| } |
| } |
| |
| } // anonymous namespace |
| |
| int testGccDepfileReader(int argc, char* argv[]) |
| { |
| if (argc < 2) { |
| std::cout << "Invalid arguments.\n"; |
| return -1; |
| } |
| |
| std::string dataDirPath = argv[1]; |
| dataDirPath += "/testGccDepfileReader_data"; |
| const int numberOfTestFiles = 3; |
| for (int i = 1; i <= numberOfTestFiles; ++i) { |
| const std::string base = dataDirPath + "/deps" + std::to_string(i); |
| const std::string depfile = base + ".d"; |
| const std::string plainDepfile = base + ".txt"; |
| std::cout << "Comparing " << base << " with " << plainDepfile << std::endl; |
| const auto actual = cmReadGccDepfile(depfile.c_str()); |
| const auto expected = readPlainDepfile(plainDepfile.c_str()); |
| if (!compare(actual, expected)) { |
| dump("actual", actual); |
| dump("expected", expected); |
| return 1; |
| } |
| } |
| |
| return 0; |
| } |