install_paths_test.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/base/install_paths.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. #include <filesystem>
  8. #include <memory>
  9. #include <string>
  10. #include "common/check.h"
  11. #include "common/error_test_helpers.h"
  12. #include "common/filesystem.h"
  13. #include "llvm/ADT/SmallString.h"
  14. #include "llvm/Support/FormatVariadic.h"
  15. #include "testing/base/global_exe_path.h"
  16. #include "tools/cpp/runfiles/runfiles.h"
  17. namespace Carbon {
  18. class InstallPathsTestPeer {
  19. public:
  20. static auto GetRoot(const InstallPaths& paths) -> std::filesystem::path {
  21. return paths.root_;
  22. }
  23. };
  24. namespace {
  25. using ::bazel::tools::cpp::runfiles::Runfiles;
  26. using ::testing::_;
  27. using ::testing::Eq;
  28. using ::testing::HasSubstr;
  29. using Testing::IsSuccess;
  30. using ::testing::Optional;
  31. using ::testing::StartsWith;
  32. class InstallPathsTest : public ::testing::Test {
  33. public:
  34. InstallPathsTest() {
  35. std::string error;
  36. test_runfiles_.reset(Runfiles::Create(Testing::GetExePath().str(), &error));
  37. CARBON_CHECK(test_runfiles_ != nullptr, "{0}", error);
  38. }
  39. // Test the install paths found with the given `exe_path`. Will check that
  40. // the detected install root path has the expected location relative to the
  41. // FHS layout, and then check that the path accessors point to the right kind
  42. // of file or directory.
  43. auto TestInstallPaths(const InstallPaths& paths) -> void {
  44. std::filesystem::path root_path = InstallPathsTestPeer::GetRoot(paths);
  45. SCOPED_TRACE(llvm::formatv("Install root: '{0}'", root_path));
  46. // Open the root directory.
  47. auto root_result = Filesystem::Cwd().OpenDir(root_path);
  48. ASSERT_THAT(root_result, IsSuccess(_));
  49. Filesystem::Dir root = *std::move(root_result);
  50. std::filesystem::path core_package_path = paths.core_package();
  51. ASSERT_THAT(core_package_path, StartsWith(root_path));
  52. EXPECT_THAT(Filesystem::Cwd().Access(core_package_path / "prelude.carbon"),
  53. IsSuccess(Eq(true)))
  54. << "path: " << core_package_path;
  55. std::filesystem::path llvm_bin_path = paths.llvm_install_bin();
  56. ASSERT_THAT(llvm_bin_path, StartsWith(root_path));
  57. auto open_result = Filesystem::Cwd().OpenDir(llvm_bin_path);
  58. ASSERT_THAT(open_result, IsSuccess(_));
  59. Filesystem::Dir llvm_bin = *std::move(open_result);
  60. for (std::filesystem::path bin_name : {"ld.lld", "ld64.lld"}) {
  61. EXPECT_THAT(
  62. llvm_bin.Access(bin_name, Filesystem::AccessCheckFlags::Execute),
  63. IsSuccess(Eq(true)))
  64. << "path: " << (llvm_bin_path / bin_name);
  65. }
  66. }
  67. std::unique_ptr<Runfiles> test_runfiles_;
  68. };
  69. TEST_F(InstallPathsTest, RootBusybox) {
  70. std::string installed_busybox_path =
  71. test_runfiles_->Rlocation("carbon/toolchain/install/carbon-busybox");
  72. auto paths = InstallPaths::MakeExeRelative(installed_busybox_path);
  73. ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
  74. TestInstallPaths(paths);
  75. }
  76. TEST_F(InstallPathsTest, RootExplicit) {
  77. std::string marker_path =
  78. test_runfiles_->Rlocation("carbon/toolchain/install/carbon_install.txt");
  79. llvm::StringRef root_path = marker_path;
  80. CARBON_CHECK(root_path.consume_back("carbon_install.txt"),
  81. "Unexpected suffix of the marker path: {0}", marker_path);
  82. auto paths = InstallPaths::Make(root_path);
  83. ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
  84. TestInstallPaths(paths);
  85. }
  86. TEST_F(InstallPathsTest, TestRunfiles) {
  87. auto paths = InstallPaths::MakeForBazelRunfiles(Testing::GetExePath());
  88. ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
  89. TestInstallPaths(paths);
  90. }
  91. TEST_F(InstallPathsTest, BinaryRunfiles) {
  92. std::filesystem::path test_binary_path =
  93. test_runfiles_->Rlocation("carbon/toolchain/base/test_binary");
  94. ASSERT_THAT(Filesystem::Cwd().Access(test_binary_path,
  95. Filesystem::AccessCheckFlags::Execute),
  96. IsSuccess(Eq(true)))
  97. << "path: " << test_binary_path;
  98. auto paths = InstallPaths::MakeForBazelRunfiles(test_binary_path.native());
  99. ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
  100. TestInstallPaths(paths);
  101. }
  102. TEST_F(InstallPathsTest, Errors) {
  103. auto paths = InstallPaths::Make("/foo/bar/baz");
  104. EXPECT_THAT(paths.error(), Optional(HasSubstr("foo/bar/baz")));
  105. EXPECT_THAT(InstallPathsTestPeer::GetRoot(paths), Eq(""));
  106. paths = InstallPaths::MakeExeRelative("foo/bar/baz");
  107. EXPECT_THAT(paths.error(), Optional(HasSubstr("foo/bar/baz")));
  108. EXPECT_THAT(InstallPathsTestPeer::GetRoot(paths), Eq(""));
  109. // Note that we can't test the runfiles code path from within a test because
  110. // it succeeds some of the time even with a bogus executable name.
  111. }
  112. } // namespace
  113. } // namespace Carbon