diff --git a/.bazelci/postsubmit.yml b/.bazelci/postsubmit.yml index a9eb038aa55def..c71145f9f74f7e 100644 --- a/.bazelci/postsubmit.yml +++ b/.bazelci/postsubmit.yml @@ -254,7 +254,6 @@ tasks: - "//tools/aquery_differ/..." - "//tools/bash/..." - "//tools/build_defs/..." - - "//tools/cpp/runfiles/..." - "//tools/java/..." - "//tools/jdk/..." - "//tools/python/..." diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 6b485bdbcd0f4d..ef6f384d101e5a 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -263,7 +263,6 @@ tasks: - "//tools/aquery_differ/..." - "//tools/bash/..." - "//tools/build_defs/..." - - "//tools/cpp/runfiles/..." - "//tools/java/..." - "//tools/jdk/..." - "//tools/python/..." diff --git a/MODULE.bazel b/MODULE.bazel index 5f9a8e28891a43..d9a23b1488c4c7 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -24,7 +24,7 @@ bazel_dep(name = "stardoc", version = "0.7.1", repo_name = "io_bazel_skydoc") bazel_dep(name = "zstd-jni", version = "1.5.2-3.bcr.1") bazel_dep(name = "blake3", version = "1.5.1.bcr.1") bazel_dep(name = "zlib", version = "1.3.1.bcr.3") -bazel_dep(name = "rules_cc", version = "0.0.16") +bazel_dep(name = "rules_cc", version = "0.0.17") bazel_dep(name = "rules_java", version = "8.3.1") bazel_dep(name = "rules_graalvm", version = "0.11.1") bazel_dep(name = "rules_proto", version = "7.0.2") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 0079841ba4fcd1..e93e3bd449f40c 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -128,8 +128,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/source.json": "227e83737046aa4f50015da48e98e0d8ab42fd0ec74d8d653b6cc9f9a357f200", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5", "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", "https://bcr.bazel.build/modules/rules_cc/0.0.5/MODULE.bazel": "be41f87587998fe8890cd82ea4e848ed8eb799e053c224f78f3ff7fe1a1d9b74", "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", diff --git a/scripts/bootstrap/compile.sh b/scripts/bootstrap/compile.sh index 33fd09de07d4c2..9aab1a59805c36 100755 --- a/scripts/bootstrap/compile.sh +++ b/scripts/bootstrap/compile.sh @@ -266,15 +266,8 @@ EOF # Create @bazel_tools//tools/cpp/runfiles mkdir -p ${BAZEL_TOOLS_REPO}/tools/cpp/runfiles - link_file "${PWD}/tools/cpp/runfiles/runfiles_src.h" \ + link_file "${PWD}/tools/cpp/runfiles/runfiles.h" \ "${BAZEL_TOOLS_REPO}/tools/cpp/runfiles/runfiles.h" - # Transform //tools/cpp/runfiles:runfiles_src.cc to - # @bazel_tools//tools/cpp/runfiles:runfiles.cc - # Keep this transformation logic in sync with the - # //tools/cpp/runfiles:srcs_for_embedded_tools genrule. - sed 's|^#include.*/runfiles_src.h.*|#include \"tools/cpp/runfiles/runfiles.h\"|' \ - "${PWD}/tools/cpp/runfiles/runfiles_src.cc" > \ - "${BAZEL_TOOLS_REPO}/tools/cpp/runfiles/runfiles.cc" link_file "${PWD}/tools/cpp/runfiles/BUILD.tools" \ "${BAZEL_TOOLS_REPO}/tools/cpp/runfiles/BUILD" diff --git a/src/MODULE.tools b/src/MODULE.tools index 77c6c907ee122a..ac321e55a56d4c 100644 --- a/src/MODULE.tools +++ b/src/MODULE.tools @@ -40,7 +40,7 @@ use_repo(buildozer_binary, "buildozer_binary") # See also: --incompatible_autoload_externally, AutoloadSymbols bazel_dep(name = "protobuf", version = "29.0-rc2", repo_name = "com_google_protobuf") bazel_dep(name = "rules_java", version = "8.3.1") -bazel_dep(name = "rules_cc", version = "0.0.16") +bazel_dep(name = "rules_cc", version = "0.0.17") bazel_dep(name = "rules_python", version = "0.36.0") bazel_dep(name = "rules_shell", version = "0.2.0") # add rules_android diff --git a/src/create_embedded_tools.py b/src/create_embedded_tools.py index edc987aa47b3a3..f40b7e5c21b22a 100644 --- a/src/create_embedded_tools.py +++ b/src/create_embedded_tools.py @@ -45,8 +45,6 @@ ('*tools/j2objc/BUILD.tools', lambda x: 'tools/j2objc/BUILD'), ('*tools/platforms/*', lambda x: 'platforms/' + os.path.basename(x)), ('*tools/cpp/BUILD.tools', lambda x: 'tools/cpp/BUILD'), - ('*tools/cpp/runfiles/generated_*', - lambda x: 'tools/cpp/runfiles/' + os.path.basename(x)[len('generated_'):]), ('*launcher.exe', lambda x: 'tools/launcher/launcher.exe'), ('*launcher_maker.exe', lambda x: 'tools/launcher/launcher_maker.exe'), ('*def_parser.exe', lambda x: 'tools/def_parser/def_parser.exe'), diff --git a/src/main/cpp/util/BUILD b/src/main/cpp/util/BUILD index f63b4249e3b770..d399fefda4d5e5 100644 --- a/src/main/cpp/util/BUILD +++ b/src/main/cpp/util/BUILD @@ -60,7 +60,6 @@ cc_library( "//src/tools/launcher:__subpackages__", "//src/tools/singlejar:__pkg__", "//third_party/def_parser:__pkg__", - "//tools/cpp/runfiles:__pkg__", "//tools/test:__pkg__", ], deps = [ diff --git a/src/main/starlark/builtins_bzl/common/cc/cc_helper.bzl b/src/main/starlark/builtins_bzl/common/cc/cc_helper.bzl index 55041afedf26e3..fd57282f569d4c 100644 --- a/src/main/starlark/builtins_bzl/common/cc/cc_helper.bzl +++ b/src/main/starlark/builtins_bzl/common/cc/cc_helper.bzl @@ -956,11 +956,12 @@ def _is_stamping_enabled_for_aspect(ctx): stamp = ctx.rule.attr.stamp return stamp -_RUNFILES_LIBRARY_TARGET = Label("@bazel_tools//tools/cpp/runfiles") +_RUNFILES_LIBRARY_TARGET = Label("@rules_cc//cc/runfiles") +_LEGACY_RUNFILES_LIBRARY_TARGET = Label("@bazel_tools//tools/cpp/runfiles") def _get_local_defines_for_runfiles_lookup(ctx, all_deps): for dep in all_deps: - if dep.label == _RUNFILES_LIBRARY_TARGET: + if dep.label == _RUNFILES_LIBRARY_TARGET or dep.label == _LEGACY_RUNFILES_LIBRARY_TARGET: return ["BAZEL_CURRENT_REPOSITORY=\"{}\"".format(ctx.label.workspace_name)] return [] diff --git a/src/test/native/windows/BUILD b/src/test/native/windows/BUILD index 1740499fb1fa42..9dd68914681cf0 100644 --- a/src/test/native/windows/BUILD +++ b/src/test/native/windows/BUILD @@ -68,7 +68,7 @@ cc_test( "//src/main/cpp/util:filesystem", "//src/main/native/windows:lib-file", "//src/main/native/windows:lib-process", - "@bazel_tools//tools/cpp/runfiles", + "@rules_cc//cc/runfiles", ], "//conditions:default": [], }), diff --git a/src/test/native/windows/process_test.cc b/src/test/native/windows/process_test.cc index 63aa8b9bd43f7d..928c94b76fd671 100644 --- a/src/test/native/windows/process_test.cc +++ b/src/test/native/windows/process_test.cc @@ -27,7 +27,7 @@ #include "gtest/gtest.h" #include "src/main/cpp/util/path.h" #include "src/main/native/windows/util.h" -#include "tools/cpp/runfiles/runfiles.h" +#include "rules_cc/cc/runfiles/runfiles.h" namespace { @@ -49,8 +49,8 @@ void AssertSubprocessReceivesArgsAsIntended( // Create a Runfiles object. std::string error; - std::unique_ptr runfiles( - bazel::tools::cpp::runfiles::Runfiles::CreateForTest(&error)); + std::unique_ptr runfiles( + rules_cc::cc::runfiles::Runfiles::CreateForTest(&error)); ASSERT_NE(runfiles.get(), nullptr) << error; // Look up the path of the printarg.exe utility. diff --git a/src/test/py/bazel/bzlmod/bazel_repo_mapping_test.py b/src/test/py/bazel/bzlmod/bazel_repo_mapping_test.py index 0e89aa970e9590..1fe6523458c895 100644 --- a/src/test/py/bazel/bzlmod/bazel_repo_mapping_test.py +++ b/src/test/py/bazel/bzlmod/bazel_repo_mapping_test.py @@ -259,7 +259,7 @@ def testBashRunfilesLibraryRepoMapping(self): env_add={'RUNFILES_LIB_DEBUG': '1'}, ) - def testCppRunfilesLibraryRepoMapping(self): + def testLegacyCppRunfilesLibraryRepoMapping(self): self.main_registry.setModuleBasePath('projects') projects_dir = self.main_registry.projects @@ -311,6 +311,58 @@ def testCppRunfilesLibraryRepoMapping(self): # Run unsandboxed on all platforms. self.RunBazel(['run', '@test//:test']) + def testCppRunfilesLibraryRepoMapping(self): + self.main_registry.setModuleBasePath('projects') + projects_dir = self.main_registry.projects + + self.main_registry.createLocalPathModule('data', '1.0', 'data') + scratchFile(projects_dir.joinpath('data', 'foo.txt'), ['hello']) + scratchFile( + projects_dir.joinpath('data', 'BUILD'), ['exports_files(["foo.txt"])'] + ) + + self.main_registry.createLocalPathModule( + 'test', '1.0', 'test', {'data': '1.0'} + ) + scratchFile( + projects_dir.joinpath('test', 'BUILD'), + [ + 'cc_test(', + ' name = "test",', + ' srcs = ["test.cpp"],', + ' data = ["@data//:foo.txt"],', + ' args = ["$(rlocationpath @data//:foo.txt)"],', + ' deps = ["@rules_cc//cc/runfiles"],', + ')', + ], + ) + scratchFile( + projects_dir.joinpath('test', 'test.cpp'), + [ + '#include ', + '#include ', + '#include "rules_cc/cc/runfiles/runfiles.h"', + 'using rules_cc::cc::runfiles::Runfiles;', + 'int main(int argc, char** argv) {', + ( + ' Runfiles* runfiles = Runfiles::Create(argv[0],' + ' BAZEL_CURRENT_REPOSITORY);' + ), + ' std::ifstream f1(runfiles->Rlocation(argv[1]));', + ' if (!f1.good()) std::exit(1);', + ' std::ifstream f2(runfiles->Rlocation("data/foo.txt"));', + ' if (!f2.good()) std::exit(2);', + '}', + ], + ) + + self.ScratchFile('MODULE.bazel', ['bazel_dep(name="test",version="1.0")']) + + # Run sandboxed on Linux and macOS. + self.RunBazel(['test', '@test//:test', '--test_output=errors']) + # Run unsandboxed on all platforms. + self.RunBazel(['run', '@test//:test']) + def testJavaRunfilesLibraryRepoMapping(self): self.main_registry.setModuleBasePath('projects') projects_dir = self.main_registry.projects diff --git a/src/test/tools/bzlmod/MODULE.bazel.lock b/src/test/tools/bzlmod/MODULE.bazel.lock index 8e8005ad0c2616..dde18f0f65c6da 100644 --- a/src/test/tools/bzlmod/MODULE.bazel.lock +++ b/src/test/tools/bzlmod/MODULE.bazel.lock @@ -66,8 +66,8 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", - "https://bcr.bazel.build/modules/rules_cc/0.0.16/source.json": "227e83737046aa4f50015da48e98e0d8ab42fd0ec74d8d653b6cc9f9a357f200", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5", "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", diff --git a/src/tools/launcher/util/launcher_util_test.cc b/src/tools/launcher/util/launcher_util_test.cc index 72e3f6d5dca5ad..b9f28eb4506c96 100644 --- a/src/tools/launcher/util/launcher_util_test.cc +++ b/src/tools/launcher/util/launcher_util_test.cc @@ -30,7 +30,7 @@ #include "src/main/cpp/util/path_platform.h" #include "src/main/cpp/util/strings.h" #include "src/main/native/windows/util.h" -#include "tools/cpp/runfiles/runfiles.h" +#include "rules_cc/cc/runfiles/runfiles.h" namespace bazel { namespace launcher { diff --git a/src/tools/singlejar/BUILD b/src/tools/singlejar/BUILD index 595e3b3668f771..80d59b062cda80 100644 --- a/src/tools/singlejar/BUILD +++ b/src/tools/singlejar/BUILD @@ -463,8 +463,8 @@ cc_library( hdrs = ["test_util.h"], deps = [ "//src/main/cpp/util", - "@bazel_tools//tools/cpp/runfiles", "@com_google_googletest//:gtest_main", + "@rules_cc//cc/runfiles", ], ) diff --git a/src/tools/singlejar/test_util.h b/src/tools/singlejar/test_util.h index f5aacbf8e256e3..dd73a48a3c2d3c 100644 --- a/src/tools/singlejar/test_util.h +++ b/src/tools/singlejar/test_util.h @@ -16,7 +16,7 @@ #include -#include "tools/cpp/runfiles/runfiles.h" +#include "rules_cc/cc/runfiles/runfiles.h" namespace singlejar_test_util { using std::string; diff --git a/tools/cpp/runfiles/BUILD b/tools/cpp/runfiles/BUILD index f58d8aaf65fead..81931f9dc7d109 100644 --- a/tools/cpp/runfiles/BUILD +++ b/tools/cpp/runfiles/BUILD @@ -16,51 +16,7 @@ filegroup( name = "embedded_tools", srcs = [ "BUILD.tools", - ":srcs_for_embedded_tools", + "runfiles.h", ], visibility = ["//tools/cpp:__pkg__"], ) - -# Rewrite the include path for runfiles.h in runfiles_src.cc, and create -# "generated_runfiles.{h,cc}". These files are renamed to "runfiles.{h,cc}" as -# part of creating the embedded tools of Bazel. -# -# We cannot just check in runfiles_src.{h,cc} as runfiles.{h,cc}, because it'd -# cause a header check failure on Windows when building targets in the Bazel -# source tree, if those targets depend on @bazel_tools//tools/cpp/runfiles, -# because due to lack of sandboxing they would accidentally pick up runfiles.h -# from //tools/cpp/runfiles. -genrule( - name = "srcs_for_embedded_tools", - srcs = [ - "runfiles_src.cc", - "runfiles_src.h", - ], - outs = [ - "generated_runfiles.cc", - "generated_runfiles.h", - ], - # Keep this transformation logic in sync with the - # //scripts/bootstrap/compile.sh - cmd = ("sed " + - " 's|^#include.*/runfiles_src.h.*|#include \"tools/cpp/runfiles/runfiles.h\"|' " + - " $(location runfiles_src.cc) > $(location generated_runfiles.cc) && " + - "cp $(location runfiles_src.h) $(location generated_runfiles.h)"), -) - -cc_library( - name = "runfiles", - testonly = 1, - srcs = ["runfiles_src.cc"], - hdrs = ["runfiles_src.h"], -) - -cc_test( - name = "runfiles_test", - srcs = ["runfiles_test.cc"], - visibility = ["//visibility:public"], - deps = [ - ":runfiles", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/tools/cpp/runfiles/BUILD.tools b/tools/cpp/runfiles/BUILD.tools index ef9518c05b8b15..13d213aea94661 100644 --- a/tools/cpp/runfiles/BUILD.tools +++ b/tools/cpp/runfiles/BUILD.tools @@ -1,8 +1,6 @@ -# This package will host the C++ runfiles library when it's finally released. - cc_library( name = "runfiles", - srcs = ["runfiles.cc"], hdrs = ["runfiles.h"], + deps = ["@rules_cc//cc/runfiles"], visibility = ["//visibility:public"], ) diff --git a/tools/cpp/runfiles/runfiles.h b/tools/cpp/runfiles/runfiles.h new file mode 100644 index 00000000000000..8dec86d4d6020c --- /dev/null +++ b/tools/cpp/runfiles/runfiles.h @@ -0,0 +1,37 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// 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. + +// Deprecated forwarder for the rules_cc runfiles library. +// +// Depend on @rules_cc//cc/runfiles instead and refer to its header file: +// https://github.com/bazelbuild/rules_cc/blob/main/cc/runfiles/runfiles.h + +#ifndef TOOLS_CPP_RUNFILES_RUNFILES_H_ +#define TOOLS_CPP_RUNFILES_RUNFILES_H_ 1 + +#include "rules_cc/cc/runfiles/runfiles.h" + +namespace bazel { +namespace tools { +namespace cpp { +namespace runfiles { + +typedef ::rules_cc::cc::runfiles::Runfiles Runfiles; + +} // namespace runfiles +} // namespace cpp +} // namespace tools +} // namespace bazel + +#endif // TOOLS_CPP_RUNFILES_RUNFILES_H_ diff --git a/tools/cpp/runfiles/runfiles_src.cc b/tools/cpp/runfiles/runfiles_src.cc deleted file mode 100644 index 9da569fda0b58d..00000000000000 --- a/tools/cpp/runfiles/runfiles_src.cc +++ /dev/null @@ -1,486 +0,0 @@ -// Copyright 2018 The Bazel Authors. All rights reserved. -// -// 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. - -// The "srcs_for_embedded_tools" rule in the same package sets the line below to -// include runfiles.h from the correct path. Do not modify the line below. -#include "tools/cpp/runfiles/runfiles_src.h" - -#ifdef _WIN32 -#include -#else // not _WIN32 -#include -#include -#include -#include -#endif // _WIN32 - -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#endif // _WIN32 - -namespace bazel { -namespace tools { -namespace cpp { -namespace runfiles { - -using std::function; -using std::map; -using std::pair; -using std::string; -using std::vector; - -namespace { - -bool starts_with(const string& s, const char* prefix) { - if (!prefix || !*prefix) { - return true; - } - if (s.empty()) { - return false; - } - return s.find(prefix) == 0; -} - -bool contains(const string& s, const char* substr) { - if (!substr || !*substr) { - return true; - } - if (s.empty()) { - return false; - } - return s.find(substr) != string::npos; -} - -bool ends_with(const string& s, const string& suffix) { - if (suffix.empty()) { - return true; - } - if (s.empty()) { - return false; - } - return s.rfind(suffix) == s.size() - suffix.size(); -} - -bool IsReadableFile(const string& path) { - return std::ifstream(path).is_open(); -} - -bool IsDirectory(const string& path) { -#ifdef _WIN32 - DWORD attrs = GetFileAttributesA(path.c_str()); - return (attrs != INVALID_FILE_ATTRIBUTES) && - (attrs & FILE_ATTRIBUTE_DIRECTORY); -#else - struct stat buf; - return stat(path.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode); -#endif -} - -bool PathsFrom(const std::string& argv0, std::string runfiles_manifest_file, - std::string runfiles_dir, std::string* out_manifest, - std::string* out_directory); - -bool PathsFrom(const std::string& argv0, std::string runfiles_manifest_file, - std::string runfiles_dir, - std::function is_runfiles_manifest, - std::function is_runfiles_directory, - std::string* out_manifest, std::string* out_directory); - -bool ParseManifest(const string& path, map* result, - string* error); -bool ParseRepoMapping(const string& path, - map, string>* result, string* error); - -} // namespace - -Runfiles* Runfiles::Create(const string& argv0, - const string& runfiles_manifest_file, - const string& runfiles_dir, - const string& source_repository, string* error) { - string manifest, directory; - if (!PathsFrom(argv0, runfiles_manifest_file, runfiles_dir, &manifest, - &directory)) { - if (error) { - std::ostringstream err; - err << "ERROR: " << __FILE__ << "(" << __LINE__ - << "): cannot find runfiles (argv0=\"" << argv0 << "\")"; - *error = err.str(); - } - return nullptr; - } - - vector > envvars = { - {"RUNFILES_MANIFEST_FILE", manifest}, - {"RUNFILES_DIR", directory}, - // TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can - // pick up RUNFILES_DIR. - {"JAVA_RUNFILES", directory}}; - - map runfiles; - if (!manifest.empty()) { - if (!ParseManifest(manifest, &runfiles, error)) { - return nullptr; - } - } - - map, string> mapping; - if (!ParseRepoMapping( - RlocationUnchecked("_repo_mapping", runfiles, directory), &mapping, - error)) { - return nullptr; - } - - return new Runfiles(std::move(runfiles), std::move(directory), - std::move(mapping), std::move(envvars), - string(source_repository)); -} - -bool IsAbsolute(const string& path) { - if (path.empty()) { - return false; - } - char c = path.front(); - return (c == '/' && (path.size() < 2 || path[1] != '/')) || - (path.size() >= 3 && - ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) && - path[1] == ':' && (path[2] == '\\' || path[2] == '/')); -} - -string GetEnv(const string& key) { -#ifdef _WIN32 - DWORD size = ::GetEnvironmentVariableA(key.c_str(), nullptr, 0); - if (size == 0) { - return string(); // unset or empty envvar - } - std::unique_ptr value(new char[size]); - ::GetEnvironmentVariableA(key.c_str(), value.get(), size); - return value.get(); -#else - char* result = getenv(key.c_str()); - return (result == nullptr) ? string() : string(result); -#endif -} - -// Replaces \s, \n, and \b with their respective characters. -string Unescape(const string& path) { - string result; - result.reserve(path.size()); - for (size_t i = 0; i < path.size(); ++i) { - if (path[i] == '\\' && i + 1 < path.size()) { - switch (path[i + 1]) { - case 's': { - result.push_back(' '); - break; - } - case 'n': { - result.push_back('\n'); - break; - } - case 'b': { - result.push_back('\\'); - break; - } - default: { - result.push_back(path[i]); - result.push_back(path[i + 1]); - break; - } - } - ++i; - } else { - result.push_back(path[i]); - } - } - return result; -} - -string Runfiles::Rlocation(const string& path) const { - return Rlocation(path, source_repository_); -} - -string Runfiles::Rlocation(const string& path, - const string& source_repo) const { - if (path.empty() || starts_with(path, "../") || contains(path, "/..") || - starts_with(path, "./") || contains(path, "/./") || - ends_with(path, "/.") || contains(path, "//")) { - return string(); - } - if (IsAbsolute(path)) { - return path; - } - - string::size_type first_slash = path.find_first_of('/'); - if (first_slash == string::npos) { - return RlocationUnchecked(path, runfiles_map_, directory_); - } - string target_apparent = path.substr(0, first_slash); - auto target = - repo_mapping_.find(std::make_pair(source_repo, target_apparent)); - if (target == repo_mapping_.cend()) { - return RlocationUnchecked(path, runfiles_map_, directory_); - } - return RlocationUnchecked(target->second + path.substr(first_slash), - runfiles_map_, directory_); -} - -string Runfiles::RlocationUnchecked(const string& path, - const map& runfiles_map, - const string& directory) { - const auto exact_match = runfiles_map.find(path); - if (exact_match != runfiles_map.end()) { - return exact_match->second; - } - if (!runfiles_map.empty()) { - // If path references a runfile that lies under a directory that itself is a - // runfile, then only the directory is listed in the manifest. Look up all - // prefixes of path in the manifest and append the relative path from the - // prefix to the looked up path. - std::size_t prefix_end = path.size(); - while ((prefix_end = path.find_last_of('/', prefix_end - 1)) != - string::npos) { - const string prefix = path.substr(0, prefix_end); - const auto prefix_match = runfiles_map.find(prefix); - if (prefix_match != runfiles_map.end()) { - return prefix_match->second + "/" + path.substr(prefix_end + 1); - } - } - } - if (!directory.empty()) { - return directory + "/" + path; - } - return ""; -} - -namespace { - -bool ParseManifest(const string& path, map* result, - string* error) { - std::ifstream stm(path); - if (!stm.is_open()) { - if (error) { - std::ostringstream err; - err << "ERROR: " << __FILE__ << "(" << __LINE__ - << "): cannot open runfiles manifest \"" << path << "\""; - *error = err.str(); - } - return false; - } - string line; - std::getline(stm, line); - size_t line_count = 1; - while (!line.empty()) { - std::string source; - std::string target; - if (line[0] == ' ') { - // The link path contains escape sequences for spaces and backslashes. - string::size_type idx = line.find(' ', 1); - if (idx == string::npos) { - if (error) { - std::ostringstream err; - err << "ERROR: " << __FILE__ << "(" << __LINE__ - << "): bad runfiles manifest entry in \"" << path << "\" line #" - << line_count << ": \"" << line << "\""; - *error = err.str(); - } - return false; - } - source = Unescape(line.substr(1, idx - 1)); - target = Unescape(line.substr(idx + 1)); - } else { - string::size_type idx = line.find(' '); - if (idx == string::npos) { - if (error) { - std::ostringstream err; - err << "ERROR: " << __FILE__ << "(" << __LINE__ - << "): bad runfiles manifest entry in \"" << path << "\" line #" - << line_count << ": \"" << line << "\""; - *error = err.str(); - } - return false; - } - source = line.substr(0, idx); - target = line.substr(idx + 1); - } - (*result)[source] = target; - std::getline(stm, line); - ++line_count; - } - return true; -} - -bool ParseRepoMapping(const string& path, - map, string>* result, - string* error) { - std::ifstream stm(path); - if (!stm.is_open()) { - return true; - } - string line; - std::getline(stm, line); - size_t line_count = 1; - while (!line.empty()) { - string::size_type first_comma = line.find_first_of(','); - if (first_comma == string::npos) { - if (error) { - std::ostringstream err; - err << "ERROR: " << __FILE__ << "(" << __LINE__ - << "): bad repository mapping entry in \"" << path << "\" line #" - << line_count << ": \"" << line << "\""; - *error = err.str(); - } - return false; - } - string::size_type second_comma = line.find_first_of(',', first_comma + 1); - if (second_comma == string::npos) { - if (error) { - std::ostringstream err; - err << "ERROR: " << __FILE__ << "(" << __LINE__ - << "): bad repository mapping entry in \"" << path << "\" line #" - << line_count << ": \"" << line << "\""; - *error = err.str(); - } - return false; - } - - string source = line.substr(0, first_comma); - string target_apparent = - line.substr(first_comma + 1, second_comma - (first_comma + 1)); - string target = line.substr(second_comma + 1); - - (*result)[std::make_pair(source, target_apparent)] = target; - std::getline(stm, line); - ++line_count; - } - return true; -} - -} // namespace - -namespace testing { - -bool TestOnly_PathsFrom(const string& argv0, string mf, string dir, - function is_runfiles_manifest, - function is_runfiles_directory, - string* out_manifest, string* out_directory) { - return PathsFrom(argv0, mf, dir, is_runfiles_manifest, is_runfiles_directory, - out_manifest, out_directory); -} - -bool TestOnly_IsAbsolute(const string& path) { return IsAbsolute(path); } - -} // namespace testing - -Runfiles* Runfiles::Create(const std::string& argv0, - const std::string& runfiles_manifest_file, - const std::string& runfiles_dir, - std::string* error) { - return Runfiles::Create(argv0, runfiles_manifest_file, runfiles_dir, "", - error); -} - -Runfiles* Runfiles::Create(const string& argv0, const string& source_repository, - string* error) { - return Runfiles::Create(argv0, GetEnv("RUNFILES_MANIFEST_FILE"), - GetEnv("RUNFILES_DIR"), source_repository, error); -} - -Runfiles* Runfiles::Create(const string& argv0, string* error) { - return Runfiles::Create(argv0, "", error); -} - -Runfiles* Runfiles::CreateForTest(const string& source_repository, - std::string* error) { - return Runfiles::Create(std::string(), GetEnv("RUNFILES_MANIFEST_FILE"), - GetEnv("TEST_SRCDIR"), source_repository, error); -} - -Runfiles* Runfiles::CreateForTest(std::string* error) { - return Runfiles::CreateForTest("", error); -} - -namespace { - -bool PathsFrom(const string& argv0, string mf, string dir, string* out_manifest, - string* out_directory) { - return PathsFrom( - argv0, mf, dir, [](const string& path) { return IsReadableFile(path); }, - [](const string& path) { return IsDirectory(path); }, out_manifest, - out_directory); -} - -bool PathsFrom(const string& argv0, string mf, string dir, - function is_runfiles_manifest, - function is_runfiles_directory, - string* out_manifest, string* out_directory) { - out_manifest->clear(); - out_directory->clear(); - - bool mfValid = is_runfiles_manifest(mf); - bool dirValid = is_runfiles_directory(dir); - - if (!argv0.empty() && !mfValid && !dirValid) { - mf = argv0 + ".runfiles/MANIFEST"; - dir = argv0 + ".runfiles"; - mfValid = is_runfiles_manifest(mf); - dirValid = is_runfiles_directory(dir); - if (!mfValid) { - mf = argv0 + ".runfiles_manifest"; - mfValid = is_runfiles_manifest(mf); - } - } - - if (!mfValid && !dirValid) { - return false; - } - - if (!mfValid) { - mf = dir + "/MANIFEST"; - mfValid = is_runfiles_manifest(mf); - if (!mfValid) { - mf = dir + "_manifest"; - mfValid = is_runfiles_manifest(mf); - } - } - - if (!dirValid && - (ends_with(mf, ".runfiles_manifest") || ends_with(mf, "/MANIFEST"))) { - static const size_t kSubstrLen = 9; // "_manifest" or "/MANIFEST" - dir = mf.substr(0, mf.size() - kSubstrLen); - dirValid = is_runfiles_directory(dir); - } - - if (mfValid) { - *out_manifest = mf; - } - - if (dirValid) { - *out_directory = dir; - } - - return true; -} - -} // namespace - -} // namespace runfiles -} // namespace cpp -} // namespace tools -} // namespace bazel diff --git a/tools/cpp/runfiles/runfiles_src.h b/tools/cpp/runfiles/runfiles_src.h deleted file mode 100644 index 93e9da198d330d..00000000000000 --- a/tools/cpp/runfiles/runfiles_src.h +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright 2018 The Bazel Authors. All rights reserved. -// -// 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. - -// Runfiles lookup library for Bazel-built C++ binaries and tests. -// -// USAGE: -// 1. Depend on this runfiles library from your build rule: -// -// cc_binary( -// name = "my_binary", -// ... -// deps = ["@bazel_tools//tools/cpp/runfiles"], -// ) -// -// 2. Include the runfiles library. -// -// #include "tools/cpp/runfiles/runfiles.h" -// -// using bazel::tools::cpp::runfiles::Runfiles; -// -// 3. Create a Runfiles object and use rlocation to look up runfile paths: -// -// int main(int argc, char** argv) { -// std::string error; -// std::unique_ptr runfiles( -// Runfiles::Create(argv[0], BAZEL_CURRENT_REPOSITORY, &error)); -// -// // Important: -// // If this is a test, use -// // Runfiles::CreateForTest(BAZEL_CURRENT_REPOSITORY, &error). -// -// if (runfiles == nullptr) { -// ... // error handling -// } -// std::string path = -// runfiles->Rlocation("my_workspace/path/to/my/data.txt"); -// ... -// -// The code above creates a Runfiles object and retrieves a runfile path. -// The BAZEL_CURRENT_REPOSITORY macro is available in every target that -// depends on the runfiles library. -// -// The Runfiles::Create function uses the runfiles manifest and the -// runfiles directory from the RUNFILES_MANIFEST_FILE and RUNFILES_DIR -// environment variables. If not present, the function looks for the -// manifest and directory near argv[0], the path of the main program. -// -// To start child processes that also need runfiles, you need to set the right -// environment variables for them: -// -// std::unique_ptr runfiles(Runfiles::Create( -// argv[0], BAZEL_CURRENT_REPOSITORY, &error)); -// -// std::string path = runfiles->Rlocation("path/to/binary")); -// if (!path.empty()) { -// ... // create "args" argument vector for execv -// const auto envvars = runfiles->EnvVars(); -// pid_t child = fork(); -// if (child) { -// int status; -// waitpid(child, &status, 0); -// } else { -// for (const auto i : envvars) { -// setenv(i.first.c_str(), i.second.c_str(), 1); -// } -// execv(args[0], args); -// } - -#ifndef TOOLS_CPP_RUNFILES_RUNFILES_H_ -#define TOOLS_CPP_RUNFILES_RUNFILES_H_ 1 - -#include -#include -#include -#include -#include - -namespace bazel { -namespace tools { -namespace cpp { -namespace runfiles { - -class Runfiles { - public: - virtual ~Runfiles() {} - - // Returns a new `Runfiles` instance. - // - // Use this from within `cc_test` rules. - // - // Returns nullptr on error. If `error` is provided, the method prints an - // error message into it. - // - // This method looks at the RUNFILES_MANIFEST_FILE and TEST_SRCDIR - // environment variables. - // - // If source_repository is not provided, it defaults to the main repository - // (also known as the workspace). - static Runfiles* CreateForTest(std::string* error = nullptr); - static Runfiles* CreateForTest(const std::string& source_repository, - std::string* error = nullptr); - - // Returns a new `Runfiles` instance. - // - // Use this from `cc_binary` or `cc_library` rules. You may pass an empty - // `argv0` if `argv[0]` from the `main` method is unknown. - // - // Returns nullptr on error. If `error` is provided, the method prints an - // error message into it. - // - // This method looks at the RUNFILES_MANIFEST_FILE and RUNFILES_DIR - // environment variables. If either is empty, the method looks for the - // manifest or directory using the other environment variable, or using argv0 - // (unless it's empty). - // - // If source_repository is not provided, it defaults to the main repository - // (also known as the workspace). - static Runfiles* Create(const std::string& argv0, - std::string* error = nullptr); - static Runfiles* Create(const std::string& argv0, - const std::string& source_repository, - std::string* error = nullptr); - - // Returns a new `Runfiles` instance. - // - // Use this from any `cc_*` rule if you want to manually specify the paths to - // the runfiles manifest and/or runfiles directory. You may pass an empty - // `argv0` if `argv[0]` from the `main` method is unknown. - // - // This method is the same as `Create(argv0, error)`, except it uses - // `runfiles_manifest_file` and `runfiles_dir` as the corresponding - // environment variable values, instead of looking up the actual environment - // variables. - static Runfiles* Create(const std::string& argv0, - const std::string& runfiles_manifest_file, - const std::string& runfiles_dir, - std::string* error = nullptr); - static Runfiles* Create(const std::string& argv0, - const std::string& runfiles_manifest_file, - const std::string& runfiles_dir, - const std::string& source_repository, - std::string* error = nullptr); - - // Returns the runtime path of a runfile. - // - // Runfiles are data-dependencies of Bazel-built binaries and tests. - // - // The returned path may not exist. The caller should verify the path's - // existence. - // - // The function may return an empty string if it cannot find a runfile. - // - // Args: - // path: runfiles-root-relative path of the runfile; must not be empty and - // must not contain uplevel references. - // source_repository: if provided, overrides the source repository set when - // this Runfiles instance was created. - // Returns: - // the path to the runfile, which the caller should check for existence, or - // an empty string if the method doesn't know about this runfile - std::string Rlocation(const std::string& path) const; - std::string Rlocation(const std::string& path, - const std::string& source_repository) const; - - // Returns environment variables for subprocesses. - // - // The caller should set the returned key-value pairs in the environment of - // subprocesses, so that those subprocesses can also access runfiles (in case - // they are also Bazel-built binaries). - const std::vector >& EnvVars() const { - return envvars_; - } - - // Returns a new Runfiles instance that by default uses the provided source - // repository as a default for all calls to Rlocation. - // - // The current instance remains valid. - std::unique_ptr WithSourceRepository( - const std::string& source_repository) const { - return std::unique_ptr(new Runfiles( - runfiles_map_, directory_, repo_mapping_, envvars_, source_repository)); - } - - private: - Runfiles( - std::map runfiles_map, std::string directory, - std::map, std::string> repo_mapping, - std::vector > envvars, - std::string source_repository) - : runfiles_map_(std::move(runfiles_map)), - directory_(std::move(directory)), - repo_mapping_(std::move(repo_mapping)), - envvars_(std::move(envvars)), - source_repository_(std::move(source_repository)) {} - Runfiles(const Runfiles&) = delete; - Runfiles(Runfiles&&) = delete; - Runfiles& operator=(const Runfiles&) = delete; - Runfiles& operator=(Runfiles&&) = delete; - - static std::string RlocationUnchecked( - const std::string& path, - const std::map& runfiles_map, - const std::string& directory); - - const std::map runfiles_map_; - const std::string directory_; - const std::map, std::string> - repo_mapping_; - const std::vector > envvars_; - const std::string source_repository_; -}; - -// The "testing" namespace contains functions that allow unit testing the code. -// Do not use these outside of runfiles_test.cc, they are only part of the -// public API for the benefit of the tests. -// These functions and their interface may change without notice. -namespace testing { - -// For testing only. -// -// Computes the path of the runfiles manifest and the runfiles directory. -// -// If the method finds both a valid manifest and valid directory according to -// `is_runfiles_manifest` and `is_runfiles_directory`, then the method sets -// the corresponding values to `out_manifest` and `out_directory` and returns -// true. -// -// If the method only finds a valid manifest or a valid directory, but not -// both, then it sets the corresponding output variable (`out_manifest` or -// `out_directory`) to the value while clearing the other output variable. The -// method still returns true in this case. -// -// If the method cannot find either a valid manifest or valid directory, it -// clears both output variables and returns false. -bool TestOnly_PathsFrom( - const std::string& argv0, std::string runfiles_manifest_file, - std::string runfiles_dir, - std::function is_runfiles_manifest, - std::function is_runfiles_directory, - std::string* out_manifest, std::string* out_directory); - -// For testing only. -// Returns true if `path` is an absolute Unix or Windows path. -// For Windows paths, this function does not regard drive-less absolute paths -// (i.e. absolute-on-current-drive, e.g. "\foo\bar") as absolute and returns -// false for these. -bool TestOnly_IsAbsolute(const std::string& path); - -} // namespace testing -} // namespace runfiles -} // namespace cpp -} // namespace tools -} // namespace bazel - -#endif // TOOLS_CPP_RUNFILES_RUNFILES_H_ diff --git a/tools/cpp/runfiles/runfiles_test.cc b/tools/cpp/runfiles/runfiles_test.cc deleted file mode 100644 index 86c31e06f5e22a..00000000000000 --- a/tools/cpp/runfiles/runfiles_test.cc +++ /dev/null @@ -1,882 +0,0 @@ -// Copyright 2018 The Bazel Authors. All rights reserved. -// -// 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. - -#include "tools/cpp/runfiles/runfiles_src.h" - -#ifdef _WIN32 -#include -#endif // _WIN32 - -#include -#include -#include -#include - -#include "gtest/gtest.h" - -#define RUNFILES_TEST_TOSTRING_HELPER(x) #x -#define RUNFILES_TEST_TOSTRING(x) RUNFILES_TEST_TOSTRING_HELPER(x) -#define LINE_AS_STRING() RUNFILES_TEST_TOSTRING(__LINE__) - -namespace bazel { -namespace tools { -namespace cpp { -namespace runfiles { -namespace { - -using bazel::tools::cpp::runfiles::testing::TestOnly_IsAbsolute; -using bazel::tools::cpp::runfiles::testing::TestOnly_PathsFrom; -using std::cerr; -using std::endl; -using std::function; -using std::pair; -using std::string; -using std::unique_ptr; -using std::vector; - -class RunfilesTest : public ::testing::Test { - protected: - // Create a temporary file that is deleted with the destructor. - class MockFile { - public: - // Create an empty file with the given name under $TEST_TMPDIR. - static MockFile* Create(const string& name); - - // Create a file with the given name and contents under $TEST_TMPDIR. - // The method ensures to create all parent directories, so `name` is allowed - // to contain directory components. - static MockFile* Create(const string& name, const vector& lines); - - ~MockFile(); - const string& Path() const { return path_; } - - string DirName() const { - string::size_type pos = path_.find_last_of('/'); - return pos == string::npos ? "" : path_.substr(0, pos); - } - - private: - MockFile(const string& path) : path_(path) {} - MockFile(const MockFile&) = delete; - MockFile(MockFile&&) = delete; - MockFile& operator=(const MockFile&) = delete; - MockFile& operator=(MockFile&&) = delete; - - const string path_; - }; - - void AssertEnvvars(const Runfiles& runfiles, - const string& expected_manifest_file, - const string& expected_directory); - - static string GetTemp(); -}; - -void RunfilesTest::AssertEnvvars(const Runfiles& runfiles, - const string& expected_manifest_file, - const string& expected_directory) { - vector > expected = { - {"RUNFILES_MANIFEST_FILE", expected_manifest_file}, - {"RUNFILES_DIR", expected_directory}, - {"JAVA_RUNFILES", expected_directory}}; - ASSERT_EQ(runfiles.EnvVars(), expected); -} - -string RunfilesTest::GetTemp() { -#ifdef _WIN32 - DWORD size = ::GetEnvironmentVariableA("TEST_TMPDIR", nullptr, 0); - if (size == 0) { - return string(); // unset or empty envvar - } - unique_ptr value(new char[size]); - ::GetEnvironmentVariableA("TEST_TMPDIR", value.get(), size); - return value.get(); -#else - char* result = getenv("TEST_TMPDIR"); - return result != nullptr ? string(result) : string(); -#endif -} - -RunfilesTest::MockFile* RunfilesTest::MockFile::Create(const string& name) { - return Create(name, vector()); -} - -RunfilesTest::MockFile* RunfilesTest::MockFile::Create( - const string& name, const vector& lines) { - if (name.find("..") != string::npos || TestOnly_IsAbsolute(name)) { - cerr << "WARNING: " << __FILE__ << "(" << __LINE__ << "): bad name: \"" - << name << "\"" << endl; - return nullptr; - } - - string tmp(RunfilesTest::GetTemp()); - if (tmp.empty()) { - cerr << "WARNING: " << __FILE__ << "(" << __LINE__ - << "): $TEST_TMPDIR is empty" << endl; - return nullptr; - } - string path(tmp + "/" + name); - - string::size_type i = 0; -#ifdef _WIN32 - while ((i = name.find_first_of("/\\", i + 1)) != string::npos) { - string d = tmp + "\\" + name.substr(0, i); - if (!CreateDirectoryA(d.c_str(), nullptr)) { - cerr << "ERROR: " << __FILE__ << "(" << __LINE__ - << "): failed to create directory \"" << d << "\"" << endl; - return nullptr; - } - } -#else - while ((i = name.find_first_of('/', i + 1)) != string::npos) { - string d = tmp + "/" + name.substr(0, i); - if (mkdir(d.c_str(), 0777)) { - cerr << "ERROR: " << __FILE__ << "(" << __LINE__ - << "): failed to create directory \"" << d << "\"" << endl; - return nullptr; - } - } -#endif - - auto stm = std::ofstream(path); - for (auto i : lines) { - stm << i << std::endl; - } - return new MockFile(path); -} - -RunfilesTest::MockFile::~MockFile() { std::remove(path_.c_str()); } - -TEST_F(RunfilesTest, CreatesManifestBasedRunfilesFromManifestNextToBinary) { - unique_ptr mf(MockFile::Create( - "foo" LINE_AS_STRING() ".runfiles_manifest", {"a/b c/d"})); - ASSERT_TRUE(mf != nullptr); - string argv0(mf->Path().substr( - 0, mf->Path().size() - string(".runfiles_manifest").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - EXPECT_EQ(r->Rlocation("a/b"), "c/d"); - // We know it's manifest-based because it returns empty string for unknown - // paths. - EXPECT_EQ(r->Rlocation("unknown"), ""); - AssertEnvvars(*r, mf->Path(), ""); -} - -TEST_F(RunfilesTest, - CreatesManifestBasedRunfilesFromManifestInRunfilesDirectory) { - unique_ptr mf(MockFile::Create( - "foo" LINE_AS_STRING() ".runfiles/MANIFEST", {"a/b c/d"})); - ASSERT_TRUE(mf != nullptr); - string argv0(mf->Path().substr( - 0, mf->Path().size() - string(".runfiles/MANIFEST").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - EXPECT_EQ(r->Rlocation("a/b"), "c/d"); - EXPECT_EQ(r->Rlocation("foo"), argv0 + ".runfiles/foo"); - AssertEnvvars(*r, mf->Path(), argv0 + ".runfiles"); -} - -TEST_F(RunfilesTest, CreatesManifestBasedRunfilesFromEnvvar) { - unique_ptr mf(MockFile::Create( - "foo" LINE_AS_STRING() ".runfiles_manifest", {"a/b c/d"})); - ASSERT_TRUE(mf != nullptr); - - string error; - unique_ptr r(Runfiles::Create("ignore-argv0", mf->Path(), - "non-existent-runfiles_dir", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - EXPECT_EQ(r->Rlocation("a/b"), "c/d"); - // We know it's manifest-based because it returns empty string for unknown - // paths. - EXPECT_EQ(r->Rlocation("unknown"), ""); - AssertEnvvars(*r, mf->Path(), ""); -} - -TEST_F(RunfilesTest, CannotCreateManifestBasedRunfilesDueToBadManifest) { - unique_ptr mf(MockFile::Create( - "foo" LINE_AS_STRING() ".runfiles_manifest", {"a b", "nospace"})); - ASSERT_TRUE(mf != nullptr); - - string error; - unique_ptr r( - Runfiles::Create("ignore-argv0", mf->Path(), "", &error)); - EXPECT_EQ(r, nullptr); - EXPECT_NE(error.find("bad runfiles manifest entry"), string::npos); - EXPECT_NE(error.find("line #2: \"nospace\""), string::npos); -} - -TEST_F(RunfilesTest, ManifestBasedRunfilesRlocationAndEnvVars) { - unique_ptr mf( - MockFile::Create("foo" LINE_AS_STRING() ".runfiles_manifest", - { - "a/b c/d", - "e/f target path with spaces", - " h/\\si j k", - " dir\\swith\\sspaces l/m", - " h/\\n\\s\\bi j k \\n\\b", - "not_escaped with\\backslash and spaces", - })); - ASSERT_TRUE(mf != nullptr); - - string error; - unique_ptr r( - Runfiles::Create("ignore-argv0", mf->Path(), "", &error)); - - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - EXPECT_EQ(r->Rlocation("a/b"), "c/d"); - EXPECT_EQ(r->Rlocation("c/d"), ""); - EXPECT_EQ(r->Rlocation(""), ""); - EXPECT_EQ(r->Rlocation("foo"), ""); - EXPECT_EQ(r->Rlocation("foo/"), ""); - EXPECT_EQ(r->Rlocation("foo/bar"), ""); - EXPECT_EQ(r->Rlocation("../foo"), ""); - EXPECT_EQ(r->Rlocation("foo/.."), ""); - EXPECT_EQ(r->Rlocation("foo/../bar"), ""); - EXPECT_EQ(r->Rlocation("./foo"), ""); - EXPECT_EQ(r->Rlocation("foo/."), ""); - EXPECT_EQ(r->Rlocation("foo/./bar"), ""); - EXPECT_EQ(r->Rlocation("//foo"), ""); - EXPECT_EQ(r->Rlocation("foo//"), ""); - EXPECT_EQ(r->Rlocation("foo//bar"), ""); - EXPECT_EQ(r->Rlocation("/Foo"), "/Foo"); - EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo"); - EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo"); - EXPECT_EQ(r->Rlocation("a/b/file"), "c/d/file"); - EXPECT_EQ(r->Rlocation("a/b/deeply/nested/file"), "c/d/deeply/nested/file"); - EXPECT_EQ(r->Rlocation("a/b/deeply/nested/file with spaces"), - "c/d/deeply/nested/file with spaces"); - EXPECT_EQ(r->Rlocation("e/f"), "target path with spaces"); - EXPECT_EQ(r->Rlocation("e/f/file"), "target path with spaces/file"); - EXPECT_EQ(r->Rlocation("h/ i"), "j k"); - EXPECT_EQ(r->Rlocation("h/\n \\i"), "j k \n\\"); - EXPECT_EQ(r->Rlocation("dir with spaces"), "l/m"); - EXPECT_EQ(r->Rlocation("dir with spaces/file"), "l/m/file"); - EXPECT_EQ(r->Rlocation("not_escaped"), "with\\backslash and spaces"); -} - -TEST_F(RunfilesTest, DirectoryBasedRunfilesRlocationAndEnvVars) { - unique_ptr dummy( - MockFile::Create("foo" LINE_AS_STRING() ".runfiles/dummy", {"a/b c/d"})); - ASSERT_TRUE(dummy != nullptr); - string dir = dummy->DirName(); - - string error; - unique_ptr r(Runfiles::Create("ignore-argv0", "", dir, &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - EXPECT_EQ(r->Rlocation("a/b"), dir + "/a/b"); - EXPECT_EQ(r->Rlocation("c/d"), dir + "/c/d"); - EXPECT_EQ(r->Rlocation(""), ""); - EXPECT_EQ(r->Rlocation("foo"), dir + "/foo"); - EXPECT_EQ(r->Rlocation("foo/"), dir + "/foo/"); - EXPECT_EQ(r->Rlocation("foo/bar"), dir + "/foo/bar"); - EXPECT_EQ(r->Rlocation("../foo"), ""); - EXPECT_EQ(r->Rlocation("foo/.."), ""); - EXPECT_EQ(r->Rlocation("foo/../bar"), ""); - EXPECT_EQ(r->Rlocation("./foo"), ""); - EXPECT_EQ(r->Rlocation("foo/."), ""); - EXPECT_EQ(r->Rlocation("foo/./bar"), ""); - EXPECT_EQ(r->Rlocation("//foo"), ""); - EXPECT_EQ(r->Rlocation("foo//"), ""); - EXPECT_EQ(r->Rlocation("foo//bar"), ""); - EXPECT_EQ(r->Rlocation("/Foo"), "/Foo"); - EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo"); - EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo"); - AssertEnvvars(*r, "", dir); -} - -TEST_F(RunfilesTest, ManifestAndDirectoryBasedRunfilesRlocationAndEnvVars) { - unique_ptr mf(MockFile::Create( - "foo" LINE_AS_STRING() ".runfiles/MANIFEST", {"a/b c/d"})); - ASSERT_TRUE(mf != nullptr); - string dir = mf->DirName(); - - string error; - unique_ptr r( - Runfiles::Create("ignore-argv0", mf->Path(), "", &error)); - - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - EXPECT_EQ(r->Rlocation("a/b"), "c/d"); - EXPECT_EQ(r->Rlocation("c/d"), dir + "/c/d"); - EXPECT_EQ(r->Rlocation(""), ""); - EXPECT_EQ(r->Rlocation("foo"), dir + "/foo"); - EXPECT_EQ(r->Rlocation("foo/"), dir + "/foo/"); - EXPECT_EQ(r->Rlocation("foo/bar"), dir + "/foo/bar"); - EXPECT_EQ(r->Rlocation("../foo"), ""); - EXPECT_EQ(r->Rlocation("foo/.."), ""); - EXPECT_EQ(r->Rlocation("foo/../bar"), ""); - EXPECT_EQ(r->Rlocation("./foo"), ""); - EXPECT_EQ(r->Rlocation("foo/."), ""); - EXPECT_EQ(r->Rlocation("foo/./bar"), ""); - EXPECT_EQ(r->Rlocation("//foo"), ""); - EXPECT_EQ(r->Rlocation("foo//"), ""); - EXPECT_EQ(r->Rlocation("foo//bar"), ""); - EXPECT_EQ(r->Rlocation("/Foo"), "/Foo"); - EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo"); - EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo"); - EXPECT_EQ(r->Rlocation("a/b/file"), "c/d/file"); - EXPECT_EQ(r->Rlocation("a/b/deeply/nested/file"), "c/d/deeply/nested/file"); - AssertEnvvars(*r, mf->Path(), dir); -} - -TEST_F(RunfilesTest, ManifestBasedRunfilesEnvVars) { - unique_ptr mf( - MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles_manifest"))); - ASSERT_TRUE(mf != nullptr); - - string error; - unique_ptr r( - Runfiles::Create("ignore-argv0", mf->Path(), "", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - AssertEnvvars(*r, mf->Path(), ""); -} - -TEST_F(RunfilesTest, CreatesDirectoryBasedRunfilesFromDirectoryNextToBinary) { - // We create a directory as a side-effect of creating a mock file. - unique_ptr mf( - MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/dummy"))); - string argv0(mf->Path().substr( - 0, mf->Path().size() - string(".runfiles/dummy").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - EXPECT_EQ(r->Rlocation("a/b"), argv0 + ".runfiles/a/b"); - // We know it's directory-based because it returns some result for unknown - // paths. - EXPECT_EQ(r->Rlocation("unknown"), argv0 + ".runfiles/unknown"); - AssertEnvvars(*r, "", argv0 + ".runfiles"); -} - -TEST_F(RunfilesTest, CreatesDirectoryBasedRunfilesFromEnvvar) { - // We create a directory as a side-effect of creating a mock file. - unique_ptr mf( - MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/dummy"))); - string dir = mf->DirName(); - - string error; - unique_ptr r(Runfiles::Create("ignore-argv0", "", dir, &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - EXPECT_EQ(r->Rlocation("a/b"), dir + "/a/b"); - EXPECT_EQ(r->Rlocation("foo"), dir + "/foo"); - EXPECT_EQ(r->Rlocation("/Foo"), "/Foo"); - EXPECT_EQ(r->Rlocation("c:/Foo"), "c:/Foo"); - EXPECT_EQ(r->Rlocation("c:\\Foo"), "c:\\Foo"); - AssertEnvvars(*r, "", dir); -} - -TEST_F(RunfilesTest, FailsToCreateAnyRunfilesBecauseEnvvarsAreNotDefined) { - unique_ptr mf( - MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/MANIFEST"))); - ASSERT_TRUE(mf != nullptr); - - string error; - unique_ptr r( - Runfiles::Create("ignore-argv0", mf->Path(), "whatever", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - // We create a directory as a side-effect of creating a mock file. - mf.reset(MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/dummy"))); - r.reset(Runfiles::Create("ignore-argv0", "", mf->DirName(), &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - r.reset(Runfiles::Create("ignore-argv0", /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", &error)); - EXPECT_EQ(r, nullptr); - EXPECT_NE(error.find("cannot find runfiles"), string::npos); -} - -TEST_F(RunfilesTest, MockFileTest) { - { - unique_ptr mf( - MockFile::Create(string("foo" LINE_AS_STRING() "/.."))); - EXPECT_TRUE(mf == nullptr); - } - - { - unique_ptr mf(MockFile::Create(string("/Foo" LINE_AS_STRING()))); - EXPECT_TRUE(mf == nullptr); - } - - { - unique_ptr mf( - MockFile::Create(string("C:/Foo" LINE_AS_STRING()))); - EXPECT_TRUE(mf == nullptr); - } - - string path; - { - unique_ptr mf( - MockFile::Create(string("foo" LINE_AS_STRING() "/bar1/qux"))); - ASSERT_TRUE(mf != nullptr); - path = mf->Path(); - - std::ifstream stm(path); - EXPECT_TRUE(stm.good()); - string actual; - stm >> actual; - EXPECT_TRUE(actual.empty()); - } - { - std::ifstream stm(path); - EXPECT_FALSE(stm.good()); - } - - { - unique_ptr mf(MockFile::Create( - string("foo" LINE_AS_STRING() "/bar2/qux"), vector())); - ASSERT_TRUE(mf != nullptr); - path = mf->Path(); - - std::ifstream stm(path); - EXPECT_TRUE(stm.good()); - string actual; - stm >> actual; - EXPECT_TRUE(actual.empty()); - } - { - std::ifstream stm(path); - EXPECT_FALSE(stm.good()); - } - - { - unique_ptr mf( - MockFile::Create(string("foo" LINE_AS_STRING() "/bar3/qux"), - {"hello world", "you are beautiful"})); - ASSERT_TRUE(mf != nullptr); - path = mf->Path(); - - std::ifstream stm(path); - EXPECT_TRUE(stm.good()); - string actual; - std::getline(stm, actual); - EXPECT_EQ("hello world", actual); - std::getline(stm, actual); - EXPECT_EQ("you are beautiful", actual); - std::getline(stm, actual); - EXPECT_EQ("", actual); - } - { - std::ifstream stm(path); - EXPECT_FALSE(stm.good()); - } -} - -TEST_F(RunfilesTest, IsAbsolute) { - EXPECT_FALSE(TestOnly_IsAbsolute("foo")); - EXPECT_FALSE(TestOnly_IsAbsolute("foo/bar")); - EXPECT_FALSE(TestOnly_IsAbsolute("\\foo")); - EXPECT_TRUE(TestOnly_IsAbsolute("c:\\foo")); - EXPECT_TRUE(TestOnly_IsAbsolute("c:/foo")); - EXPECT_TRUE(TestOnly_IsAbsolute("/foo")); - EXPECT_TRUE(TestOnly_IsAbsolute("x:\\foo")); - EXPECT_FALSE(TestOnly_IsAbsolute("::\\foo")); - EXPECT_FALSE(TestOnly_IsAbsolute("x\\foo")); - EXPECT_FALSE(TestOnly_IsAbsolute("x:")); - EXPECT_TRUE(TestOnly_IsAbsolute("x:\\")); -} - -TEST_F(RunfilesTest, PathsFromEnvVars) { - string mf, dir, rm; - - // Both envvars have a valid value. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1.runfiles/MANIFEST", "mock2.runfiles", - [](const string& path) { return path == "mock1.runfiles/MANIFEST"; }, - [](const string& path) { return path == "mock2.runfiles"; }, &mf, &dir)); - EXPECT_EQ(mf, "mock1.runfiles/MANIFEST"); - EXPECT_EQ(dir, "mock2.runfiles"); - - // RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good and there's a - // runfiles manifest in the runfiles directory. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1.runfiles/MANIFEST", "mock2.runfiles", - [](const string& path) { return path == "mock2.runfiles/MANIFEST"; }, - [](const string& path) { return path == "mock2.runfiles"; }, &mf, &dir)); - EXPECT_EQ(mf, "mock2.runfiles/MANIFEST"); - EXPECT_EQ(dir, "mock2.runfiles"); - - // RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good, but there's no - // runfiles manifest in the runfiles directory. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1.runfiles/MANIFEST", "mock2.runfiles", - [](const string& path) { return false; }, - [](const string& path) { return path == "mock2.runfiles"; }, &mf, &dir)); - EXPECT_EQ(mf, ""); - EXPECT_EQ(dir, "mock2.runfiles"); - - // RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, and it is in - // a valid-looking runfiles directory. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1.runfiles/MANIFEST", "mock2", - [](const string& path) { return path == "mock1.runfiles/MANIFEST"; }, - [](const string& path) { return path == "mock1.runfiles"; }, &mf, &dir)); - EXPECT_EQ(mf, "mock1.runfiles/MANIFEST"); - EXPECT_EQ(dir, "mock1.runfiles"); - - // RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, but it is not - // in any valid-looking runfiles directory. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1/MANIFEST", "mock2", - [](const string& path) { return path == "mock1/MANIFEST"; }, - [](const string& path) { return false; }, &mf, &dir)); - EXPECT_EQ(mf, "mock1/MANIFEST"); - EXPECT_EQ(dir, ""); - - // Both envvars are invalid, but there's a manifest in a runfiles directory - // next to argv0, however there's no other content in the runfiles directory. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1/MANIFEST", "mock2", - [](const string& path) { return path == "argv0.runfiles/MANIFEST"; }, - [](const string& path) { return false; }, &mf, &dir)); - EXPECT_EQ(mf, "argv0.runfiles/MANIFEST"); - EXPECT_EQ(dir, ""); - - // Both envvars are invalid, but there's a manifest next to argv0. There's - // no runfiles tree anywhere. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1/MANIFEST", "mock2", - [](const string& path) { return path == "argv0.runfiles_manifest"; }, - [](const string& path) { return false; }, &mf, &dir)); - EXPECT_EQ(mf, "argv0.runfiles_manifest"); - EXPECT_EQ(dir, ""); - - // Both envvars are invalid, but there's a valid manifest next to argv0, and a - // valid runfiles directory (without a manifest in it). - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1/MANIFEST", "mock2", - [](const string& path) { return path == "argv0.runfiles_manifest"; }, - [](const string& path) { return path == "argv0.runfiles"; }, &mf, &dir)); - EXPECT_EQ(mf, "argv0.runfiles_manifest"); - EXPECT_EQ(dir, "argv0.runfiles"); - - // Both envvars are invalid, but there's a valid runfiles directory next to - // argv0, though no manifest in it. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1/MANIFEST", "mock2", - [](const string& path) { return false; }, - [](const string& path) { return path == "argv0.runfiles"; }, &mf, &dir)); - EXPECT_EQ(mf, ""); - EXPECT_EQ(dir, "argv0.runfiles"); - - // Both envvars are invalid, but there's a valid runfiles directory next to - // argv0 with a valid manifest in it. - EXPECT_TRUE(TestOnly_PathsFrom( - "argv0", "mock1/MANIFEST", "mock2", - [](const string& path) { return path == "argv0.runfiles/MANIFEST"; }, - [](const string& path) { return path == "argv0.runfiles"; }, &mf, &dir)); - EXPECT_EQ(mf, "argv0.runfiles/MANIFEST"); - EXPECT_EQ(dir, "argv0.runfiles"); -} - -TEST_F(RunfilesTest, ManifestBasedRlocationWithRepoMapping_fromMain) { - string uid = LINE_AS_STRING(); - unique_ptr rm( - MockFile::Create("foo" + uid + ".repo_mapping", - {",config.json,config.json+1.2.3", ",my_module,_main", - ",my_protobuf,protobuf+3.19.2", ",my_workspace,_main", - "protobuf+3.19.2,config.json,config.json+1.2.3", - "protobuf+3.19.2,protobuf,protobuf+3.19.2"})); - ASSERT_TRUE(rm != nullptr); - unique_ptr mf(MockFile::Create( - "foo" + uid + ".runfiles_manifest", - {"_repo_mapping " + rm->Path(), "config.json /etc/config.json", - "protobuf+3.19.2/foo/runfile C:/Actual Path\\protobuf\\runfile", - "_main/bar/runfile /the/path/./to/other//other runfile.txt", - "protobuf+3.19.2/bar/dir E:\\Actual Path\\Directory"})); - ASSERT_TRUE(mf != nullptr); - string argv0(mf->Path().substr( - 0, mf->Path().size() - string(".runfiles_manifest").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", - /*source_repository=*/"", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - EXPECT_EQ(r->Rlocation("my_module/bar/runfile"), - "/the/path/./to/other//other runfile.txt"); - EXPECT_EQ(r->Rlocation("my_workspace/bar/runfile"), - "/the/path/./to/other//other runfile.txt"); - EXPECT_EQ(r->Rlocation("my_protobuf/foo/runfile"), - "C:/Actual Path\\protobuf\\runfile"); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir"), "E:\\Actual Path\\Directory"); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir/file"), - "E:\\Actual Path\\Directory/file"); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir/de eply/nes ted/fi+le"), - "E:\\Actual Path\\Directory/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("protobuf/foo/runfile"), ""); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir"), ""); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/file"), ""); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/dir/de eply/nes ted/fi+le"), ""); - - EXPECT_EQ(r->Rlocation("_main/bar/runfile"), - "/the/path/./to/other//other runfile.txt"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/foo/runfile"), - "C:/Actual Path\\protobuf\\runfile"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir"), - "E:\\Actual Path\\Directory"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/file"), - "E:\\Actual Path\\Directory/file"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"), - "E:\\Actual Path\\Directory/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("config.json"), "/etc/config.json"); - EXPECT_EQ(r->Rlocation("_main"), ""); - EXPECT_EQ(r->Rlocation("my_module"), ""); - EXPECT_EQ(r->Rlocation("protobuf"), ""); -} - -TEST_F(RunfilesTest, ManifestBasedRlocationWithRepoMapping_fromOtherRepo) { - string uid = LINE_AS_STRING(); - unique_ptr rm( - MockFile::Create("foo" + uid + ".repo_mapping", - {",config.json,config.json+1.2.3", ",my_module,_main", - ",my_protobuf,protobuf+3.19.2", ",my_workspace,_main", - "protobuf+3.19.2,config.json,config.json+1.2.3", - "protobuf+3.19.2,protobuf,protobuf+3.19.2"})); - ASSERT_TRUE(rm != nullptr); - unique_ptr mf(MockFile::Create( - "foo" + uid + ".runfiles_manifest", - {"_repo_mapping " + rm->Path(), "config.json /etc/config.json", - "protobuf+3.19.2/foo/runfile C:/Actual Path\\protobuf\\runfile", - "_main/bar/runfile /the/path/./to/other//other runfile.txt", - "protobuf+3.19.2/bar/dir E:\\Actual Path\\Directory"})); - ASSERT_TRUE(mf != nullptr); - string argv0(mf->Path().substr( - 0, mf->Path().size() - string(".runfiles_manifest").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", - "protobuf+3.19.2", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - EXPECT_EQ(r->Rlocation("protobuf/foo/runfile"), - "C:/Actual Path\\protobuf\\runfile"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir"), "E:\\Actual Path\\Directory"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/file"), - "E:\\Actual Path\\Directory/file"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/de eply/nes ted/fi+le"), - "E:\\Actual Path\\Directory/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("my_module/bar/runfile"), ""); - EXPECT_EQ(r->Rlocation("my_protobuf/foo/runfile"), ""); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir"), ""); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir/file"), ""); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir/de eply/nes ted/fi+le"), ""); - - EXPECT_EQ(r->Rlocation("_main/bar/runfile"), - "/the/path/./to/other//other runfile.txt"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/foo/runfile"), - "C:/Actual Path\\protobuf\\runfile"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir"), - "E:\\Actual Path\\Directory"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/file"), - "E:\\Actual Path\\Directory/file"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"), - "E:\\Actual Path\\Directory/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("config.json"), "/etc/config.json"); - EXPECT_EQ(r->Rlocation("_main"), ""); - EXPECT_EQ(r->Rlocation("my_module"), ""); - EXPECT_EQ(r->Rlocation("protobuf"), ""); -} - -TEST_F(RunfilesTest, DirectoryBasedRlocationWithRepoMapping_fromMain) { - string uid = LINE_AS_STRING(); - unique_ptr rm( - MockFile::Create("foo" + uid + ".runfiles/_repo_mapping", - {",config.json,config.json+1.2.3", ",my_module,_main", - ",my_protobuf,protobuf+3.19.2", ",my_workspace,_main", - "protobuf+3.19.2,config.json,config.json+1.2.3", - "protobuf+3.19.2,protobuf,protobuf+3.19.2"})); - ASSERT_TRUE(rm != nullptr); - string dir = rm->DirName(); - string argv0(dir.substr(0, dir.size() - string(".runfiles").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", - /*source_repository=*/"", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - EXPECT_EQ(r->Rlocation("my_module/bar/runfile"), dir + "/_main/bar/runfile"); - EXPECT_EQ(r->Rlocation("my_workspace/bar/runfile"), - dir + "/_main/bar/runfile"); - EXPECT_EQ(r->Rlocation("my_protobuf/foo/runfile"), - dir + "/protobuf+3.19.2/foo/runfile"); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir"), - dir + "/protobuf+3.19.2/bar/dir"); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir/file"), - dir + "/protobuf+3.19.2/bar/dir/file"); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir/de eply/nes ted/fi+le"), - dir + "/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("protobuf/foo/runfile"), - dir + "/protobuf/foo/runfile"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/dir/de eply/nes ted/fi+le"), - dir + "/protobuf/bar/dir/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("_main/bar/runfile"), dir + "/_main/bar/runfile"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/foo/runfile"), - dir + "/protobuf+3.19.2/foo/runfile"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir"), - dir + "/protobuf+3.19.2/bar/dir"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/file"), - dir + "/protobuf+3.19.2/bar/dir/file"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"), - dir + "/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("config.json"), dir + "/config.json"); -} - -TEST_F(RunfilesTest, DirectoryBasedRlocationWithRepoMapping_fromOtherRepo) { - string uid = LINE_AS_STRING(); - unique_ptr rm( - MockFile::Create("foo" + uid + ".runfiles/_repo_mapping", - {",config.json,config.json+1.2.3", ",my_module,_main", - ",my_protobuf,protobuf+3.19.2", ",my_workspace,_main", - "protobuf+3.19.2,config.json,config.json+1.2.3", - "protobuf+3.19.2,protobuf,protobuf+3.19.2"})); - ASSERT_TRUE(rm != nullptr); - string dir = rm->DirName(); - string argv0(dir.substr(0, dir.size() - string(".runfiles").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", - "protobuf+3.19.2", &error)); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - EXPECT_EQ(r->Rlocation("protobuf/foo/runfile"), - dir + "/protobuf+3.19.2/foo/runfile"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir"), dir + "/protobuf+3.19.2/bar/dir"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/file"), - dir + "/protobuf+3.19.2/bar/dir/file"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/de eply/nes ted/fi+le"), - dir + "/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("my_module/bar/runfile"), - dir + "/my_module/bar/runfile"); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir/de eply/nes ted/fi+le"), - dir + "/my_protobuf/bar/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("_main/bar/runfile"), dir + "/_main/bar/runfile"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/foo/runfile"), - dir + "/protobuf+3.19.2/foo/runfile"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir"), - dir + "/protobuf+3.19.2/bar/dir"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/file"), - dir + "/protobuf+3.19.2/bar/dir/file"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"), - dir + "/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("config.json"), dir + "/config.json"); -} - -TEST_F(RunfilesTest, - DirectoryBasedRlocationWithRepoMapping_fromOtherRepo_withSourceRepo) { - string uid = LINE_AS_STRING(); - unique_ptr rm( - MockFile::Create("foo" + uid + ".runfiles/_repo_mapping", - {",config.json,config.json+1.2.3", ",my_module,_main", - ",my_protobuf,protobuf+3.19.2", ",my_workspace,_main", - "protobuf+3.19.2,config.json,config.json+1.2.3", - "protobuf+3.19.2,protobuf,protobuf+3.19.2"})); - ASSERT_TRUE(rm != nullptr); - string dir = rm->DirName(); - string argv0(dir.substr(0, dir.size() - string(".runfiles").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", - /*source_repository=*/"", &error)); - r = r->WithSourceRepository("protobuf+3.19.2"); - ASSERT_TRUE(r != nullptr); - EXPECT_TRUE(error.empty()); - - EXPECT_EQ(r->Rlocation("protobuf/foo/runfile"), - dir + "/protobuf+3.19.2/foo/runfile"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir"), dir + "/protobuf+3.19.2/bar/dir"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/file"), - dir + "/protobuf+3.19.2/bar/dir/file"); - EXPECT_EQ(r->Rlocation("protobuf/bar/dir/de eply/nes ted/fi+le"), - dir + "/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("my_module/bar/runfile"), - dir + "/my_module/bar/runfile"); - EXPECT_EQ(r->Rlocation("my_protobuf/bar/dir/de eply/nes ted/fi+le"), - dir + "/my_protobuf/bar/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("_main/bar/runfile"), dir + "/_main/bar/runfile"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/foo/runfile"), - dir + "/protobuf+3.19.2/foo/runfile"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir"), - dir + "/protobuf+3.19.2/bar/dir"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/file"), - dir + "/protobuf+3.19.2/bar/dir/file"); - EXPECT_EQ(r->Rlocation("protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"), - dir + "/protobuf+3.19.2/bar/dir/de eply/nes ted/fi+le"); - - EXPECT_EQ(r->Rlocation("config.json"), dir + "/config.json"); -} - -TEST_F(RunfilesTest, InvalidRepoMapping) { - string uid = LINE_AS_STRING(); - unique_ptr rm( - MockFile::Create("foo" + uid + ".runfiles/_repo_mapping", {"a,b"})); - ASSERT_TRUE(rm != nullptr); - string dir = rm->DirName(); - string argv0(dir.substr(0, dir.size() - string(".runfiles").size())); - - string error; - unique_ptr r(Runfiles::Create(argv0, /*runfiles_manifest_file=*/"", - /*runfiles_dir=*/"", - /*source_repository=*/"", &error)); - EXPECT_EQ(r, nullptr); - EXPECT_TRUE(error.find("bad repository mapping") != string::npos); -} - -} // namespace -} // namespace runfiles -} // namespace cpp -} // namespace tools -} // namespace bazel diff --git a/tools/test/windows/tw.cc b/tools/test/windows/tw.cc index a85ae2b697ce46..88a63d2ffb58b0 100644 --- a/tools/test/windows/tw.cc +++ b/tools/test/windows/tw.cc @@ -49,7 +49,7 @@ #include "third_party/ijar/common.h" #include "third_party/ijar/platform_utils.h" #include "third_party/ijar/zip.h" -#include "tools/cpp/runfiles/runfiles.h" +#include "rules_cc/cc/runfiles/runfiles.h" namespace bazel { namespace tools {