github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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 namespace gvisor { 197 namespace testing { 198 199 constexpr char kTestOnGvisor[] = "TEST_ON_GVISOR"; 200 201 // TestInit must be called prior to RUN_ALL_TESTS. 202 // 203 // This parses all arguments and adjusts argc and argv appropriately. 204 // 205 // TestInit may create background threads. 206 void TestInit(int* argc, char*** argv); 207 208 // SKIP_IF may be used to skip a test case. 209 // 210 // These cases are still emitted, but a SKIPPED line will appear. 211 #define SKIP_IF(expr) \ 212 do { \ 213 if (expr) GTEST_SKIP() << #expr; \ 214 } while (0) 215 216 // Platform contains platform names. 217 namespace Platform { 218 constexpr char kNative[] = "native"; 219 constexpr char kPtrace[] = "ptrace"; 220 constexpr char kKVM[] = "kvm"; 221 constexpr char kFuchsia[] = "fuchsia"; 222 } // namespace Platform 223 224 bool IsRunningOnGvisor(); 225 const std::string GvisorPlatform(); 226 bool IsRunningWithHostinet(); 227 // TODO(gvisor.dev/issue/1624): Delete once VFS1 is gone. 228 bool IsRunningWithVFS1(); 229 bool IsFUSEEnabled(); 230 231 #ifdef __linux__ 232 void SetupGvisorDeathTest(); 233 #endif 234 235 struct KernelVersion { 236 int major; 237 int minor; 238 int micro; 239 }; 240 241 bool operator==(const KernelVersion& first, const KernelVersion& second); 242 243 PosixErrorOr<KernelVersion> ParseKernelVersion(absl::string_view vers_string); 244 PosixErrorOr<KernelVersion> GetKernelVersion(); 245 246 static const size_t kPageSize = sysconf(_SC_PAGESIZE); 247 248 enum class CPUVendor { kIntel, kAMD, kUnknownVendor }; 249 250 CPUVendor GetCPUVendor(); 251 252 inline int NumCPUs() { return std::thread::hardware_concurrency(); } 253 254 // Converts cpu_set_t to a std::string for easy examination. 255 std::string CPUSetToString(const cpu_set_t& set, size_t cpus = CPU_SETSIZE); 256 257 struct OpenFd { 258 // fd is the open file descriptor number. 259 int fd = -1; 260 261 // link is the resolution of the symbolic link. 262 std::string link; 263 }; 264 265 // Make it easier to log OpenFds to error streams. 266 std::ostream& operator<<(std::ostream& out, std::vector<OpenFd> const& v); 267 std::ostream& operator<<(std::ostream& out, OpenFd const& ofd); 268 269 // Gets a detailed list of open fds for this process. 270 PosixErrorOr<std::vector<OpenFd>> GetOpenFDs(); 271 272 // Returns the number of hard links to a path. 273 PosixErrorOr<uint64_t> Links(const std::string& path); 274 275 inline uint64_t ns_elapsed(const struct timespec& begin, 276 const struct timespec& end) { 277 return (end.tv_sec - begin.tv_sec) * 1000000000 + 278 (end.tv_nsec - begin.tv_nsec); 279 } 280 281 inline uint64_t ms_elapsed(const struct timespec& begin, 282 const struct timespec& end) { 283 return ns_elapsed(begin, end) / 1000000; 284 } 285 286 namespace internal { 287 288 template <typename Container> 289 class ElementOfMatcher { 290 public: 291 explicit ElementOfMatcher(Container container) 292 : container_(::std::move(container)) {} 293 294 template <typename T> 295 bool MatchAndExplain(T const& rv, 296 ::testing::MatchResultListener* const listener) const { 297 using std::count; 298 return count(container_.begin(), container_.end(), rv) != 0; 299 } 300 301 void DescribeTo(::std::ostream* const os) const { 302 *os << "one of {"; 303 char const* sep = ""; 304 for (auto const& elem : container_) { 305 *os << sep << elem; 306 sep = ", "; 307 } 308 *os << "}"; 309 } 310 311 void DescribeNegationTo(::std::ostream* const os) const { 312 *os << "none of {"; 313 char const* sep = ""; 314 for (auto const& elem : container_) { 315 *os << sep << elem; 316 sep = ", "; 317 } 318 *os << "}"; 319 } 320 321 private: 322 Container const container_; 323 }; 324 325 template <typename E> 326 class SyscallSuccessMatcher { 327 public: 328 explicit SyscallSuccessMatcher(E expected) 329 : expected_(::std::move(expected)) {} 330 331 template <typename T> 332 operator ::testing::Matcher<T>() const { 333 // E is one of three things: 334 // - T, or a type losslessly and implicitly convertible to T. 335 // - A monomorphic Matcher<T>. 336 // - A polymorphic matcher. 337 // SafeMatcherCast handles any of the above correctly. 338 // 339 // Similarly, gMock will invoke this conversion operator to obtain a 340 // monomorphic matcher (this is how polymorphic matchers are implemented). 341 return ::testing::MakeMatcher( 342 new Impl<T>(::testing::SafeMatcherCast<T>(expected_))); 343 } 344 345 private: 346 template <typename T> 347 class Impl : public ::testing::MatcherInterface<T> { 348 public: 349 explicit Impl(::testing::Matcher<T> matcher) 350 : matcher_(::std::move(matcher)) {} 351 352 bool MatchAndExplain( 353 T const& rv, 354 ::testing::MatchResultListener* const listener) const override { 355 if (rv == static_cast<decltype(rv)>(-1) && errno != 0) { 356 *listener << "with errno " << PosixError(errno); 357 return false; 358 } 359 bool match = matcher_.MatchAndExplain(rv, listener); 360 if (match) { 361 MaybeSave(); 362 } 363 return match; 364 } 365 366 void DescribeTo(::std::ostream* const os) const override { 367 matcher_.DescribeTo(os); 368 } 369 370 void DescribeNegationTo(::std::ostream* const os) const override { 371 matcher_.DescribeNegationTo(os); 372 } 373 374 private: 375 ::testing::Matcher<T> matcher_; 376 }; 377 378 private: 379 E expected_; 380 }; 381 382 // A polymorphic matcher equivalent to ::testing::internal::AnyMatcher, except 383 // not in namespace ::testing::internal, and describing SyscallSucceeds()'s 384 // match constraints (which are enforced by SyscallSuccessMatcher::Impl). 385 class AnySuccessValueMatcher { 386 public: 387 template <typename T> 388 operator ::testing::Matcher<T>() const { 389 return ::testing::MakeMatcher(new Impl<T>()); 390 } 391 392 private: 393 template <typename T> 394 class Impl : public ::testing::MatcherInterface<T> { 395 public: 396 bool MatchAndExplain( 397 T const& rv, 398 ::testing::MatchResultListener* const listener) const override { 399 return true; 400 } 401 402 void DescribeTo(::std::ostream* const os) const override { 403 *os << "not -1 (success)"; 404 } 405 406 void DescribeNegationTo(::std::ostream* const os) const override { 407 *os << "-1 (failure)"; 408 } 409 }; 410 }; 411 412 class SyscallFailureMatcher { 413 public: 414 explicit SyscallFailureMatcher(::testing::Matcher<int> errno_matcher) 415 : errno_matcher_(std::move(errno_matcher)) {} 416 417 template <typename T> 418 bool MatchAndExplain(T const& rv, 419 ::testing::MatchResultListener* const listener) const { 420 if (rv != static_cast<decltype(rv)>(-1)) { 421 return false; 422 } 423 int actual_errno = errno; 424 *listener << "with errno " << PosixError(actual_errno); 425 bool match = errno_matcher_.MatchAndExplain(actual_errno, listener); 426 if (match) { 427 MaybeSave(); 428 } 429 return match; 430 } 431 432 void DescribeTo(::std::ostream* const os) const { 433 *os << "-1 (failure), with errno "; 434 errno_matcher_.DescribeTo(os); 435 } 436 437 void DescribeNegationTo(::std::ostream* const os) const { 438 *os << "not -1 (success), with errno "; 439 errno_matcher_.DescribeNegationTo(os); 440 } 441 442 private: 443 ::testing::Matcher<int> errno_matcher_; 444 }; 445 446 class SpecificErrnoMatcher : public ::testing::MatcherInterface<int> { 447 public: 448 explicit SpecificErrnoMatcher(int const expected) : expected_(expected) {} 449 450 bool MatchAndExplain( 451 int const actual_errno, 452 ::testing::MatchResultListener* const listener) const override { 453 return actual_errno == expected_; 454 } 455 456 void DescribeTo(::std::ostream* const os) const override { 457 *os << PosixError(expected_); 458 } 459 460 void DescribeNegationTo(::std::ostream* const os) const override { 461 *os << "not " << PosixError(expected_); 462 } 463 464 private: 465 int const expected_; 466 }; 467 468 inline ::testing::Matcher<int> SpecificErrno(int const expected) { 469 return ::testing::MakeMatcher(new SpecificErrnoMatcher(expected)); 470 } 471 472 } // namespace internal 473 474 template <typename Container> 475 inline ::testing::PolymorphicMatcher<internal::ElementOfMatcher<Container>> 476 ElementOf(Container container) { 477 return ::testing::MakePolymorphicMatcher( 478 internal::ElementOfMatcher<Container>(::std::move(container))); 479 } 480 481 template <typename T> 482 inline ::testing::PolymorphicMatcher< 483 internal::ElementOfMatcher<::std::vector<T>>> 484 ElementOf(::std::initializer_list<T> elems) { 485 return ::testing::MakePolymorphicMatcher( 486 internal::ElementOfMatcher<::std::vector<T>>(::std::vector<T>(elems))); 487 } 488 489 template <typename E> 490 inline internal::SyscallSuccessMatcher<E> SyscallSucceedsWithValue(E expected) { 491 return internal::SyscallSuccessMatcher<E>(::std::move(expected)); 492 } 493 494 inline internal::SyscallSuccessMatcher<internal::AnySuccessValueMatcher> 495 SyscallSucceeds() { 496 return SyscallSucceedsWithValue( 497 ::gvisor::testing::internal::AnySuccessValueMatcher()); 498 } 499 500 inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher> 501 SyscallFailsWithErrno(::testing::Matcher<int> expected) { 502 return ::testing::MakePolymorphicMatcher( 503 internal::SyscallFailureMatcher(::std::move(expected))); 504 } 505 506 // Overload taking an int so that SyscallFailsWithErrno(<specific errno>) uses 507 // internal::SpecificErrno (which stringifies the errno) rather than 508 // ::testing::Eq (which doesn't). 509 inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher> 510 SyscallFailsWithErrno(int const expected) { 511 return SyscallFailsWithErrno(internal::SpecificErrno(expected)); 512 } 513 514 inline ::testing::PolymorphicMatcher<internal::SyscallFailureMatcher> 515 SyscallFails() { 516 return SyscallFailsWithErrno(::testing::Gt(0)); 517 } 518 519 // As of GCC 7.2, -Wall => -Wc++17-compat => -Wnoexcept-type generates an 520 // irrelevant, non-actionable warning about ABI compatibility when 521 // RetryEINTRImpl is constructed with a noexcept function, such as glibc's 522 // syscall(). See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80985. 523 #if defined(__GNUC__) && !defined(__clang__) && \ 524 (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)) 525 #pragma GCC diagnostic push 526 #pragma GCC diagnostic ignored "-Wnoexcept-type" 527 #endif 528 529 namespace internal { 530 531 template <typename F> 532 struct RetryEINTRImpl { 533 F const f; 534 535 explicit constexpr RetryEINTRImpl(F f) : f(std::move(f)) {} 536 537 template <typename... Args> 538 auto operator()(Args&&... args) const 539 -> decltype(f(std::forward<Args>(args)...)) { 540 while (true) { 541 errno = 0; 542 auto const ret = f(std::forward<Args>(args)...); 543 if (ret != -1 || errno != EINTR) { 544 return ret; 545 } 546 } 547 } 548 }; 549 550 } // namespace internal 551 552 template <typename F> 553 constexpr internal::RetryEINTRImpl<F> RetryEINTR(F&& f) { 554 return internal::RetryEINTRImpl<F>(std::forward<F>(f)); 555 } 556 557 #if defined(__GNUC__) && !defined(__clang__) && \ 558 (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)) 559 #pragma GCC diagnostic pop 560 #endif 561 562 namespace internal { 563 564 template <typename F> 565 ssize_t ApplyFileIoSyscall(F const& f, size_t const count) { 566 size_t completed = 0; 567 // `do ... while` because some callers actually want to make a syscall with a 568 // count of 0. 569 do { 570 auto const cur = RetryEINTR(f)(completed); 571 if (cur < 0) { 572 return cur; 573 } else if (cur == 0) { 574 break; 575 } 576 completed += cur; 577 } while (completed < count); 578 return completed; 579 } 580 581 } // namespace internal 582 583 inline PosixErrorOr<std::string> ReadAllFd(int fd) { 584 std::string all; 585 all.reserve(128 * 1024); // arbitrary. 586 587 std::vector<char> buffer(16 * 1024); 588 for (;;) { 589 auto const bytes = RetryEINTR(read)(fd, buffer.data(), buffer.size()); 590 if (bytes < 0) { 591 return PosixError(errno, "file read"); 592 } 593 if (bytes == 0) { 594 return std::move(all); 595 } 596 if (bytes > 0) { 597 all.append(buffer.data(), bytes); 598 } 599 } 600 } 601 602 inline ssize_t ReadFd(int fd, void* buf, size_t count) { 603 return internal::ApplyFileIoSyscall( 604 [&](size_t completed) { 605 return read(fd, static_cast<char*>(buf) + completed, count - completed); 606 }, 607 count); 608 } 609 610 inline ssize_t WriteFd(int fd, void const* buf, size_t count) { 611 return internal::ApplyFileIoSyscall( 612 [&](size_t completed) { 613 return write(fd, static_cast<char const*>(buf) + completed, 614 count - completed); 615 }, 616 count); 617 } 618 619 inline ssize_t PreadFd(int fd, void* buf, size_t count, off_t offset) { 620 return internal::ApplyFileIoSyscall( 621 [&](size_t completed) { 622 return pread(fd, static_cast<char*>(buf) + completed, count - completed, 623 offset + completed); 624 }, 625 count); 626 } 627 628 inline ssize_t PwriteFd(int fd, void const* buf, size_t count, off_t offset) { 629 return internal::ApplyFileIoSyscall( 630 [&](size_t completed) { 631 return pwrite(fd, static_cast<char const*>(buf) + completed, 632 count - completed, offset + completed); 633 }, 634 count); 635 } 636 637 template <typename T> 638 using List = std::initializer_list<T>; 639 640 namespace internal { 641 642 template <typename T> 643 void AppendAllBitwiseCombinations(std::vector<T>* combinations, T current) { 644 combinations->push_back(current); 645 } 646 647 template <typename T, typename Arg, typename... Args> 648 void AppendAllBitwiseCombinations(std::vector<T>* combinations, T current, 649 Arg&& next, Args&&... rest) { 650 for (auto const option : next) { 651 AppendAllBitwiseCombinations(combinations, current | option, rest...); 652 } 653 } 654 655 inline size_t CombinedSize(size_t accum) { return accum; } 656 657 template <typename T, typename... Args> 658 size_t CombinedSize(size_t accum, T const& x, Args&&... xs) { 659 return CombinedSize(accum + x.size(), std::forward<Args>(xs)...); 660 } 661 662 // Base case: no more containers, so do nothing. 663 template <typename T> 664 void DoMoveExtendContainer(T* c) {} 665 666 // Append each container next to c. 667 template <typename T, typename U, typename... Args> 668 void DoMoveExtendContainer(T* c, U&& next, Args&&... rest) { 669 std::move(std::begin(next), std::end(next), std::back_inserter(*c)); 670 DoMoveExtendContainer(c, std::forward<Args>(rest)...); 671 } 672 673 } // namespace internal 674 675 template <typename T = int> 676 std::vector<T> AllBitwiseCombinations() { 677 return std::vector<T>(); 678 } 679 680 template <typename T = int, typename... Args> 681 std::vector<T> AllBitwiseCombinations(Args&&... args) { 682 std::vector<T> combinations; 683 internal::AppendAllBitwiseCombinations(&combinations, 0, args...); 684 return combinations; 685 } 686 687 template <typename T, typename U, typename F> 688 std::vector<T> ApplyVec(F const& f, std::vector<U> const& us) { 689 std::vector<T> vec; 690 vec.reserve(us.size()); 691 for (auto const& u : us) { 692 vec.push_back(f(u)); 693 } 694 return vec; 695 } 696 697 template <typename T, typename U> 698 std::vector<T> ApplyVecToVec(std::vector<std::function<T(U)>> const& fs, 699 std::vector<U> const& us) { 700 std::vector<T> vec; 701 vec.reserve(us.size() * fs.size()); 702 for (auto const& f : fs) { 703 for (auto const& u : us) { 704 vec.push_back(f(u)); 705 } 706 } 707 return vec; 708 } 709 710 // Moves all elements from the containers `args` to the end of `c`. 711 template <typename T, typename... Args> 712 void VecAppend(T* c, Args&&... args) { 713 c->reserve(internal::CombinedSize(c->size(), args...)); 714 internal::DoMoveExtendContainer(c, std::forward<Args>(args)...); 715 } 716 717 // Returns a vector containing the concatenated contents of the containers 718 // `args`. 719 template <typename T, typename... Args> 720 std::vector<T> VecCat(Args&&... args) { 721 std::vector<T> combined; 722 VecAppend(&combined, std::forward<Args>(args)...); 723 return combined; 724 } 725 726 #define RETURN_ERROR_IF_SYSCALL_FAIL(syscall) \ 727 do { \ 728 if ((syscall) < 0 && errno != 0) { \ 729 return PosixError(errno, #syscall); \ 730 } \ 731 } while (false) 732 733 // Fill the given buffer with random bytes. 734 void RandomizeBuffer(void* buffer, size_t len); 735 736 template <typename T> 737 inline PosixErrorOr<T> Atoi(absl::string_view str) { 738 T ret; 739 if (!absl::SimpleAtoi<T>(str, &ret)) { 740 return PosixError(EINVAL, "String not a number."); 741 } 742 return ret; 743 } 744 745 inline PosixErrorOr<uint64_t> AtoiBase(absl::string_view str, int base) { 746 if (base > 255 || base < 2) { 747 return PosixError(EINVAL, "Invalid Base"); 748 } 749 750 uint64_t ret = 0; 751 if (!absl::numbers_internal::safe_strtou64_base(str, &ret, base)) { 752 return PosixError(EINVAL, "String not a number."); 753 } 754 755 return ret; 756 } 757 758 inline PosixErrorOr<double> Atod(absl::string_view str) { 759 double ret; 760 if (!absl::SimpleAtod(str, &ret)) { 761 return PosixError(EINVAL, "String not a double type."); 762 } 763 return ret; 764 } 765 766 inline PosixErrorOr<float> Atof(absl::string_view str) { 767 float ret; 768 if (!absl::SimpleAtof(str, &ret)) { 769 return PosixError(EINVAL, "String not a float type."); 770 } 771 return ret; 772 } 773 774 // Return the smallest number of iovec arrays that can be used to write 775 // "total_bytes" number of bytes, each iovec writing one "buf". 776 std::vector<std::vector<struct iovec>> GenerateIovecs(uint64_t total_size, 777 void* buf, size_t buflen); 778 779 // Returns bytes in 'n' megabytes. Used for readability. 780 uint64_t Megabytes(uint64_t n); 781 782 // Predicate for checking that a value is within some tolerance of another 783 // value. Returns true iff current is in the range [target * (1 - tolerance), 784 // target * (1 + tolerance)]. 785 bool Equivalent(uint64_t current, uint64_t target, double tolerance); 786 787 // Matcher wrapping the Equivalent predicate. 788 MATCHER_P2(EquivalentWithin, target, tolerance, 789 std::string(negation ? "Isn't" : "Is") + 790 ::absl::StrFormat(" within %.2f%% of the target of %zd bytes", 791 tolerance * 100, target)) { 792 if (target == 0) { 793 *result_listener << ::absl::StreamFormat("difference of infinity%%"); 794 } else { 795 int64_t delta = static_cast<int64_t>(arg) - static_cast<int64_t>(target); 796 double delta_percent = 797 static_cast<double>(delta) / static_cast<double>(target) * 100; 798 *result_listener << ::absl::StreamFormat("difference of %.2f%%", 799 delta_percent); 800 } 801 return Equivalent(arg, target, tolerance); 802 } 803 804 // Returns the absolute path to the a data dependency. 'path' is the runfile 805 // location relative to workspace root. 806 #ifdef __linux__ 807 std::string RunfilePath(std::string path); 808 #endif 809 810 void TestInit(int* argc, char*** argv); 811 int RunAllTests(void); 812 813 } // namespace testing 814 } // namespace gvisor 815 816 #endif // GVISOR_TEST_UTIL_TEST_UTIL_H_