install_paths_test.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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/install/install_paths.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. #include <memory>
  8. #include <string>
  9. #include "common/check.h"
  10. #include "llvm/ADT/SmallString.h"
  11. #include "llvm/Support/FileSystem.h"
  12. #include "llvm/Support/FormatVariadic.h"
  13. #include "llvm/Support/Path.h"
  14. #include "testing/base/global_exe_path.h"
  15. #include "tools/cpp/runfiles/runfiles.h"
  16. namespace Carbon {
  17. class InstallPathsTestPeer {
  18. public:
  19. static auto GetPrefix(const InstallPaths& paths) -> llvm::StringRef {
  20. return paths.prefix_;
  21. }
  22. };
  23. namespace {
  24. using ::bazel::tools::cpp::runfiles::Runfiles;
  25. using ::testing::Eq;
  26. using ::testing::HasSubstr;
  27. using ::testing::Optional;
  28. using ::testing::StartsWith;
  29. class InstallPathsTest : public ::testing::Test {
  30. public:
  31. InstallPathsTest() {
  32. std::string error;
  33. test_runfiles_.reset(Runfiles::Create(Testing::GetExePath().str(), &error));
  34. CARBON_CHECK(test_runfiles_ != nullptr, "{0}", error);
  35. }
  36. // Test the install paths found with the given `exe_path`. Will check that
  37. // the detected install prefix path starts with `prefix_startswith`, and then
  38. // check that the path accessors point to the right kind of file or
  39. // directory.
  40. auto TestInstallPaths(const InstallPaths& paths) -> void {
  41. auto prefix = InstallPathsTestPeer::GetPrefix(paths);
  42. SCOPED_TRACE(llvm::formatv("Install prefix: '{0}'", prefix));
  43. // Grab a the prefix into a string to make it easier to use in the test.
  44. EXPECT_TRUE(llvm::sys::fs::exists(prefix));
  45. EXPECT_TRUE(llvm::sys::fs::is_directory(prefix));
  46. // Now check that all the expected parts of the toolchain's install are in
  47. // fact found using the API.
  48. llvm::SmallString<256> driver_path(prefix);
  49. // TODO: Adjust this to work equally well on Windows.
  50. llvm::sys::path::append(driver_path, llvm::sys::path::Style::posix,
  51. "bin/carbon");
  52. EXPECT_TRUE(llvm::sys::fs::exists(driver_path)) << "path: " << driver_path;
  53. EXPECT_TRUE(llvm::sys::fs::can_execute(driver_path))
  54. << "path: " << driver_path;
  55. std::string core_package_path = paths.core_package();
  56. ASSERT_THAT(core_package_path, StartsWith(prefix));
  57. EXPECT_TRUE(llvm::sys::fs::exists(core_package_path + "/prelude.carbon"))
  58. << "path: " << core_package_path;
  59. std::string llvm_bin_path = paths.llvm_install_bin();
  60. ASSERT_THAT(llvm_bin_path, StartsWith(prefix));
  61. EXPECT_TRUE(llvm::sys::fs::exists(llvm_bin_path))
  62. << "path: " << llvm_bin_path;
  63. EXPECT_TRUE(llvm::sys::fs::is_directory(llvm_bin_path))
  64. << "path: " << llvm_bin_path;
  65. for (llvm::StringRef llvm_bin : {"ld.lld", "ld64.lld"}) {
  66. llvm::SmallString<128> bin_path;
  67. bin_path.assign(llvm_bin_path);
  68. llvm::sys::path::append(bin_path, llvm_bin);
  69. EXPECT_TRUE(llvm::sys::fs::exists(bin_path)) << "path: " << bin_path;
  70. EXPECT_TRUE(llvm::sys::fs::can_execute(bin_path)) << "path: " << bin_path;
  71. }
  72. }
  73. std::unique_ptr<Runfiles> test_runfiles_;
  74. };
  75. TEST_F(InstallPathsTest, PrefixRootBusybox) {
  76. std::string installed_driver_path = test_runfiles_->Rlocation(
  77. "carbon/toolchain/install/prefix_root/lib/carbon/carbon-busybox");
  78. auto paths = InstallPaths::MakeExeRelative(installed_driver_path);
  79. ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
  80. TestInstallPaths(paths);
  81. }
  82. TEST_F(InstallPathsTest, PrefixRootExplicit) {
  83. std::string marker_path = test_runfiles_->Rlocation(
  84. "carbon/toolchain/install/prefix_root/lib/carbon/carbon_install.txt");
  85. llvm::StringRef prefix_path = marker_path;
  86. CARBON_CHECK(prefix_path.consume_back("lib/carbon/carbon_install.txt"),
  87. "Unexpected suffix of the marker path: {0}", marker_path);
  88. auto paths = InstallPaths::Make(prefix_path);
  89. ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
  90. TestInstallPaths(paths);
  91. }
  92. TEST_F(InstallPathsTest, TestRunfiles) {
  93. auto paths = InstallPaths::MakeForBazelRunfiles(Testing::GetExePath());
  94. ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
  95. TestInstallPaths(paths);
  96. }
  97. TEST_F(InstallPathsTest, BinaryRunfiles) {
  98. std::string test_binary_path =
  99. test_runfiles_->Rlocation("carbon/toolchain/install/test_binary");
  100. CARBON_CHECK(llvm::sys::fs::can_execute(test_binary_path), "{0}",
  101. test_binary_path);
  102. auto paths = InstallPaths::MakeForBazelRunfiles(test_binary_path);
  103. ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
  104. TestInstallPaths(paths);
  105. }
  106. TEST_F(InstallPathsTest, Errors) {
  107. auto paths = InstallPaths::Make("/foo/bar/baz");
  108. EXPECT_THAT(paths.error(), Optional(HasSubstr("foo/bar/baz")));
  109. EXPECT_THAT(InstallPathsTestPeer::GetPrefix(paths), Eq(""));
  110. paths = InstallPaths::MakeExeRelative("foo/bar/baz");
  111. EXPECT_THAT(paths.error(), Optional(HasSubstr("foo/bar/baz")));
  112. EXPECT_THAT(InstallPathsTestPeer::GetPrefix(paths), Eq(""));
  113. // Note that we can't test the runfiles code path from within a test because
  114. // it succeeds some of the time even with a bogus executable name.
  115. }
  116. } // namespace
  117. } // namespace Carbon