123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- Testing/Support/SupportHelpers.h -----------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H
- #define LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H
- #include "llvm/ADT/SmallString.h"
- #include "llvm/Support/Error.h"
- #include "llvm/Support/FileSystem.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Support/raw_os_ostream.h"
- #include "gmock/gmock-matchers.h"
- #include "gtest/gtest-printers.h"
- #include <optional>
- #include <string>
- namespace llvm {
- namespace detail {
- struct ErrorHolder {
- std::vector<std::shared_ptr<ErrorInfoBase>> Infos;
- bool Success() const { return Infos.empty(); }
- };
- template <typename T> struct ExpectedHolder : public ErrorHolder {
- ExpectedHolder(ErrorHolder Err, Expected<T> &Exp)
- : ErrorHolder(std::move(Err)), Exp(Exp) {}
- Expected<T> &Exp;
- };
- inline void PrintTo(const ErrorHolder &Err, std::ostream *Out) {
- raw_os_ostream OS(*Out);
- OS << (Err.Success() ? "succeeded" : "failed");
- if (!Err.Success()) {
- const char *Delim = " (";
- for (const auto &Info : Err.Infos) {
- OS << Delim;
- Delim = "; ";
- Info->log(OS);
- }
- OS << ")";
- }
- }
- template <typename T>
- void PrintTo(const ExpectedHolder<T> &Item, std::ostream *Out) {
- if (Item.Success()) {
- *Out << "succeeded with value " << ::testing::PrintToString(*Item.Exp);
- } else {
- PrintTo(static_cast<const ErrorHolder &>(Item), Out);
- }
- }
- template <class InnerMatcher> class ValueIsMatcher {
- public:
- explicit ValueIsMatcher(InnerMatcher ValueMatcher)
- : ValueMatcher(ValueMatcher) {}
- template <class T>
- operator ::testing::Matcher<const std::optional<T> &>() const {
- return ::testing::MakeMatcher(
- new Impl<T>(::testing::SafeMatcherCast<T>(ValueMatcher)));
- }
- template <class T, class O = std::optional<T>>
- class Impl : public ::testing::MatcherInterface<const O &> {
- public:
- explicit Impl(const ::testing::Matcher<T> &ValueMatcher)
- : ValueMatcher(ValueMatcher) {}
- bool MatchAndExplain(const O &Input,
- testing::MatchResultListener *L) const override {
- return Input && ValueMatcher.MatchAndExplain(*Input, L);
- }
- void DescribeTo(std::ostream *OS) const override {
- *OS << "has a value that ";
- ValueMatcher.DescribeTo(OS);
- }
- void DescribeNegationTo(std::ostream *OS) const override {
- *OS << "does not have a value that ";
- ValueMatcher.DescribeTo(OS);
- }
- private:
- testing::Matcher<T> ValueMatcher;
- };
- private:
- InnerMatcher ValueMatcher;
- };
- } // namespace detail
- /// Matches an std::optional<T> with a value that conforms to an inner matcher.
- /// To match std::nullopt you could use Eq(std::nullopt).
- template <class InnerMatcher>
- detail::ValueIsMatcher<InnerMatcher> ValueIs(const InnerMatcher &ValueMatcher) {
- return detail::ValueIsMatcher<InnerMatcher>(ValueMatcher);
- }
- namespace unittest {
- SmallString<128> getInputFileDirectory(const char *Argv0);
- /// A RAII object that creates a temporary directory upon initialization and
- /// removes it upon destruction.
- class TempDir {
- SmallString<128> Path;
- public:
- /// Creates a managed temporary directory.
- ///
- /// @param Name The name of the directory to create.
- /// @param Unique If true, the directory will be created using
- /// llvm::sys::fs::createUniqueDirectory.
- explicit TempDir(StringRef Name, bool Unique = false) {
- std::error_code EC;
- if (Unique) {
- EC = llvm::sys::fs::createUniqueDirectory(Name, Path);
- if (!EC) {
- // Resolve any symlinks in the new directory.
- std::string UnresolvedPath(Path.str());
- EC = llvm::sys::fs::real_path(UnresolvedPath, Path);
- }
- } else {
- Path = Name;
- EC = llvm::sys::fs::create_directory(Path);
- }
- if (EC)
- Path.clear();
- EXPECT_FALSE(EC) << EC.message();
- }
- ~TempDir() {
- if (!Path.empty()) {
- EXPECT_FALSE(llvm::sys::fs::remove_directories(Path.str()));
- }
- }
- TempDir(const TempDir &) = delete;
- TempDir &operator=(const TempDir &) = delete;
- TempDir(TempDir &&) = default;
- TempDir &operator=(TempDir &&) = default;
- /// The path to the temporary directory.
- StringRef path() const { return Path; }
- /// The null-terminated C string pointing to the path.
- const char *c_str() { return Path.c_str(); }
- /// Creates a new path by appending the argument to the path of the managed
- /// directory using the native path separator.
- SmallString<128> path(StringRef component) const {
- SmallString<128> Result(Path);
- SmallString<128> ComponentToAppend(component);
- llvm::sys::path::native(ComponentToAppend);
- llvm::sys::path::append(Result, Twine(ComponentToAppend));
- return Result;
- }
- };
- /// A RAII object that creates a link upon initialization and
- /// removes it upon destruction.
- ///
- /// The link may be a soft or a hard link, depending on the platform.
- class TempLink {
- SmallString<128> Path;
- public:
- /// Creates a managed link at path Link pointing to Target.
- TempLink(StringRef Target, StringRef Link) {
- Path = Link;
- std::error_code EC = sys::fs::create_link(Target, Link);
- if (EC)
- Path.clear();
- EXPECT_FALSE(EC);
- }
- ~TempLink() {
- if (!Path.empty()) {
- EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
- }
- }
- TempLink(const TempLink &) = delete;
- TempLink &operator=(const TempLink &) = delete;
- TempLink(TempLink &&) = default;
- TempLink &operator=(TempLink &&) = default;
- /// The path to the link.
- StringRef path() const { return Path; }
- };
- /// A RAII object that creates a file upon initialization and
- /// removes it upon destruction.
- class TempFile {
- SmallString<128> Path;
- public:
- /// Creates a managed file.
- ///
- /// @param Name The name of the file to create.
- /// @param Contents The string to write to the file.
- /// @param Unique If true, the file will be created using
- /// llvm::sys::fs::createTemporaryFile.
- TempFile(StringRef Name, StringRef Suffix = "", StringRef Contents = "",
- bool Unique = false) {
- std::error_code EC;
- int fd;
- if (Unique) {
- EC = llvm::sys::fs::createTemporaryFile(Name, Suffix, fd, Path);
- } else {
- Path = Name;
- if (!Suffix.empty()) {
- Path.append(".");
- Path.append(Suffix);
- }
- EC = llvm::sys::fs::openFileForWrite(Path, fd);
- }
- EXPECT_FALSE(EC);
- raw_fd_ostream OS(fd, /*shouldClose*/ true);
- OS << Contents;
- OS.flush();
- EXPECT_FALSE(OS.error());
- if (EC || OS.error())
- Path.clear();
- }
- ~TempFile() {
- if (!Path.empty()) {
- EXPECT_FALSE(llvm::sys::fs::remove(Path.str()));
- }
- }
- TempFile(const TempFile &) = delete;
- TempFile &operator=(const TempFile &) = delete;
- TempFile(TempFile &&) = default;
- TempFile &operator=(TempFile &&) = default;
- /// The path to the file.
- StringRef path() const { return Path; }
- };
- } // namespace unittest
- } // namespace llvm
- #endif
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|