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_