Merge changes If4e8ff72,I53d861fb
* changes:
Add data table for build library.
Fix few UI bugs.
diff --git a/scripts/cargo2android.py b/scripts/cargo2android.py
index c6b5f04..730df5a 100755
--- a/scripts/cargo2android.py
+++ b/scripts/cargo2android.py
@@ -72,6 +72,7 @@
'libminijail': 'libminijail_rust',
'libsync': 'libsync_rust',
'libx86_64': 'libx86_64_rust',
+ 'libxml': 'libxml_rust',
'protoc_gen_rust': 'protoc-gen-rust',
}
@@ -303,6 +304,9 @@
# which can be changed if self is a merged test module.
self.decide_module_type()
if should_merge_test:
+ if (self.main_src in self.runner.args.test_blocklist and
+ not other.main_src in self.runner.args.test_blocklist):
+ self.main_src = other.main_src
self.srcs.append(other.main_src)
# use a short unique name as the merged module name.
prefix = self.root_pkg + '_tests'
diff --git a/vndk/tools/header-checker/src/dumper/abi_wrappers.cpp b/vndk/tools/header-checker/src/dumper/abi_wrappers.cpp
index 388f44c..2ff0385 100644
--- a/vndk/tools/header-checker/src/dumper/abi_wrappers.cpp
+++ b/vndk/tools/header-checker/src/dumper/abi_wrappers.cpp
@@ -69,7 +69,7 @@
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 @@
// 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 @@
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;
}
diff --git a/vndk/tools/header-checker/src/dumper/abi_wrappers.h b/vndk/tools/header-checker/src/dumper/abi_wrappers.h
index 92e1019..b2a039e 100644
--- a/vndk/tools/header-checker/src/dumper/abi_wrappers.h
+++ b/vndk/tools/header-checker/src/dumper/abi_wrappers.h
@@ -49,7 +49,7 @@
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,
diff --git a/vndk/tools/header-checker/src/dumper/ast_processing.cpp b/vndk/tools/header-checker/src/dumper/ast_processing.cpp
index de97da6..12dcbb3 100644
--- a/vndk/tools/header-checker/src/dumper/ast_processing.cpp
+++ b/vndk/tools/header-checker/src/dumper/ast_processing.cpp
@@ -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 @@
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 @@
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 @@
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 @@
// 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*/));
diff --git a/vndk/tools/header-checker/src/dumper/ast_util.h b/vndk/tools/header-checker/src/dumper/ast_util.h
index a4872e7..9960f0b 100644
--- a/vndk/tools/header-checker/src/dumper/ast_util.h
+++ b/vndk/tools/header-checker/src/dumper/ast_util.h
@@ -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 @@
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_;
diff --git a/vndk/tools/header-checker/src/dumper/header_checker.cpp b/vndk/tools/header-checker/src/dumper/header_checker.cpp
index 7832ce8..209aebb 100644
--- a/vndk/tools/header-checker/src/dumper/header_checker.cpp
+++ b/vndk/tools/header-checker/src/dumper/header_checker.cpp
@@ -42,9 +42,11 @@
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 @@
"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 @@
::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);
diff --git a/vndk/tools/header-checker/src/dumper/header_checker.h b/vndk/tools/header-checker/src/dumper/header_checker.h
index 53c917a..7a7506d 100644
--- a/vndk/tools/header-checker/src/dumper/header_checker.h
+++ b/vndk/tools/header-checker/src/dumper/header_checker.h
@@ -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 @@
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 @@
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) {}
diff --git a/vndk/tools/header-checker/src/linker/header_abi_linker.cpp b/vndk/tools/header-checker/src/linker/header_abi_linker.cpp
index f857081..e877150 100644
--- a/vndk/tools/header-checker/src/linker/header_abi_linker.cpp
+++ b/vndk/tools/header-checker/src/linker/header_abi_linker.cpp
@@ -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 @@
"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 @@
}
// 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();
diff --git a/vndk/tools/header-checker/src/utils/header_abi_util.h b/vndk/tools/header-checker/src/utils/header_abi_util.h
index c9c6b1d..9915c52 100644
--- a/vndk/tools/header-checker/src/utils/header_abi_util.h
+++ b/vndk/tools/header-checker/src/utils/header_abi_util.h
@@ -26,16 +26,6 @@
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) {
diff --git a/vndk/tools/header-checker/src/utils/source_path_utils.cpp b/vndk/tools/header-checker/src/utils/source_path_utils.cpp
index bc69809..5e6daf4 100644
--- a/vndk/tools/header-checker/src/utils/source_path_utils.cpp
+++ b/vndk/tools/header-checker/src/utils/source_path_utils.cpp
@@ -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 @@
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 @@
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);
}
diff --git a/vndk/tools/header-checker/src/utils/source_path_utils.h b/vndk/tools/header-checker/src/utils/source_path_utils.h
new file mode 100644
index 0000000..efd927c
--- /dev/null
+++ b/vndk/tools/header-checker/src/utils/source_path_utils.h
@@ -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_
diff --git a/vndk/tools/header-checker/src/utils/source_path_utils_test.cpp b/vndk/tools/header-checker/src/utils/source_path_utils_test.cpp
index 4ef1c65..2b74eba 100644
--- a/vndk/tools/header-checker/src/utils/source_path_utils_test.cpp
+++ b/vndk/tools/header-checker/src/utils/source_path_utils_test.cpp
@@ -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 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