Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:37

0001 //===- Testing/Support/SupportHelpers.h -----------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H
0010 #define LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H
0011 
0012 #include "llvm/ADT/SmallString.h"
0013 #include "llvm/Support/Error.h"
0014 #include "llvm/Support/FileSystem.h"
0015 #include "llvm/Support/Path.h"
0016 #include "llvm/Support/raw_os_ostream.h"
0017 #include "gmock/gmock-matchers.h"
0018 #include "gtest/gtest-printers.h"
0019 
0020 #include <optional>
0021 #include <string>
0022 
0023 namespace llvm {
0024 namespace detail {
0025 struct ErrorHolder {
0026   std::vector<std::shared_ptr<ErrorInfoBase>> Infos;
0027 
0028   bool Success() const { return Infos.empty(); }
0029 };
0030 
0031 template <typename T> struct ExpectedHolder : public ErrorHolder {
0032   ExpectedHolder(ErrorHolder Err, Expected<T> &Exp)
0033       : ErrorHolder(std::move(Err)), Exp(Exp) {}
0034 
0035   Expected<T> &Exp;
0036 };
0037 
0038 inline void PrintTo(const ErrorHolder &Err, std::ostream *Out) {
0039   raw_os_ostream OS(*Out);
0040   OS << (Err.Success() ? "succeeded" : "failed");
0041   if (!Err.Success()) {
0042     const char *Delim = "  (";
0043     for (const auto &Info : Err.Infos) {
0044       OS << Delim;
0045       Delim = "; ";
0046       Info->log(OS);
0047     }
0048     OS << ")";
0049   }
0050 }
0051 
0052 template <typename T>
0053 void PrintTo(const ExpectedHolder<T> &Item, std::ostream *Out) {
0054   if (Item.Success()) {
0055     *Out << "succeeded with value " << ::testing::PrintToString(*Item.Exp);
0056   } else {
0057     PrintTo(static_cast<const ErrorHolder &>(Item), Out);
0058   }
0059 }
0060 
0061 template <class InnerMatcher> class ValueIsMatcher {
0062 public:
0063   explicit ValueIsMatcher(InnerMatcher ValueMatcher)
0064       : ValueMatcher(ValueMatcher) {}
0065 
0066   template <class T>
0067   operator ::testing::Matcher<const std::optional<T> &>() const {
0068     return ::testing::MakeMatcher(
0069         new Impl<T>(::testing::SafeMatcherCast<T>(ValueMatcher)));
0070   }
0071 
0072   template <class T, class O = std::optional<T>>
0073   class Impl : public ::testing::MatcherInterface<const O &> {
0074   public:
0075     explicit Impl(const ::testing::Matcher<T> &ValueMatcher)
0076         : ValueMatcher(ValueMatcher) {}
0077 
0078     bool MatchAndExplain(const O &Input,
0079                          testing::MatchResultListener *L) const override {
0080       return Input && ValueMatcher.MatchAndExplain(*Input, L);
0081     }
0082 
0083     void DescribeTo(std::ostream *OS) const override {
0084       *OS << "has a value that ";
0085       ValueMatcher.DescribeTo(OS);
0086     }
0087     void DescribeNegationTo(std::ostream *OS) const override {
0088       *OS << "does not have a value that ";
0089       ValueMatcher.DescribeTo(OS);
0090     }
0091 
0092   private:
0093     testing::Matcher<T> ValueMatcher;
0094   };
0095 
0096 private:
0097   InnerMatcher ValueMatcher;
0098 };
0099 } // namespace detail
0100 
0101 /// Matches an std::optional<T> with a value that conforms to an inner matcher.
0102 /// To match std::nullopt you could use Eq(std::nullopt).
0103 template <class InnerMatcher>
0104 detail::ValueIsMatcher<InnerMatcher> ValueIs(const InnerMatcher &ValueMatcher) {
0105   return detail::ValueIsMatcher<InnerMatcher>(ValueMatcher);
0106 }
0107 namespace unittest {
0108 
0109 SmallString<128> getInputFileDirectory(const char *Argv0);
0110 
0111 /// A RAII object that creates a temporary directory upon initialization and
0112 /// removes it upon destruction.
0113 class TempDir {
0114   SmallString<128> Path;
0115 
0116 public:
0117   /// Creates a managed temporary directory.
0118   ///
0119   /// @param Name The name of the directory to create.
0120   /// @param Unique If true, the directory will be created using
0121   ///               llvm::sys::fs::createUniqueDirectory.
0122   explicit TempDir(StringRef Name, bool Unique = false) {
0123     std::error_code EC;
0124     if (Unique) {
0125       EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
0126       if (!EC) {
0127         // Resolve any symlinks in the new directory.
0128         std::string UnresolvedPath(Path.str());
0129         EC = llvm::sys::fs::real_path(UnresolvedPath, Path);
0130       }
0131     } else {
0132       Path = Name;
0133       EC = llvm::sys::fs::create_directory(Path);
0134     }
0135     if (EC)
0136       Path.clear();
0137     EXPECT_FALSE(EC) << EC.message();
0138   }
0139 
0140   ~TempDir() {
0141     if (!Path.empty()) {
0142       EXPECT_FALSE(llvm::sys::fs::remove_directories(Path.str()));
0143     }
0144   }
0145 
0146   TempDir(const TempDir &) = delete;
0147   TempDir &operator=(const TempDir &) = delete;
0148 
0149   TempDir(TempDir &&) = default;
0150   TempDir &operator=(TempDir &&) = default;
0151 
0152   /// The path to the temporary directory.
0153   StringRef path() const { return Path; }
0154 
0155   /// The null-terminated C string pointing to the path.
0156   const char *c_str() { return Path.c_str(); }
0157 
0158   /// Creates a new path by appending the argument to the path of the managed
0159   /// directory using the native path separator.
0160   SmallString<128> path(StringRef component) const {
0161     SmallString<128> Result(Path);
0162     SmallString<128> ComponentToAppend(component);
0163     llvm::sys::path::native(ComponentToAppend);
0164     llvm::sys::path::append(Result, Twine(ComponentToAppend));
0165     return Result;
0166   }
0167 };
0168 
0169 /// A RAII object that creates a link upon initialization and
0170 /// removes it upon destruction.
0171 ///
0172 /// The link may be a soft or a hard link, depending on the platform.
0173 class TempLink {
0174   SmallString<128> Path;
0175 
0176 public:
0177   /// Creates a managed link at path Link pointing to Target.
0178   TempLink(StringRef Target, StringRef Link) {
0179     Path = Link;
0180     std::error_code EC = sys::fs::create_link(Target, Link);
0181     if (EC)
0182       Path.clear();
0183     EXPECT_FALSE(EC);
0184   }
0185   ~TempLink() {
0186     if (!Path.empty()) {
0187       EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
0188     }
0189   }
0190 
0191   TempLink(const TempLink &) = delete;
0192   TempLink &operator=(const TempLink &) = delete;
0193 
0194   TempLink(TempLink &&) = default;
0195   TempLink &operator=(TempLink &&) = default;
0196 
0197   /// The path to the link.
0198   StringRef path() const { return Path; }
0199 };
0200 
0201 /// A RAII object that creates a file upon initialization and
0202 /// removes it upon destruction.
0203 class TempFile {
0204   SmallString<128> Path;
0205 
0206 public:
0207   /// Creates a managed file.
0208   ///
0209   /// @param Name The name of the file to create.
0210   /// @param Contents The string to write to the file.
0211   /// @param Unique If true, the file will be created using
0212   ///               llvm::sys::fs::createTemporaryFile.
0213   TempFile(StringRef Name, StringRef Suffix = "", StringRef Contents = "",
0214            bool Unique = false) {
0215     std::error_code EC;
0216     int fd;
0217     if (Unique) {
0218       EC = llvm::sys::fs::createTemporaryFile(Name, Suffix, fd, Path);
0219     } else {
0220       Path = Name;
0221       if (!Suffix.empty()) {
0222         Path.append(".");
0223         Path.append(Suffix);
0224       }
0225       EC = llvm::sys::fs::openFileForWrite(Path, fd);
0226     }
0227     EXPECT_FALSE(EC);
0228     raw_fd_ostream OS(fd, /*shouldClose*/ true);
0229     OS << Contents;
0230     OS.flush();
0231     EXPECT_FALSE(OS.error());
0232     if (EC || OS.error())
0233       Path.clear();
0234   }
0235   ~TempFile() {
0236     if (!Path.empty()) {
0237       EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
0238     }
0239   }
0240 
0241   TempFile(const TempFile &) = delete;
0242   TempFile &operator=(const TempFile &) = delete;
0243 
0244   TempFile(TempFile &&) = default;
0245   TempFile &operator=(TempFile &&) = default;
0246 
0247   /// The path to the file.
0248   StringRef path() const { return Path; }
0249 };
0250 
0251 } // namespace unittest
0252 } // namespace llvm
0253 
0254 #endif