diff options
Diffstat (limited to 'test/util')
-rw-r--r-- | test/util/BUILD | 1 | ||||
-rw-r--r-- | test/util/fs_util.cc | 16 | ||||
-rw-r--r-- | test/util/fs_util.h | 2 | ||||
-rw-r--r-- | test/util/logging.cc | 8 | ||||
-rw-r--r-- | test/util/logging.h | 39 | ||||
-rw-r--r-- | test/util/multiprocess_util.cc | 3 | ||||
-rw-r--r-- | test/util/multiprocess_util.h | 3 | ||||
-rw-r--r-- | test/util/posix_error.cc | 2 | ||||
-rw-r--r-- | test/util/posix_error.h | 14 |
9 files changed, 72 insertions, 16 deletions
diff --git a/test/util/BUILD b/test/util/BUILD index 1b028a477..e561f3daa 100644 --- a/test/util/BUILD +++ b/test/util/BUILD @@ -172,6 +172,7 @@ cc_library( ":posix_error", ":save_util", ":test_util", + gtest, "@com_google_absl//absl/strings", ], ) diff --git a/test/util/fs_util.cc b/test/util/fs_util.cc index b16055dd8..5f1ce0d8a 100644 --- a/test/util/fs_util.cc +++ b/test/util/fs_util.cc @@ -663,5 +663,21 @@ PosixErrorOr<bool> IsOverlayfs(const std::string& path) { return stat.f_type == OVERLAYFS_SUPER_MAGIC; } +PosixError CheckSameFile(const FileDescriptor& fd1, const FileDescriptor& fd2) { + struct stat stat_result1, stat_result2; + int res = fstat(fd1.get(), &stat_result1); + if (res < 0) { + return PosixError(errno, absl::StrCat("fstat ", fd1.get())); + } + + res = fstat(fd2.get(), &stat_result2); + if (res < 0) { + return PosixError(errno, absl::StrCat("fstat ", fd2.get())); + } + EXPECT_EQ(stat_result1.st_dev, stat_result2.st_dev); + EXPECT_EQ(stat_result1.st_ino, stat_result2.st_ino); + + return NoError(); +} } // namespace testing } // namespace gvisor diff --git a/test/util/fs_util.h b/test/util/fs_util.h index c99cf5eb7..2190c3bca 100644 --- a/test/util/fs_util.h +++ b/test/util/fs_util.h @@ -191,6 +191,8 @@ PosixErrorOr<bool> IsTmpfs(const std::string& path); // IsOverlayfs returns true if the file at path is backed by overlayfs. PosixErrorOr<bool> IsOverlayfs(const std::string& path); +PosixError CheckSameFile(const FileDescriptor& fd1, const FileDescriptor& fd2); + namespace internal { // Not part of the public API. std::string JoinPathImpl(std::initializer_list<absl::string_view> paths); diff --git a/test/util/logging.cc b/test/util/logging.cc index 5d5e76c46..5fadb076b 100644 --- a/test/util/logging.cc +++ b/test/util/logging.cc @@ -69,9 +69,7 @@ int WriteNumber(int fd, uint32_t val) { } // namespace void CheckFailure(const char* cond, size_t cond_size, const char* msg, - size_t msg_size, bool include_errno) { - int saved_errno = errno; - + size_t msg_size, int errno_value) { constexpr char kCheckFailure[] = "Check failed: "; Write(2, kCheckFailure, sizeof(kCheckFailure) - 1); Write(2, cond, cond_size); @@ -81,10 +79,10 @@ void CheckFailure(const char* cond, size_t cond_size, const char* msg, Write(2, msg, msg_size); } - if (include_errno) { + if (errno_value != 0) { constexpr char kErrnoMessage[] = " (errno "; Write(2, kErrnoMessage, sizeof(kErrnoMessage) - 1); - WriteNumber(2, saved_errno); + WriteNumber(2, errno_value); Write(2, ")", 1); } diff --git a/test/util/logging.h b/test/util/logging.h index 589166fab..9d224ea05 100644 --- a/test/util/logging.h +++ b/test/util/logging.h @@ -21,7 +21,7 @@ namespace gvisor { namespace testing { void CheckFailure(const char* cond, size_t cond_size, const char* msg, - size_t msg_size, bool include_errno); + size_t msg_size, int errno_value); // If cond is false, aborts the current process. // @@ -30,7 +30,7 @@ void CheckFailure(const char* cond, size_t cond_size, const char* msg, do { \ if (!(cond)) { \ ::gvisor::testing::CheckFailure(#cond, sizeof(#cond) - 1, nullptr, \ - 0, false); \ + 0, 0); \ } \ } while (0) @@ -41,7 +41,7 @@ void CheckFailure(const char* cond, size_t cond_size, const char* msg, do { \ if (!(cond)) { \ ::gvisor::testing::CheckFailure(#cond, sizeof(#cond) - 1, msg, \ - sizeof(msg) - 1, false); \ + sizeof(msg) - 1, 0); \ } \ } while (0) @@ -52,7 +52,7 @@ void CheckFailure(const char* cond, size_t cond_size, const char* msg, do { \ if (!(cond)) { \ ::gvisor::testing::CheckFailure(#cond, sizeof(#cond) - 1, nullptr, \ - 0, true); \ + 0, errno); \ } \ } while (0) @@ -63,10 +63,39 @@ void CheckFailure(const char* cond, size_t cond_size, const char* msg, do { \ if (!(cond)) { \ ::gvisor::testing::CheckFailure(#cond, sizeof(#cond) - 1, msg, \ - sizeof(msg) - 1, true); \ + sizeof(msg) - 1, errno); \ } \ } while (0) +// expr must return PosixErrorOr<T>. The current process is aborted if +// !PosixError<T>.ok(). +// +// This macro is async-signal-safe. +#define TEST_CHECK_NO_ERRNO(expr) \ + ({ \ + auto _expr_result = (expr); \ + if (!_expr_result.ok()) { \ + ::gvisor::testing::CheckFailure( \ + #expr, sizeof(#expr) - 1, nullptr, 0, \ + _expr_result.error().errno_value()); \ + } \ + }) + +// expr must return PosixErrorOr<T>. The current process is aborted if +// !PosixError<T>.ok(). Otherwise, PosixErrorOr<T> value is returned. +// +// This macro is async-signal-safe. +#define TEST_CHECK_NO_ERRNO_AND_VALUE(expr) \ + ({ \ + auto _expr_result = (expr); \ + if (!_expr_result.ok()) { \ + ::gvisor::testing::CheckFailure( \ + #expr, sizeof(#expr) - 1, nullptr, 0, \ + _expr_result.error().errno_value()); \ + } \ + std::move(_expr_result).ValueOrDie(); \ + }) + } // namespace testing } // namespace gvisor diff --git a/test/util/multiprocess_util.cc b/test/util/multiprocess_util.cc index 8b676751b..a6b0de24b 100644 --- a/test/util/multiprocess_util.cc +++ b/test/util/multiprocess_util.cc @@ -154,6 +154,9 @@ PosixErrorOr<int> InForkedProcess(const std::function<void()>& fn) { pid_t pid = fork(); if (pid == 0) { fn(); + TEST_CHECK_MSG(!::testing::Test::HasFailure(), + "EXPECT*/ASSERT* failed. These are not async-signal-safe " + "and must not be called from fn."); _exit(0); } MaybeSave(); diff --git a/test/util/multiprocess_util.h b/test/util/multiprocess_util.h index 2f3bf4a6f..840fde4ee 100644 --- a/test/util/multiprocess_util.h +++ b/test/util/multiprocess_util.h @@ -123,7 +123,8 @@ inline PosixErrorOr<Cleanup> ForkAndExecveat(int32_t dirfd, // Calls fn in a forked subprocess and returns the exit status of the // subprocess. // -// fn must be async-signal-safe. +// fn must be async-signal-safe. Use of ASSERT/EXPECT functions is prohibited. +// Use TEST_CHECK variants instead. PosixErrorOr<int> InForkedProcess(const std::function<void()>& fn); } // namespace testing diff --git a/test/util/posix_error.cc b/test/util/posix_error.cc index deed0c05b..8522e4c81 100644 --- a/test/util/posix_error.cc +++ b/test/util/posix_error.cc @@ -50,7 +50,7 @@ std::string PosixError::ToString() const { ret = absl::StrCat("PosixError(errno=", errno_, " ", res, ")"); #endif - if (!msg_.empty()) { + if (strnlen(msg_, sizeof(msg_)) > 0) { ret.append(" "); ret.append(msg_); } diff --git a/test/util/posix_error.h b/test/util/posix_error.h index b634a7f78..27557ad44 100644 --- a/test/util/posix_error.h +++ b/test/util/posix_error.h @@ -26,12 +26,18 @@ namespace gvisor { namespace testing { +// PosixError must be async-signal-safe. class ABSL_MUST_USE_RESULT PosixError { public: PosixError() {} + explicit PosixError(int errno_value) : errno_(errno_value) {} - PosixError(int errno_value, std::string msg) - : errno_(errno_value), msg_(std::move(msg)) {} + + PosixError(int errno_value, std::string_view msg) : errno_(errno_value) { + // Check that `msg` will fit, leaving room for '\0' at the end. + TEST_CHECK(msg.size() < sizeof(msg_)); + msg.copy(msg_, msg.size()); + } PosixError(PosixError&& other) = default; PosixError& operator=(PosixError&& other) = default; @@ -45,7 +51,7 @@ class ABSL_MUST_USE_RESULT PosixError { const PosixError& error() const { return *this; } int errno_value() const { return errno_; } - std::string message() const { return msg_; } + const char* message() const { return msg_; } // ToString produces a full string representation of this posix error // including the printable representation of the errno and the error message. @@ -58,7 +64,7 @@ class ABSL_MUST_USE_RESULT PosixError { private: int errno_ = 0; - std::string msg_; + char msg_[1024] = {}; }; template <typename T> |