// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "toolchain/base/install_paths.h" #include #include #include #include #include #include "common/check.h" #include "common/error_test_helpers.h" #include "common/filesystem.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/FormatVariadic.h" #include "testing/base/global_exe_path.h" #include "tools/cpp/runfiles/runfiles.h" namespace Carbon { class InstallPathsTestPeer { public: static auto GetRoot(const InstallPaths& paths) -> std::filesystem::path { return paths.root_; } }; namespace { using ::bazel::tools::cpp::runfiles::Runfiles; using ::testing::_; using ::testing::Eq; using ::testing::HasSubstr; using Testing::IsSuccess; using ::testing::Optional; using ::testing::StartsWith; class InstallPathsTest : public ::testing::Test { public: InstallPathsTest() { std::string error; test_runfiles_.reset(Runfiles::Create(Testing::GetExePath().str(), &error)); CARBON_CHECK(test_runfiles_ != nullptr, "{0}", error); } // Test the install paths found with the given `exe_path`. Will check that // the detected install root path has the expected location relative to the // FHS layout, and then check that the path accessors point to the right kind // of file or directory. auto TestInstallPaths(const InstallPaths& paths) -> void { std::filesystem::path root_path = InstallPathsTestPeer::GetRoot(paths); SCOPED_TRACE(llvm::formatv("Install root: '{0}'", root_path)); // Open the root directory. auto root_result = Filesystem::Cwd().OpenDir(root_path); ASSERT_THAT(root_result, IsSuccess(_)); Filesystem::Dir root = *std::move(root_result); std::filesystem::path core_package_path = paths.core_package(); ASSERT_THAT(core_package_path, StartsWith(root_path)); EXPECT_THAT(Filesystem::Cwd().Access(core_package_path / "prelude.carbon"), IsSuccess(Eq(true))) << "path: " << core_package_path; std::filesystem::path llvm_bin_path = paths.llvm_install_bin(); ASSERT_THAT(llvm_bin_path, StartsWith(root_path)); auto open_result = Filesystem::Cwd().OpenDir(llvm_bin_path); ASSERT_THAT(open_result, IsSuccess(_)); Filesystem::Dir llvm_bin = *std::move(open_result); for (std::filesystem::path bin_name : {"ld.lld", "ld64.lld"}) { EXPECT_THAT( llvm_bin.Access(bin_name, Filesystem::AccessCheckFlags::Execute), IsSuccess(Eq(true))) << "path: " << (llvm_bin_path / bin_name); } } std::unique_ptr test_runfiles_; }; TEST_F(InstallPathsTest, RootBusybox) { std::string installed_busybox_path = test_runfiles_->Rlocation("carbon/toolchain/install/carbon-busybox"); auto paths = InstallPaths::MakeExeRelative(installed_busybox_path); ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error(); TestInstallPaths(paths); } TEST_F(InstallPathsTest, RootExplicit) { std::string marker_path = test_runfiles_->Rlocation("carbon/toolchain/install/carbon_install.txt"); llvm::StringRef root_path = marker_path; CARBON_CHECK(root_path.consume_back("carbon_install.txt"), "Unexpected suffix of the marker path: {0}", marker_path); auto paths = InstallPaths::Make(root_path); ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error(); TestInstallPaths(paths); } TEST_F(InstallPathsTest, TestRunfiles) { auto paths = InstallPaths::MakeForBazelRunfiles(Testing::GetExePath()); ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error(); TestInstallPaths(paths); } TEST_F(InstallPathsTest, BinaryRunfiles) { std::filesystem::path test_binary_path = test_runfiles_->Rlocation("carbon/toolchain/base/test_binary"); ASSERT_THAT(Filesystem::Cwd().Access(test_binary_path, Filesystem::AccessCheckFlags::Execute), IsSuccess(Eq(true))) << "path: " << test_binary_path; auto paths = InstallPaths::MakeForBazelRunfiles(test_binary_path.native()); ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error(); TestInstallPaths(paths); } TEST_F(InstallPathsTest, Errors) { auto paths = InstallPaths::Make("/foo/bar/baz"); EXPECT_THAT(paths.error(), Optional(HasSubstr("foo/bar/baz"))); EXPECT_THAT(InstallPathsTestPeer::GetRoot(paths), Eq("")); paths = InstallPaths::MakeExeRelative("foo/bar/baz"); EXPECT_THAT(paths.error(), Optional(HasSubstr("foo/bar/baz"))); EXPECT_THAT(InstallPathsTestPeer::GetRoot(paths), Eq("")); // Note that we can't test the runfiles code path from within a test because // it succeeds some of the time even with a bogus executable name. } } // namespace } // namespace Carbon