|  | // 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 <windows.h> | 
|  | #endif  // _WIN32 | 
|  |  | 
|  | #include <fstream> | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #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<string>& 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<pair<string, string> > 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<char[]> 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<string>()); | 
|  | } | 
|  |  | 
|  | RunfilesTest::MockFile* RunfilesTest::MockFile::Create( | 
|  | const string& name, const vector<string>& 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<MockFile> 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<Runfiles> 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<MockFile> 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<Runfiles> 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<MockFile> mf(MockFile::Create( | 
|  | "foo" LINE_AS_STRING() ".runfiles_manifest", {"a/b c/d"})); | 
|  | ASSERT_TRUE(mf != nullptr); | 
|  |  | 
|  | string error; | 
|  | unique_ptr<Runfiles> 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<MockFile> mf(MockFile::Create( | 
|  | "foo" LINE_AS_STRING() ".runfiles_manifest", {"a b", "nospace"})); | 
|  | ASSERT_TRUE(mf != nullptr); | 
|  |  | 
|  | string error; | 
|  | unique_ptr<Runfiles> 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<MockFile> mf(MockFile::Create( | 
|  | "foo" LINE_AS_STRING() ".runfiles_manifest", {"a/b c/d"})); | 
|  | ASSERT_TRUE(mf != nullptr); | 
|  |  | 
|  | string error; | 
|  | unique_ptr<Runfiles> 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"); | 
|  | } | 
|  |  | 
|  | TEST_F(RunfilesTest, DirectoryBasedRunfilesRlocationAndEnvVars) { | 
|  | unique_ptr<MockFile> 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<Runfiles> 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<MockFile> 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<Runfiles> 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<MockFile> mf( | 
|  | MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles_manifest"))); | 
|  | ASSERT_TRUE(mf != nullptr); | 
|  |  | 
|  | string error; | 
|  | unique_ptr<Runfiles> 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<MockFile> 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<Runfiles> 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<MockFile> mf( | 
|  | MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/dummy"))); | 
|  | string dir = mf->DirName(); | 
|  |  | 
|  | string error; | 
|  | unique_ptr<Runfiles> 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<MockFile> mf( | 
|  | MockFile::Create(string("foo" LINE_AS_STRING() ".runfiles/MANIFEST"))); | 
|  | ASSERT_TRUE(mf != nullptr); | 
|  |  | 
|  | string error; | 
|  | unique_ptr<Runfiles> 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<MockFile> mf( | 
|  | MockFile::Create(string("foo" LINE_AS_STRING() "/.."))); | 
|  | EXPECT_TRUE(mf == nullptr); | 
|  | } | 
|  |  | 
|  | { | 
|  | unique_ptr<MockFile> mf(MockFile::Create(string("/Foo" LINE_AS_STRING()))); | 
|  | EXPECT_TRUE(mf == nullptr); | 
|  | } | 
|  |  | 
|  | { | 
|  | unique_ptr<MockFile> mf( | 
|  | MockFile::Create(string("C:/Foo" LINE_AS_STRING()))); | 
|  | EXPECT_TRUE(mf == nullptr); | 
|  | } | 
|  |  | 
|  | string path; | 
|  | { | 
|  | unique_ptr<MockFile> 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<MockFile> mf(MockFile::Create( | 
|  | string("foo" LINE_AS_STRING() "/bar2/qux"), vector<string>())); | 
|  | 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<MockFile> 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<MockFile> rm(MockFile::Create( | 
|  | "foo" + uid + ".repo_mapping", | 
|  | {",my_module,_main", ",my_protobuf,protobuf~3.19.2", | 
|  | ",my_workspace,_main", "protobuf~3.19.2,protobuf,protobuf~3.19.2"})); | 
|  | ASSERT_TRUE(rm != nullptr); | 
|  | unique_ptr<MockFile> 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<Runfiles> 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<MockFile> rm(MockFile::Create( | 
|  | "foo" + uid + ".repo_mapping", | 
|  | {",my_module,_main", ",my_protobuf,protobuf~3.19.2", | 
|  | ",my_workspace,_main", "protobuf~3.19.2,protobuf,protobuf~3.19.2"})); | 
|  | ASSERT_TRUE(rm != nullptr); | 
|  | unique_ptr<MockFile> 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<Runfiles> 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<MockFile> rm(MockFile::Create( | 
|  | "foo" + uid + ".runfiles/_repo_mapping", | 
|  | {",my_module,_main", ",my_protobuf,protobuf~3.19.2", | 
|  | ",my_workspace,_main", "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<Runfiles> 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<MockFile> rm(MockFile::Create( | 
|  | "foo" + uid + ".runfiles/_repo_mapping", | 
|  | {",my_module,_main", ",my_protobuf,protobuf~3.19.2", | 
|  | ",my_workspace,_main", "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<Runfiles> 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<MockFile> rm(MockFile::Create( | 
|  | "foo" + uid + ".runfiles/_repo_mapping", | 
|  | {",my_module,_main", ",my_protobuf,protobuf~3.19.2", | 
|  | ",my_workspace,_main", "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<Runfiles> 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<MockFile> 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<Runfiles> 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 |