gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/util/test_util.h (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Utilities for syscall testing.
    16  //
    17  // Initialization
    18  // ==============
    19  //
    20  // Prior to calling RUN_ALL_TESTS, all tests must use TestInit(&argc, &argv).
    21  // See the TestInit function for exact side-effects and semantics.
    22  //
    23  // Configuration
    24  // =============
    25  //
    26  // IsRunningOnGvisor returns true if the test is known to be running on gVisor.
    27  // GvisorPlatform can be used to get more detail:
    28  //
    29  //   if (GvisorPlatform() == Platform::kPtrace) {
    30  //       ...
    31  //   }
    32  //
    33  // SetupGvisorDeathTest ensures that signal handling does not interfere with
    34  /// tests that rely on fatal signals.
    35  //
    36  // Matchers
    37  // ========
    38  //
    39  // ElementOf(xs) matches if the matched value is equal to an element of the
    40  // container xs. Example:
    41  //
    42  //   // PASS
    43  //   EXPECT_THAT(1, ElementOf({0, 1, 2}));
    44  //
    45  //   // FAIL
    46  //   // Value of: 3
    47  //   // Expected: one of {0, 1, 2}
    48  //   //   Actual: 3
    49  //   EXPECT_THAT(3, ElementOf({0, 1, 2}));
    50  //
    51  // SyscallSucceeds() matches if the syscall is successful. A successful syscall
    52  // is defined by either a return value not equal to -1, or a return value of -1
    53  // with an errno of 0 (which is a possible successful return for e.g.
    54  // PTRACE_PEEK). Example:
    55  //
    56  //   // PASS
    57  //   EXPECT_THAT(open("/dev/null", O_RDONLY), SyscallSucceeds());
    58  //
    59  //   // FAIL
    60  //   // Value of: open("/", O_RDWR)
    61  //   // Expected: not -1 (success)
    62  //   //   Actual: -1 (of type int), with errno 21 (Is a directory)
    63  //   EXPECT_THAT(open("/", O_RDWR), SyscallSucceeds());
    64  //
    65  // SyscallSucceedsWithValue(m) matches if the syscall is successful, and the
    66  // value also matches m. Example:
    67  //
    68  //   // PASS
    69  //   EXPECT_THAT(read(4, buf, 8192), SyscallSucceedsWithValue(8192));
    70  //
    71  //   // FAIL
    72  //   // Value of: read(-1, buf, 8192)
    73  //   // Expected: is equal to 8192
    74  //   //   Actual: -1 (of type long), with errno 9 (Bad file number)
    75  //   EXPECT_THAT(read(-1, buf, 8192), SyscallSucceedsWithValue(8192));
    76  //
    77  //   // FAIL
    78  //   // Value of: read(4, buf, 1)
    79  //   // Expected: is > 4096
    80  //   //   Actual: 1 (of type long)
    81  //   EXPECT_THAT(read(4, buf, 1), SyscallSucceedsWithValue(Gt(4096)));
    82  //
    83  // SyscallFails() matches if the syscall is unsuccessful. An unsuccessful
    84  // syscall is defined by a return value of -1 with a non-zero errno. Example:
    85  //
    86  //   // PASS
    87  //   EXPECT_THAT(open("/", O_RDWR), SyscallFails());
    88  //
    89  //   // FAIL
    90  //   // Value of: open("/dev/null", O_RDONLY)
    91  //   // Expected: -1 (failure)
    92  //   //   Actual: 0 (of type int)
    93  //   EXPECT_THAT(open("/dev/null", O_RDONLY), SyscallFails());
    94  //
    95  // SyscallFailsWithErrno(m) matches if the syscall is unsuccessful, and errno
    96  // matches m. Example:
    97  //
    98  //   // PASS
    99  //   EXPECT_THAT(open("/", O_RDWR), SyscallFailsWithErrno(EISDIR));
   100  //
   101  //   // PASS
   102  //   EXPECT_THAT(open("/etc/passwd", O_RDWR | O_DIRECTORY),
   103  //               SyscallFailsWithErrno(AnyOf(EACCES, ENOTDIR)));
   104  //
   105  //   // FAIL
   106  //   // Value of: open("/dev/null", O_RDONLY)
   107  //   // Expected: -1 (failure) with errno 21 (Is a directory)
   108  //   //   Actual: 0 (of type int)
   109  //   EXPECT_THAT(open("/dev/null", O_RDONLY), SyscallFailsWithErrno(EISDIR));
   110  //
   111  //   // FAIL
   112  //   // Value of: open("/", O_RDWR)
   113  //   // Expected: -1 (failure) with errno 22 (Invalid argument)
   114  //   //   Actual: -1 (of type int), failure, but with errno 21 (Is a directory)
   115  //   EXPECT_THAT(open("/", O_RDWR), SyscallFailsWithErrno(EINVAL));
   116  //
   117  // Because the syscall matchers encode save/restore functionality, their meaning
   118  // should not be inverted via Not. That is, AnyOf(SyscallSucceedsWithValue(1),
   119  // SyscallSucceedsWithValue(2)) is permitted, but not
   120  // Not(SyscallFailsWithErrno(EPERM)).
   121  //
   122  // Syscalls
   123  // ========
   124  //
   125  // RetryEINTR wraps a function that returns -1 and sets errno on failure
   126  // to be automatically retried when EINTR occurs. Example:
   127  //
   128  //   auto rv = RetryEINTR(waitpid)(pid, &status, 0);
   129  //
   130  // ReadFd/WriteFd/PreadFd/PwriteFd are interface-compatible wrappers around the
   131  // read/write/pread/pwrite syscalls to handle both EINTR and partial
   132  // reads/writes. Example:
   133  //
   134  //   EXPECT_THAT(ReadFd(fd, &buf, size), SyscallSucceedsWithValue(size));
   135  //
   136  // General Utilities
   137  // =================
   138  //
   139  // ApplyVec(f, xs) returns a vector containing the result of applying function
   140  // `f` to each value in `xs`.
   141  //
   142  // AllBitwiseCombinations takes a variadic number of ranges containing integers
   143  // and returns a vector containing every integer that can be formed by ORing
   144  // together exactly one integer from each list. List<T> is an alias for
   145  // std::initializer_list<T> that makes AllBitwiseCombinations more ergonomic to
   146  // use with list literals (initializer lists do not otherwise participate in
   147  // template argument deduction). Example:
   148  //
   149  //     EXPECT_THAT(
   150  //         AllBitwiseCombinations<int>(
   151  //             List<int>{SOCK_DGRAM, SOCK_STREAM},
   152  //             List<int>{0, SOCK_NONBLOCK}),
   153  //         Contains({SOCK_DGRAM, SOCK_STREAM, SOCK_DGRAM | SOCK_NONBLOCK,
   154  //                   SOCK_STREAM | SOCK_NONBLOCK}));
   155  //
   156  // VecCat takes a variadic number of containers and returns a vector containing
   157  // the concatenated contents.
   158  //
   159  // VecAppend takes an initial container and a variadic number of containers and
   160  // appends each to the initial container.
   161  //
   162  // RandomizeBuffer will use MTRandom to fill the given buffer with random bytes.
   163  //
   164  // GenerateIovecs will return the smallest number of iovec arrays for writing a
   165  // given total number of bytes to a file, each iovec array size up to IOV_MAX,
   166  // each iovec in each array pointing to the same buffer.
   167  
   168  #ifndef GVISOR_TEST_UTIL_TEST_UTIL_H_
   169  #define GVISOR_TEST_UTIL_TEST_UTIL_H_
   170  
   171  #include <stddef.h>
   172  #include <stdlib.h>
   173  #include <sys/uio.h>
   174  #include <time.h>
   175  #include <unistd.h>
   176  
   177  #include <algorithm>
   178  #include <cerrno>
   179  #include <initializer_list>
   180  #include <iterator>
   181  #include <string>
   182  #include <thread>  // NOLINT: using std::thread::hardware_concurrency().
   183  #include <utility>
   184  #include <vector>
   185  
   186  #include "gmock/gmock.h"
   187  #include "absl/strings/str_cat.h"
   188  #include "absl/strings/str_format.h"
   189  #include "absl/strings/string_view.h"
   190  #include "absl/time/time.h"
   191  #include "test/util/fs_util.h"
   192  #include "test/util/logging.h"
   193  #include "test/util/posix_error.h"
   194  #include "test/util/save_util.h"
   195  
   196  // Android's libc, Bionic, specifies that many syscall arguments are _Nonnull,
   197  // causing tests that specifically test for syscall behavior on null arguments
   198  // to fail to build.
   199  #if defined(__BIONIC__) && defined(__clang__)
   200  #pragma clang diagnostic ignored "-Wnonnull"
   201  #endif
   202  
   203  namespace gvisor {
   204  namespace testing {
   205  
   206  constexpr char kTestOnGvisor[] = "TEST_ON_GVISOR";
   207  
   208  // TestInit must be called prior to RUN_ALL_TESTS.
   209  //
   210  // This parses all arguments and adjusts argc and argv appropriately.
   211  //
   212  // TestInit may create background threads.
   213  void TestInit(int* argc, char*** argv);
   214  
   215  // SKIP_IF may be used to skip a test case.
   216  //
   217  // These cases are still emitted, but a SKIPPED line will appear.
   218  #define SKIP_IF(expr)                \
   219    do {                               \
   220      if (expr) GTEST_SKIP() << #expr; \
   221    } while (0)
   222  
   223  // Platform contains platform names.
   224  namespace Platform {
   225  constexpr char kNative[] = "native";
   226  constexpr char kPtrace[] = "ptrace";
   227  constexpr char kKVM[] = "kvm";
   228  constexpr char kFuchsia[] = "fuchsia";
   229  constexpr char kStarnix[] = "starnix";
   230  constexpr char kSystrap[] = "systrap";
   231  }  // namespace Platform
   232  
   233  bool IsRunningOnGvisor();
   234  const std::string GvisorPlatform();
   235  bool IsRunningWithHostinet();
   236  bool IsIOUringEnabled();
   237  
   238  #ifdef __linux__
   239  void SetupGvisorDeathTest();
   240  #endif
   241  
   242  struct KernelVersion {
   243    int major;
   244    int minor;
   245    int micro;
   246  };
   247  
   248  bool operator==(const KernelVersion& first, const KernelVersion& second);
   249  
   250  PosixErrorOr<KernelVersion> ParseKernelVersion(absl::string_view vers_string);
   251  PosixErrorOr<KernelVersion> GetKernelVersion();
   252  
   253  static const size_t kPageSize = sysconf(_SC_PAGESIZE);
   254  
   255  enum class CPUVendor { kIntel, kAMD, kUnknownVendor };
   256  
   257  CPUVendor GetCPUVendor();
   258  
   259  inline int NumCPUs() { return std::thread::hardware_concurrency(); }
   260  
   261  // Converts cpu_set_t to a std::string for easy examination.
   262  std::string CPUSetToString(const cpu_set_t& set, size_t cpus = CPU_SETSIZE);
   263  
   264  struct OpenFd {
   265    // fd is the open file descriptor number.
   266    int fd = -1;
   267  
   268    // link is the resolution of the symbolic link.
   269    std::string link;
   270  };
   271  
   272  // Make it easier to log OpenFds to error streams.
   273  std::ostream& operator<<(std::ostream& out, std::vector<OpenFd> const& v);
   274  std::ostream& operator<<(std::ostream& out, OpenFd const& ofd);
   275  
   276  // Gets a detailed list of open fds for this process.
   277  PosixErrorOr<std::vector<OpenFd>> GetOpenFDs();
   278  
   279  // Returns the number of hard links to a path.
   280  PosixErrorOr<uint64_t> Links(const std::string& path);
   281  
   282  inline uint64_t ns_elapsed(const struct timespec& begin,
   283                             const struct timespec& end) {
   284    return (end.tv_sec - begin.tv_sec) * 1000000000 +
   285           (end.tv_nsec - begin.tv_nsec);
   286  }
   287  
   288  inline uint64_t ms_elapsed(const struct timespec& begin,
   289                             const struct timespec& end) {
   290    return ns_elapsed(begin, end) / 1000000;
   291  }
   292  
   293  namespace internal {
   294  
   295  template <typename Container>
   296  class ElementOfMatcher {
   297   public:
   298    explicit ElementOfMatcher(Container container)
   299        : container_(::std::move(container)) {}
   300  
   301    template <typename T>
   302    bool MatchAndExplain(T const& rv,
   303                         ::testing::MatchResultListener* const listener) const {
   304      using std::count;
   305      return count(container_.begin(), container_.end(), rv) != 0;
   306    }
   307  
   308    void DescribeTo(::std::ostream* const os) const {
   309      *os << "one of {";
   310      char const* sep = "";
   311      for (auto const& elem : container_) {
   312        *os << sep << elem;
   313        sep = ", ";
   314      }
   315      *os << "}";
   316    }
   317  
   318    void DescribeNegationTo(::std::ostream* const os) const {
   319      *os << "none of {";
   320      char const* sep = "";
   321      for (auto const& elem : container_) {
   322        *os << sep << elem;
   323        sep = ", ";
   324      }
   325      *os << "}";
   326    }
   327  
   328   private:
   329    Container const container_;
   330  };
   331  
   332  template <typename E>
   333  class SyscallSuccessMatcher {
   334   public:
   335    explicit SyscallSuccessMatcher(E expected)
   336        : expected_(::std::move(expected)) {}
   337  
   338    template <typename T>
   339    operator ::testing::Matcher<T>() const {
   340      // E is one of three things:
   341      // - T, or a type losslessly and implicitly convertible to T.
   342      // - A monomorphic Matcher<T>.
   343      // - A polymorphic matcher.
   344      // SafeMatcherCast handles any of the above correctly.
   345      //
   346      // Similarly, gMock will invoke this conversion operator to obtain a
   347      // monomorphic matcher (this is how polymorphic matchers are implemented).
   348      return ::testing::MakeMatcher(
   349          new Impl<T>(::testing::SafeMatcherCast<T>(expected_)));
   350    }
   351  
   352   private:
   353    template <typename T>
   354    class Impl : public ::testing::MatcherInterface<T> {
   355     public:
   356      explicit Impl(::testing::Matcher<T> matcher)
   357          : matcher_(::std::move(matcher)) {}
   358  
   359      bool MatchAndExplain(
   360          T const& rv,
   361          ::testing::MatchResultListener* const listener) const override {
   362        if (rv == static_cast<decltype(rv)>(-1) && errno != 0) {
   363          *listener << "with errno " << PosixError(errno);
   364          return false;
   365        }
   366        bool match = matcher_.MatchAndExplain(rv, listener);
   367        if (match) {
   368          MaybeSave();
   369        }
   370        return match;
   371      }
   372  
   373      void DescribeTo(::std::ostream* const os) const override {
   374        matcher_.DescribeTo(os);
   375      }
   376  
   377      void DescribeNegationTo(::std::ostream* const os) const override {
   378        matcher_.DescribeNegationTo(os);
   379      }
   380  
   381     private:
   382      ::testing::Matcher<T> matcher_;
   383    };
   384  
   385   private:
   386    E expected_;
   387  };
   388  
   389  // A polymorphic matcher equivalent to ::testing::internal::AnyMatcher, except
   390  // not in namespace ::testing::internal, and describing SyscallSucceeds()'s
   391  // match constraints (which are enforced by SyscallSuccessMatcher::Impl).
   392  class AnySuccessValueMatcher {
   393   public:
   394    template <typename T>
   395    operator ::testing::Matcher<T>() const {
   396      return ::testing::MakeMatcher(new Impl<T>());
   397    }
   398  
   399   private:
   400    template <typename T>
   401    class Impl : public ::testing::MatcherInterface<T> {
   402     public:
   403      bool MatchAndExplain(
   404          T const& rv,
   405          ::testing::MatchResultListener* const listener) const override {
   406        return true;
   407      }
   408  
   409      void DescribeTo(::std::ostream* const os) const override {
   410        *os << "not -1 (success)";
   411      }
   412  
   413      void DescribeNegationTo(::std::ostream* const os) const override {
   414        *os << "-1 (failure)";
   415      }
   416    };
   417  };
   418  
   419  class SyscallFailureMatcher {
   420   public:
   421    explicit SyscallFailureMatcher(::testing::Matcher<int> errno_matcher)
   422        : errno_matcher_(std::move(errno_matcher)) {}
   423  
   424    template <typename T>
   425    bool MatchAndExplain(T const& rv,
   426                         ::testing::MatchResultListener* const listener) const {
   427      if (rv != static_cast<decltype(rv)>(-1)) {
   428        return false;
   429      }
   430      int actual_errno = errno;
   431      *listener << "with errno " << PosixError(actual_errno);
   432      bool match = errno_matcher_.MatchAndExplain(actual_errno, listener);
   433      if (match) {
   434        MaybeSave();
   435      }
   436      return match;
   437    }
   438  
   439    void DescribeTo(::std::ostream* const os) const {
   440      *os << "-1 (failure), with errno ";
   441      errno_matcher_.DescribeTo(os);
   442    }
   443  
   444    void DescribeNegationTo(::std::ostream* const os) const {
   445      *os << "not -1 (success), with errno ";
   446      errno_matcher_.DescribeNegationTo(os);
   447    }
   448  
   449   private:
   450    ::testing::Matcher<int> errno_matcher_;
   451  };
   452  
   453  class SpecificErrnoMatcher : public ::testing::MatcherInterface<int> {
   454   public:
   455    explicit SpecificErrnoMatcher(int const expected) : expected_(expected) {}
   456  
   457    bool MatchAndExplain(
   458        int const actual_errno,
   459        ::testing::MatchResultListener* const listener) const override {
   460      return actual_errno == expected_;
   461    }
   462  
   463    void DescribeTo(::std::ostream* const os) const override {
   464      *os << PosixError(expected_);
   465    }
   466  
   467    void DescribeNegationTo(::std::ostream* const os) const override {
   468      *os << "not " << PosixError(expected_);
   469    }
   470  
   471   private:
   472    int const expected_;
   473  };
   474  
   475  inline ::testing::Matcher<int> SpecificErrno(int const expected) {
   476    return ::testing::MakeMatcher(new SpecificErrnoMatcher(expected));
   477  }
   478  
   479  }  // namespace internal
   480  
   481  template <typename Container>
   482  inline ::testing::PolymorphicMatcher<internal::ElementOfMatcher<Container>>
   483  ElementOf(Container container) {
   484    return ::testing::MakePolymorphicMatcher(
   485        internal::ElementOfMatcher<Container>(::std::move(container)));
   486  }
   487  
   488  template <typename T>
   489  inline ::testing::PolymorphicMatcher<
   490      internal::ElementOfMatcher<::std::vector<T>>>
   491  ElementOf(::std::initializer_list<T> elems) {
   492    return ::testing::MakePolymorphicMatcher(
   493        internal::ElementOfMatcher<::std::vector<T>>(::std::vector<T>(elems)));
   494  }
   495  
   496  template <typename E>
   497  inline internal::SyscallSuccessMatcher<E> SyscallSucceedsWithValue(E expected) {
   498    return internal::SyscallSuccessMatcher<E>(::std::move(expected));
   499  }
   500  
   501  inline internal::SyscallSuccessMatcher<internal::AnySuccessValueMatcher>
   502  SyscallSucceeds() {
   503    return SyscallSucceedsWithValue(
   504        ::gvisor::testing::internal::AnySuccessValueMatcher());
   505  }
   506  
   507  inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher>
   508  SyscallFailsWithErrno(::testing::Matcher<int> expected) {
   509    return ::testing::MakePolymorphicMatcher(
   510        internal::SyscallFailureMatcher(::std::move(expected)));
   511  }
   512  
   513  // Overload taking an int so that SyscallFailsWithErrno(<specific errno>) uses
   514  // internal::SpecificErrno (which stringifies the errno) rather than
   515  // ::testing::Eq (which doesn't).
   516  inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher>
   517  SyscallFailsWithErrno(int const expected) {
   518    return SyscallFailsWithErrno(internal::SpecificErrno(expected));
   519  }
   520  
   521  inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher>
   522  SyscallFails() {
   523    return SyscallFailsWithErrno(::testing::Gt(0));
   524  }
   525  
   526  // As of GCC 7.2, -Wall => -Wc++17-compat => -Wnoexcept-type generates an
   527  // irrelevant, non-actionable warning about ABI compatibility when
   528  // RetryEINTRImpl is constructed with a noexcept function, such as glibc's
   529  // syscall(). See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80985.
   530  #if defined(__GNUC__) && !defined(__clang__) && \
   531      (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2))
   532  #pragma GCC diagnostic push
   533  #pragma GCC diagnostic ignored "-Wnoexcept-type"
   534  #endif
   535  
   536  namespace internal {
   537  
   538  template <typename F>
   539  struct RetryEINTRImpl {
   540    F const f;
   541  
   542    explicit constexpr RetryEINTRImpl(F f) : f(std::move(f)) {}
   543  
   544    template <typename... Args>
   545    auto operator()(Args&&... args) const
   546        -> decltype(f(std::forward<Args>(args)...)) {
   547      while (true) {
   548        errno = 0;
   549        auto const ret = f(std::forward<Args>(args)...);
   550        if (ret != -1 || errno != EINTR) {
   551          return ret;
   552        }
   553      }
   554    }
   555  };
   556  
   557  }  // namespace internal
   558  
   559  template <typename F>
   560  constexpr internal::RetryEINTRImpl<F> RetryEINTR(F&& f) {
   561    return internal::RetryEINTRImpl<F>(std::forward<F>(f));
   562  }
   563  
   564  #if defined(__GNUC__) && !defined(__clang__) && \
   565      (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2))
   566  #pragma GCC diagnostic pop
   567  #endif
   568  
   569  namespace internal {
   570  
   571  template <typename F>
   572  ssize_t ApplyFileIoSyscall(F const& f, size_t const count) {
   573    size_t completed = 0;
   574    // `do ... while` because some callers actually want to make a syscall with a
   575    // count of 0.
   576    do {
   577      auto const cur = RetryEINTR(f)(completed);
   578      if (cur < 0) {
   579        return cur;
   580      } else if (cur == 0) {
   581        break;
   582      }
   583      completed += cur;
   584    } while (completed < count);
   585    return completed;
   586  }
   587  
   588  }  // namespace internal
   589  
   590  inline PosixErrorOr<std::string> ReadAllFd(int fd) {
   591    std::string all;
   592    all.reserve(128 * 1024);  // arbitrary.
   593  
   594    std::vector<char> buffer(16 * 1024);
   595    for (;;) {
   596      auto const bytes = RetryEINTR(read)(fd, buffer.data(), buffer.size());
   597      if (bytes < 0) {
   598        return PosixError(errno, "file read");
   599      }
   600      if (bytes == 0) {
   601        return std::move(all);
   602      }
   603      if (bytes > 0) {
   604        all.append(buffer.data(), bytes);
   605      }
   606    }
   607  }
   608  
   609  inline ssize_t ReadFd(int fd, void* buf, size_t count) {
   610    return internal::ApplyFileIoSyscall(
   611        [&](size_t completed) {
   612          return read(fd, static_cast<char*>(buf) + completed, count - completed);
   613        },
   614        count);
   615  }
   616  
   617  inline ssize_t WriteFd(int fd, void const* buf, size_t count) {
   618    return internal::ApplyFileIoSyscall(
   619        [&](size_t completed) {
   620          return write(fd, static_cast<char const*>(buf) + completed,
   621                       count - completed);
   622        },
   623        count);
   624  }
   625  
   626  inline ssize_t PreadFd(int fd, void* buf, size_t count, off_t offset) {
   627    return internal::ApplyFileIoSyscall(
   628        [&](size_t completed) {
   629          return pread(fd, static_cast<char*>(buf) + completed, count - completed,
   630                       offset + completed);
   631        },
   632        count);
   633  }
   634  
   635  inline ssize_t PwriteFd(int fd, void const* buf, size_t count, off_t offset) {
   636    return internal::ApplyFileIoSyscall(
   637        [&](size_t completed) {
   638          return pwrite(fd, static_cast<char const*>(buf) + completed,
   639                        count - completed, offset + completed);
   640        },
   641        count);
   642  }
   643  
   644  template <typename T>
   645  using List = std::initializer_list<T>;
   646  
   647  namespace internal {
   648  
   649  template <typename T>
   650  void AppendAllBitwiseCombinations(std::vector<T>* combinations, T current) {
   651    combinations->push_back(current);
   652  }
   653  
   654  template <typename T, typename Arg, typename... Args>
   655  void AppendAllBitwiseCombinations(std::vector<T>* combinations, T current,
   656                                    Arg&& next, Args&&... rest) {
   657    for (auto const option : next) {
   658      AppendAllBitwiseCombinations(combinations, current | option, rest...);
   659    }
   660  }
   661  
   662  inline size_t CombinedSize(size_t accum) { return accum; }
   663  
   664  template <typename T, typename... Args>
   665  size_t CombinedSize(size_t accum, T const& x, Args&&... xs) {
   666    return CombinedSize(accum + x.size(), std::forward<Args>(xs)...);
   667  }
   668  
   669  // Base case: no more containers, so do nothing.
   670  template <typename T>
   671  void DoMoveExtendContainer(T* c) {}
   672  
   673  // Append each container next to c.
   674  template <typename T, typename U, typename... Args>
   675  void DoMoveExtendContainer(T* c, U&& next, Args&&... rest) {
   676    std::move(std::begin(next), std::end(next), std::back_inserter(*c));
   677    DoMoveExtendContainer(c, std::forward<Args>(rest)...);
   678  }
   679  
   680  }  // namespace internal
   681  
   682  template <typename T = int>
   683  std::vector<T> AllBitwiseCombinations() {
   684    return std::vector<T>();
   685  }
   686  
   687  template <typename T = int, typename... Args>
   688  std::vector<T> AllBitwiseCombinations(Args&&... args) {
   689    std::vector<T> combinations;
   690    internal::AppendAllBitwiseCombinations(&combinations, 0, args...);
   691    return combinations;
   692  }
   693  
   694  template <typename T, typename U, typename F>
   695  std::vector<T> ApplyVec(F const& f, std::vector<U> const& us) {
   696    std::vector<T> vec;
   697    vec.reserve(us.size());
   698    for (auto const& u : us) {
   699      vec.push_back(f(u));
   700    }
   701    return vec;
   702  }
   703  
   704  template <typename T, typename U>
   705  std::vector<T> ApplyVecToVec(std::vector<std::function<T(U)>> const& fs,
   706                               std::vector<U> const& us) {
   707    std::vector<T> vec;
   708    vec.reserve(us.size() * fs.size());
   709    for (auto const& f : fs) {
   710      for (auto const& u : us) {
   711        vec.push_back(f(u));
   712      }
   713    }
   714    return vec;
   715  }
   716  
   717  // Moves all elements from the containers `args` to the end of `c`.
   718  template <typename T, typename... Args>
   719  void VecAppend(T* c, Args&&... args) {
   720    c->reserve(internal::CombinedSize(c->size(), args...));
   721    internal::DoMoveExtendContainer(c, std::forward<Args>(args)...);
   722  }
   723  
   724  // Returns a vector containing the concatenated contents of the containers
   725  // `args`.
   726  template <typename T, typename... Args>
   727  std::vector<T> VecCat(Args&&... args) {
   728    std::vector<T> combined;
   729    VecAppend(&combined, std::forward<Args>(args)...);
   730    return combined;
   731  }
   732  
   733  #define RETURN_ERROR_IF_SYSCALL_FAIL(syscall) \
   734    do {                                        \
   735      if ((syscall) < 0 && errno != 0) {        \
   736        return PosixError(errno, #syscall);     \
   737      }                                         \
   738    } while (false)
   739  
   740  // Fill the given buffer with random bytes.
   741  void RandomizeBuffer(char* buffer, size_t len);
   742  
   743  template <typename T>
   744  inline PosixErrorOr<T> Atoi(absl::string_view str) {
   745    T ret;
   746    if (!absl::SimpleAtoi<T>(str, &ret)) {
   747      return PosixError(EINVAL, "String not a number.");
   748    }
   749    return ret;
   750  }
   751  
   752  inline PosixErrorOr<uint64_t> AtoiBase(absl::string_view str, int base) {
   753    if (base > 255 || base < 2) {
   754      return PosixError(EINVAL, "Invalid Base");
   755    }
   756  
   757    uint64_t ret = 0;
   758    if (!absl::numbers_internal::safe_strtou64_base(str, &ret, base)) {
   759      return PosixError(EINVAL, "String not a number.");
   760    }
   761  
   762    return ret;
   763  }
   764  
   765  inline PosixErrorOr<double> Atod(absl::string_view str) {
   766    double ret;
   767    if (!absl::SimpleAtod(str, &ret)) {
   768      return PosixError(EINVAL, "String not a double type.");
   769    }
   770    return ret;
   771  }
   772  
   773  inline PosixErrorOr<float> Atof(absl::string_view str) {
   774    float ret;
   775    if (!absl::SimpleAtof(str, &ret)) {
   776      return PosixError(EINVAL, "String not a float type.");
   777    }
   778    return ret;
   779  }
   780  
   781  // Return the smallest number of iovec arrays that can be used to write
   782  // "total_bytes" number of bytes, each iovec writing one "buf".
   783  std::vector<std::vector<struct iovec>> GenerateIovecs(uint64_t total_size,
   784                                                        void* buf, size_t buflen);
   785  
   786  // Returns bytes in 'n' megabytes. Used for readability.
   787  uint64_t Megabytes(uint64_t n);
   788  
   789  // Predicate for checking that a value is within some tolerance of another
   790  // value. Returns true iff current is in the range [target * (1 - tolerance),
   791  // target * (1 + tolerance)].
   792  bool Equivalent(uint64_t current, uint64_t target, double tolerance);
   793  
   794  // Matcher wrapping the Equivalent predicate.
   795  MATCHER_P2(EquivalentWithin, target, tolerance,
   796             std::string(negation ? "Isn't" : "Is") +
   797                 ::absl::StrFormat(" within %.2f%% of the target of %zd bytes",
   798                                   tolerance * 100, target)) {
   799    if (target == 0) {
   800      *result_listener << ::absl::StreamFormat("difference of infinity%%");
   801    } else {
   802      int64_t delta = static_cast<int64_t>(arg) - static_cast<int64_t>(target);
   803      double delta_percent =
   804          static_cast<double>(delta) / static_cast<double>(target) * 100;
   805      *result_listener << ::absl::StreamFormat("difference of %.2f%%",
   806                                               delta_percent);
   807    }
   808    return Equivalent(arg, target, tolerance);
   809  }
   810  
   811  // Returns the absolute path to the a data dependency. 'path' is the runfile
   812  // location relative to workspace root.
   813  #ifdef __linux__
   814  std::string RunfilePath(std::string path);
   815  #endif
   816  
   817  void TestInit(int* argc, char*** argv);
   818  int RunAllTests(void);
   819  
   820  }  // namespace testing
   821  }  // namespace gvisor
   822  
   823  #endif  // GVISOR_TEST_UTIL_TEST_UTIL_H_