Merge "Extend header-abi-dumper/linker --root-dir" am: ece19b2c70
Original change: https://android-review.googlesource.com/c/platform/development/+/1761252 Change-Id: I62671415596fd0ce386650c9390e63959bc94ef9
This commit is contained in:
@@ -69,7 +69,7 @@ ABIWrapper::ABIWrapper(
|
||||
|
||||
std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl,
|
||||
const clang::CompilerInstance *cip,
|
||||
const std::string &root_dir) {
|
||||
const utils::RootDirs &root_dirs) {
|
||||
clang::SourceManager &sm = cip->getSourceManager();
|
||||
clang::SourceLocation location = decl->getLocation();
|
||||
// We need to use the expansion location to identify whether we should recurse
|
||||
@@ -80,7 +80,7 @@ std::string ABIWrapper::GetDeclSourceFile(const clang::Decl *decl,
|
||||
// belonging to the library.
|
||||
clang::SourceLocation expansion_location = sm.getExpansionLoc(location);
|
||||
return utils::NormalizePath(sm.getFilename(expansion_location).str(),
|
||||
root_dir);
|
||||
root_dirs);
|
||||
}
|
||||
|
||||
std::string ABIWrapper::GetCachedDeclSourceFile(
|
||||
@@ -88,7 +88,7 @@ std::string ABIWrapper::GetCachedDeclSourceFile(
|
||||
assert(decl != nullptr);
|
||||
auto result = ast_caches_->decl_to_source_file_cache_.find(decl);
|
||||
if (result == ast_caches_->decl_to_source_file_cache_.end()) {
|
||||
return GetDeclSourceFile(decl, cip, ast_caches_->root_dir_);
|
||||
return GetDeclSourceFile(decl, cip, ast_caches_->root_dirs_);
|
||||
}
|
||||
return result->second;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class ABIWrapper {
|
||||
public:
|
||||
static std::string GetDeclSourceFile(const clang::Decl *decl,
|
||||
const clang::CompilerInstance *cip,
|
||||
const std::string &root_dir);
|
||||
const utils::RootDirs &root_dirs);
|
||||
|
||||
protected:
|
||||
std::string GetCachedDeclSourceFile(const clang::Decl *decl,
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include "dumper/abi_wrappers.h"
|
||||
#include "repr/ir_dumper.h"
|
||||
#include "utils/header_abi_util.h"
|
||||
|
||||
#include <clang/AST/PrettyPrinter.h>
|
||||
#include <clang/AST/QualTypeNames.h>
|
||||
@@ -33,14 +32,15 @@ namespace dumper {
|
||||
|
||||
class PrintNormalizedPath : public clang::PrintingCallbacks {
|
||||
public:
|
||||
PrintNormalizedPath(const std::string root_dir) : root_dir_(root_dir) {}
|
||||
PrintNormalizedPath(const utils::RootDirs &root_dirs)
|
||||
: root_dirs_(root_dirs) {}
|
||||
|
||||
std::string remapPath(llvm::StringRef path) const {
|
||||
return utils::NormalizePath(path.str(), root_dir_);
|
||||
return utils::NormalizePath(path.str(), root_dirs_);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string root_dir_;
|
||||
const utils::RootDirs &root_dirs_;
|
||||
};
|
||||
|
||||
HeaderASTVisitor::HeaderASTVisitor(
|
||||
@@ -106,7 +106,7 @@ bool HeaderASTVisitor::ShouldSkipFunctionDecl(const clang::FunctionDecl *decl) {
|
||||
if (!decl->getDefinition()) {
|
||||
if (!options_.dump_function_declarations_ ||
|
||||
options_.source_file_ !=
|
||||
ABIWrapper::GetDeclSourceFile(decl, cip_, options_.root_dir_)) {
|
||||
ABIWrapper::GetDeclSourceFile(decl, cip_, options_.root_dirs_)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@ bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) {
|
||||
return true;
|
||||
}
|
||||
std::string source_file =
|
||||
ABIWrapper::GetDeclSourceFile(decl, cip_, options_.root_dir_);
|
||||
ABIWrapper::GetDeclSourceFile(decl, cip_, options_.root_dirs_);
|
||||
ast_caches_->decl_to_source_file_cache_.insert(
|
||||
std::make_pair(decl, source_file));
|
||||
// If no exported headers are specified we assume the whole AST is exported.
|
||||
@@ -208,15 +208,15 @@ void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
|
||||
// names to avoid inconsistency between C and C++ (for C++ files, this is true
|
||||
// by default)
|
||||
policy.SuppressTagKeyword = true;
|
||||
PrintNormalizedPath callbacks(options_.root_dir_);
|
||||
PrintNormalizedPath callbacks(options_.root_dirs_);
|
||||
policy.Callbacks = &callbacks;
|
||||
ctx.setPrintingPolicy(policy);
|
||||
clang::TranslationUnitDecl *translation_unit = ctx.getTranslationUnitDecl();
|
||||
std::unique_ptr<clang::MangleContext> mangle_contextp(
|
||||
ctx.createMangleContext());
|
||||
ASTCaches ast_caches(
|
||||
ABIWrapper::GetDeclSourceFile(translation_unit, cip_, options_.root_dir_),
|
||||
options_.root_dir_);
|
||||
ASTCaches ast_caches(ABIWrapper::GetDeclSourceFile(translation_unit, cip_,
|
||||
options_.root_dirs_),
|
||||
options_.root_dirs_);
|
||||
|
||||
std::unique_ptr<repr::ModuleIR> module(
|
||||
new repr::ModuleIR(nullptr /*FIXME*/));
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#ifndef AST_UTIL_H_
|
||||
#define AST_UTIL_H_
|
||||
|
||||
#include "utils/source_path_utils.h"
|
||||
|
||||
#include <clang/AST/AST.h>
|
||||
#include <clang/AST/Type.h>
|
||||
|
||||
@@ -30,12 +32,12 @@ namespace dumper {
|
||||
|
||||
struct ASTCaches {
|
||||
ASTCaches(const std::string &translation_unit_source,
|
||||
const std::string &root_dir)
|
||||
: translation_unit_source_(translation_unit_source), root_dir_(root_dir) {
|
||||
}
|
||||
const utils::RootDirs &root_dirs)
|
||||
: translation_unit_source_(translation_unit_source),
|
||||
root_dirs_(root_dirs) {}
|
||||
|
||||
std::string translation_unit_source_;
|
||||
const std::string root_dir_;
|
||||
const utils::RootDirs &root_dirs_;
|
||||
std::map<const clang::Decl *, std::string> decl_to_source_file_cache_;
|
||||
|
||||
llvm::DenseSet<clang::QualType> converted_qual_types_;
|
||||
|
||||
@@ -42,9 +42,11 @@ using header_checker::dumper::HeaderCheckerFrontendActionFactory;
|
||||
using header_checker::dumper::HeaderCheckerOptions;
|
||||
using header_checker::repr::TextFormatIR;
|
||||
using header_checker::utils::CollectAllExportedHeaders;
|
||||
using header_checker::utils::GetCwd;
|
||||
using header_checker::utils::HideIrrelevantCommandLineOptions;
|
||||
using header_checker::utils::NormalizePath;
|
||||
using header_checker::utils::ParseRootDirs;
|
||||
using header_checker::utils::RootDir;
|
||||
using header_checker::utils::RootDirs;
|
||||
|
||||
|
||||
static llvm::cl::OptionCategory header_checker_category(
|
||||
@@ -63,11 +65,13 @@ static llvm::cl::list<std::string> exported_header_dirs(
|
||||
"I", llvm::cl::desc("<export_include_dirs>"), llvm::cl::Prefix,
|
||||
llvm::cl::ZeroOrMore, llvm::cl::cat(header_checker_category));
|
||||
|
||||
static llvm::cl::opt<std::string> root_dir(
|
||||
static llvm::cl::list<std::string> root_dirs(
|
||||
"root-dir",
|
||||
llvm::cl::desc("Specify the directory that the paths in the dump file are "
|
||||
"relative to. Default to current working directory"),
|
||||
llvm::cl::Optional, llvm::cl::cat(header_checker_category));
|
||||
llvm::cl::desc("Specify the directory that the paths in the dump files "
|
||||
"are relative to. The format is <path>:<replacement> or "
|
||||
"<path>. If this option is not specified, it defaults to "
|
||||
"current working directory."),
|
||||
llvm::cl::ZeroOrMore, llvm::cl::cat(header_checker_category));
|
||||
|
||||
static llvm::cl::opt<bool> no_filter(
|
||||
"no-filter", llvm::cl::desc("Do not filter any abi"), llvm::cl::Optional,
|
||||
@@ -172,17 +176,17 @@ int main(int argc, const char **argv) {
|
||||
::exit(1);
|
||||
}
|
||||
|
||||
const std::string root_dir_or_cwd = (root_dir.empty() ? GetCwd() : root_dir);
|
||||
RootDirs parsed_root_dirs = ParseRootDirs(root_dirs);
|
||||
|
||||
bool dump_exported_only = (!no_filter && !exported_header_dirs.empty());
|
||||
std::set<std::string> exported_headers =
|
||||
CollectAllExportedHeaders(exported_header_dirs, root_dir_or_cwd);
|
||||
CollectAllExportedHeaders(exported_header_dirs, parsed_root_dirs);
|
||||
|
||||
// Initialize clang tools and run front-end action.
|
||||
std::vector<std::string> header_files{ header_file };
|
||||
HeaderCheckerOptions options(
|
||||
NormalizePath(header_file, root_dir_or_cwd), out_dump,
|
||||
std::move(exported_headers), root_dir_or_cwd, output_format,
|
||||
NormalizePath(header_file, parsed_root_dirs), out_dump,
|
||||
std::move(exported_headers), std::move(parsed_root_dirs), output_format,
|
||||
dump_exported_only, dump_function_declarations, suppress_errors);
|
||||
|
||||
clang::tooling::ClangTool tool(*compilations, header_files);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define HEADER_CHECKER_H_
|
||||
|
||||
#include "repr/ir_representation.h"
|
||||
#include "utils/source_path_utils.h"
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
@@ -30,7 +31,7 @@ class HeaderCheckerOptions {
|
||||
std::string source_file_;
|
||||
std::string dump_name_;
|
||||
const std::set<std::string> exported_headers_;
|
||||
const std::string root_dir_;
|
||||
const utils::RootDirs root_dirs_;
|
||||
repr::TextFormatIR text_format_;
|
||||
const bool dump_exported_only_;
|
||||
bool dump_function_declarations_;
|
||||
@@ -39,12 +40,12 @@ class HeaderCheckerOptions {
|
||||
public:
|
||||
HeaderCheckerOptions(std::string source_file, std::string dump_name,
|
||||
std::set<std::string> exported_headers,
|
||||
std::string root_dir, repr::TextFormatIR text_format,
|
||||
bool dump_exported_only,
|
||||
utils::RootDirs root_dirs,
|
||||
repr::TextFormatIR text_format, bool dump_exported_only,
|
||||
bool dump_function_declarations, bool suppress_errors)
|
||||
: source_file_(std::move(source_file)), dump_name_(std::move(dump_name)),
|
||||
exported_headers_(std::move(exported_headers)),
|
||||
root_dir_(std::move(root_dir)), text_format_(text_format),
|
||||
root_dirs_(std::move(root_dirs)), text_format_(text_format),
|
||||
dump_exported_only_(dump_exported_only),
|
||||
dump_function_declarations_(dump_function_declarations),
|
||||
suppress_errors_(suppress_errors) {}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "repr/symbol/so_file_parser.h"
|
||||
#include "repr/symbol/version_script_parser.h"
|
||||
#include "utils/command_line_utils.h"
|
||||
#include "utils/header_abi_util.h"
|
||||
#include "utils/source_path_utils.h"
|
||||
|
||||
#include <llvm/ADT/Optional.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
@@ -39,8 +39,9 @@
|
||||
using namespace header_checker;
|
||||
using header_checker::repr::TextFormatIR;
|
||||
using header_checker::utils::CollectAllExportedHeaders;
|
||||
using header_checker::utils::GetCwd;
|
||||
using header_checker::utils::HideIrrelevantCommandLineOptions;
|
||||
using header_checker::utils::ParseRootDirs;
|
||||
using header_checker::utils::RootDir;
|
||||
|
||||
|
||||
static llvm::cl::OptionCategory header_linker_category(
|
||||
@@ -58,11 +59,13 @@ static llvm::cl::list<std::string> exported_header_dirs(
|
||||
"I", llvm::cl::desc("<export_include_dirs>"), llvm::cl::Prefix,
|
||||
llvm::cl::ZeroOrMore, llvm::cl::cat(header_linker_category));
|
||||
|
||||
static llvm::cl::opt<std::string> root_dir(
|
||||
static llvm::cl::list<std::string> root_dirs(
|
||||
"root-dir",
|
||||
llvm::cl::desc("Specify the directory that the paths in the dump files are "
|
||||
"relative to. Default to current working directory"),
|
||||
llvm::cl::Optional, llvm::cl::cat(header_linker_category));
|
||||
llvm::cl::desc("Specify the directory that the paths in the dump files "
|
||||
"are relative to. The format is <path>:<replacement> or "
|
||||
"<path>. If this option is not specified, it defaults to "
|
||||
"current working directory."),
|
||||
llvm::cl::ZeroOrMore, llvm::cl::cat(header_linker_category));
|
||||
|
||||
static llvm::cl::opt<std::string> version_script(
|
||||
"v", llvm::cl::desc("<version_script>"), llvm::cl::Optional,
|
||||
@@ -255,8 +258,8 @@ bool HeaderAbiLinker::LinkAndDump() {
|
||||
}
|
||||
|
||||
// Construct the list of exported headers for source location filtering.
|
||||
exported_headers_ = CollectAllExportedHeaders(
|
||||
exported_header_dirs_, root_dir.empty() ? GetCwd() : root_dir);
|
||||
exported_headers_ = CollectAllExportedHeaders(exported_header_dirs_,
|
||||
ParseRootDirs(root_dirs));
|
||||
|
||||
// Read all input ABI dumps.
|
||||
auto merger = ReadInputDumpFiles();
|
||||
|
||||
@@ -26,16 +26,6 @@ namespace header_checker {
|
||||
namespace utils {
|
||||
|
||||
|
||||
std::string GetCwd();
|
||||
|
||||
// Resolve '..' and '.'; if the path starts with root_dir, remove the prefix;
|
||||
// don't resolve symbolic links.
|
||||
std::string NormalizePath(const std::string &path, const std::string &root_dir);
|
||||
|
||||
std::set<std::string>
|
||||
CollectAllExportedHeaders(const std::vector<std::string> &exported_header_dirs,
|
||||
const std::string &root_dir);
|
||||
|
||||
inline std::string FindAndReplace(const std::string &candidate_str,
|
||||
const std::string &find_str,
|
||||
const std::string &replace_str) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "utils/header_abi_util.h"
|
||||
#include "utils/source_path_utils.h"
|
||||
|
||||
#include <llvm/Support/FileSystem.h>
|
||||
#include <llvm/Support/Path.h>
|
||||
@@ -37,33 +37,87 @@ static bool ShouldSkipFile(llvm::StringRef &file_name) {
|
||||
file_name.endswith(".cc") || file_name.endswith(".c"));
|
||||
}
|
||||
|
||||
std::string GetCwd() {
|
||||
static std::string GetCwd() {
|
||||
llvm::SmallString<256> cwd;
|
||||
if (llvm::sys::fs::current_path(cwd)) {
|
||||
llvm::errs() << "ERROR: Failed to get current working directory\n";
|
||||
::exit(1);
|
||||
}
|
||||
return cwd.c_str();
|
||||
return std::string(cwd);
|
||||
}
|
||||
|
||||
std::string NormalizePath(const std::string &path,
|
||||
const std::string &root_dir) {
|
||||
llvm::SmallString<256> norm_path(path);
|
||||
RootDirs ParseRootDirs(const std::vector<std::string> &args) {
|
||||
RootDirs root_dirs;
|
||||
for (const std::string_view arg : args) {
|
||||
std::string_view path;
|
||||
std::string_view replacement;
|
||||
size_t colon_index = arg.find(":");
|
||||
if (colon_index != std::string_view::npos) {
|
||||
path = arg.substr(0, colon_index);
|
||||
replacement = arg.substr(colon_index + 1);
|
||||
} else {
|
||||
path = arg;
|
||||
replacement = "";
|
||||
}
|
||||
llvm::SmallString<256> norm_replacement(replacement.begin(),
|
||||
replacement.end());
|
||||
llvm::sys::path::remove_dots(norm_replacement, /* remove_dot_dot = */ true);
|
||||
root_dirs.emplace_back(NormalizePath(path, {}),
|
||||
std::string(norm_replacement));
|
||||
}
|
||||
if (root_dirs.empty()) {
|
||||
root_dirs.emplace_back(GetCwd(), "");
|
||||
}
|
||||
// Sort by length in descending order so that NormalizePath finds the longest
|
||||
// matching root dir.
|
||||
std::sort(root_dirs.begin(), root_dirs.end(),
|
||||
[](RootDir &first, RootDir &second) {
|
||||
return first.path.size() > second.path.size();
|
||||
});
|
||||
for (size_t index = 1; index < root_dirs.size(); index++) {
|
||||
if (root_dirs[index - 1].path == root_dirs[index].path) {
|
||||
llvm::errs() << "Duplicate root dir: " << root_dirs[index].path << "\n";
|
||||
::exit(1);
|
||||
}
|
||||
}
|
||||
return root_dirs;
|
||||
}
|
||||
|
||||
std::string NormalizePath(std::string_view path, const RootDirs &root_dirs) {
|
||||
llvm::SmallString<256> norm_path(path.begin(), path.end());
|
||||
if (llvm::sys::fs::make_absolute(norm_path)) {
|
||||
return "";
|
||||
}
|
||||
llvm::sys::path::remove_dots(norm_path, /* remove_dot_dot = */ true);
|
||||
// Convert /cwd/path to /path.
|
||||
if (llvm::sys::path::replace_path_prefix(norm_path, root_dir, "")) {
|
||||
// Convert /path to path.
|
||||
return llvm::sys::path::relative_path(norm_path.str()).str();
|
||||
llvm::StringRef separator = llvm::sys::path::get_separator();
|
||||
// Convert /root/dir/path to path.
|
||||
for (const RootDir &root_dir : root_dirs) {
|
||||
// llvm::sys::path::replace_path_prefix("AB", "A", "") returns "B", so do
|
||||
// not use it.
|
||||
if (!norm_path.startswith(root_dir.path)) {
|
||||
continue;
|
||||
}
|
||||
if (norm_path.size() == root_dir.path.size()) {
|
||||
return root_dir.replacement;
|
||||
}
|
||||
llvm::StringRef suffix = norm_path.substr(root_dir.path.size());
|
||||
if (suffix.startswith(separator)) {
|
||||
if (root_dir.replacement.empty()) {
|
||||
return suffix.substr(separator.size()).str();
|
||||
}
|
||||
// replacement == "/"
|
||||
if (llvm::StringRef(root_dir.replacement).endswith(separator)) {
|
||||
return root_dir.replacement + suffix.substr(separator.size()).str();
|
||||
}
|
||||
return root_dir.replacement + suffix.str();
|
||||
}
|
||||
}
|
||||
return std::string(norm_path);
|
||||
}
|
||||
|
||||
static bool CollectExportedHeaderSet(const std::string &dir_name,
|
||||
std::set<std::string> *exported_headers,
|
||||
const std::string &root_dir) {
|
||||
const RootDirs &root_dirs) {
|
||||
std::error_code ec;
|
||||
llvm::sys::fs::recursive_directory_iterator walker(dir_name, ec);
|
||||
// Default construction - end of directory.
|
||||
@@ -98,17 +152,17 @@ static bool CollectExportedHeaderSet(const std::string &dir_name,
|
||||
continue;
|
||||
}
|
||||
|
||||
exported_headers->insert(NormalizePath(file_path, root_dir));
|
||||
exported_headers->insert(NormalizePath(file_path, root_dirs));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<std::string>
|
||||
CollectAllExportedHeaders(const std::vector<std::string> &exported_header_dirs,
|
||||
const std::string &root_dir) {
|
||||
const RootDirs &root_dirs) {
|
||||
std::set<std::string> exported_headers;
|
||||
for (auto &&dir : exported_header_dirs) {
|
||||
if (!CollectExportedHeaderSet(dir, &exported_headers, root_dir)) {
|
||||
if (!CollectExportedHeaderSet(dir, &exported_headers, root_dirs)) {
|
||||
llvm::errs() << "Couldn't collect exported headers\n";
|
||||
::exit(1);
|
||||
}
|
||||
|
||||
52
vndk/tools/header-checker/src/utils/source_path_utils.h
Normal file
52
vndk/tools/header-checker/src/utils/source_path_utils.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2021 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SOURCE_PATH_UTILS_H_
|
||||
#define SOURCE_PATH_UTILS_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace header_checker {
|
||||
namespace utils {
|
||||
|
||||
|
||||
struct RootDir {
|
||||
std::string path;
|
||||
std::string replacement;
|
||||
|
||||
RootDir(std::string p, std::string r)
|
||||
: path(std::move(p)), replacement(std::move(r)) {}
|
||||
};
|
||||
|
||||
typedef std::vector<RootDir> RootDirs;
|
||||
|
||||
RootDirs ParseRootDirs(const std::vector<std::string> &args);
|
||||
|
||||
// Resolve '..' and '.'; if the path starts with any of root_dirs, replace the
|
||||
// prefix; don't resolve symbolic links.
|
||||
std::string NormalizePath(std::string_view path, const RootDirs &root_dirs);
|
||||
|
||||
std::set<std::string>
|
||||
CollectAllExportedHeaders(const std::vector<std::string> &exported_header_dirs,
|
||||
const RootDirs &root_dirs);
|
||||
|
||||
|
||||
} // namespace utils
|
||||
} // namespace header_checker
|
||||
|
||||
|
||||
#endif // SOURCE_PATH_UTILS_H_
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "utils/header_abi_util.h"
|
||||
#include "utils/source_path_utils.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -21,25 +21,59 @@ namespace header_checker {
|
||||
namespace utils {
|
||||
|
||||
|
||||
TEST(CollectExportedHeadersTest, NormalizeAbsolutePaths) {
|
||||
const std::string root = "/root/dir";
|
||||
EXPECT_EQ("", NormalizePath(root, root));
|
||||
EXPECT_EQ("/unit/test", NormalizePath("/unit/test", root));
|
||||
EXPECT_EQ("/root/unit/test", NormalizePath(root + "/../unit/test", root));
|
||||
TEST(SourcePathUtilsTest, NormalizeAbsolutePaths) {
|
||||
const std::vector<std::string> args{"/root/dir"};
|
||||
const RootDirs root_dirs = ParseRootDirs(args);
|
||||
ASSERT_EQ(1, root_dirs.size());
|
||||
ASSERT_EQ("/root/dir", root_dirs[0].path);
|
||||
ASSERT_EQ("", root_dirs[0].replacement);
|
||||
|
||||
EXPECT_EQ("", NormalizePath("/root/dir", root_dirs));
|
||||
EXPECT_EQ("test", NormalizePath("/root/dir/test", root_dirs));
|
||||
EXPECT_EQ("/root/unit/test",
|
||||
NormalizePath("/root/dir/../unit/test", root_dirs));
|
||||
}
|
||||
|
||||
|
||||
TEST(CollectExportedHeadersTest, NormalizeCwdPaths) {
|
||||
const std::string cwd = GetCwd();
|
||||
ASSERT_NE("", cwd);
|
||||
TEST(SourcePathUtilsTest, NormalizeCwdPaths) {
|
||||
const RootDirs cwd = ParseRootDirs(std::vector<std::string>());
|
||||
ASSERT_EQ(1, cwd.size());
|
||||
ASSERT_NE("", cwd[0].path);
|
||||
ASSERT_EQ("", cwd[0].replacement);
|
||||
|
||||
EXPECT_EQ("", NormalizePath("", cwd));
|
||||
EXPECT_EQ("unit/test", NormalizePath("./unit/test/.", cwd));
|
||||
EXPECT_EQ("unit/test", NormalizePath("unit//test//", cwd));
|
||||
EXPECT_EQ("test", NormalizePath("unit/../test", cwd));
|
||||
EXPECT_EQ("unit/test", NormalizePath(cwd + "/unit/test", cwd));
|
||||
EXPECT_EQ("unit/test", NormalizePath(cwd[0].path + "/unit/test", cwd));
|
||||
EXPECT_EQ('/', NormalizePath("../unit/test", cwd)[0]);
|
||||
}
|
||||
|
||||
|
||||
TEST(SourcePathUtilsTest, NormalizePathsWithMultipleRootDirs) {
|
||||
const std::vector<std::string> args{"/before:/", "/before/dir:after"};
|
||||
const RootDirs root_dirs = ParseRootDirs(args);
|
||||
ASSERT_EQ(2, root_dirs.size());
|
||||
ASSERT_EQ("/before/dir", root_dirs[0].path);
|
||||
ASSERT_EQ("after", root_dirs[0].replacement);
|
||||
ASSERT_EQ("/before", root_dirs[1].path);
|
||||
ASSERT_EQ("/", root_dirs[1].replacement);
|
||||
|
||||
EXPECT_EQ("/directory", NormalizePath("/before/directory", root_dirs));
|
||||
EXPECT_EQ("after", NormalizePath("/before/dir", root_dirs));
|
||||
}
|
||||
|
||||
|
||||
TEST(SourcePathUtilsTest, NormalizeRelativePaths) {
|
||||
const std::vector<std::string> args{"../before/.:..//after/."};
|
||||
const RootDirs root_dirs = ParseRootDirs(args);
|
||||
ASSERT_EQ(1, root_dirs.size());
|
||||
ASSERT_EQ('/', root_dirs[0].path[0]);
|
||||
ASSERT_EQ("../after", root_dirs[0].replacement);
|
||||
|
||||
EXPECT_EQ("../after", NormalizePath("../before", root_dirs));
|
||||
}
|
||||
|
||||
|
||||
} // namespace utils
|
||||
} // namespace header_checker
|
||||
|
||||
Reference in New Issue
Block a user