github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/util/posix_error.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 #ifndef GVISOR_TEST_UTIL_POSIX_ERROR_H_ 16 #define GVISOR_TEST_UTIL_POSIX_ERROR_H_ 17 18 #include <string> 19 20 #include "gmock/gmock.h" 21 #include "absl/base/attributes.h" 22 #include "absl/strings/string_view.h" 23 #include "absl/types/variant.h" 24 #include "test/util/logging.h" 25 26 namespace gvisor { 27 namespace testing { 28 29 // PosixError must be async-signal-safe. 30 class ABSL_MUST_USE_RESULT PosixError { 31 public: 32 PosixError() {} 33 34 explicit PosixError(int errno_value) : errno_(errno_value) {} 35 36 PosixError(int errno_value, std::string_view msg) : errno_(errno_value) { 37 // Check that `msg` will fit, leaving room for '\0' at the end. 38 TEST_CHECK(msg.size() < sizeof(msg_)); 39 msg.copy(msg_, msg.size()); 40 } 41 42 PosixError(PosixError&& other) = default; 43 PosixError& operator=(PosixError&& other) = default; 44 PosixError(const PosixError&) = default; 45 PosixError& operator=(const PosixError&) = default; 46 47 bool ok() const { return errno_ == 0; } 48 49 // Returns a reference to *this to make matchers compatible with 50 // PosixErrorOr. 51 const PosixError& error() const { return *this; } 52 53 int errno_value() const { return errno_; } 54 const char* message() const { return msg_; } 55 56 // ToString produces a full string representation of this posix error 57 // including the printable representation of the errno and the error message. 58 std::string ToString() const; 59 60 // Ignores any errors. This method does nothing except potentially suppress 61 // complaints from any tools that are checking that errors are not dropped on 62 // the floor. 63 void IgnoreError() const {} 64 65 private: 66 int errno_ = 0; 67 char msg_[1024] = {}; 68 }; 69 70 template <typename T> 71 class ABSL_MUST_USE_RESULT PosixErrorOr { 72 public: 73 // A PosixErrorOr will check fail if it is constructed with NoError(). 74 PosixErrorOr(const PosixError& error); 75 PosixErrorOr(const T& value); 76 PosixErrorOr(T&& value); 77 78 PosixErrorOr(PosixErrorOr&& other) = default; 79 PosixErrorOr& operator=(PosixErrorOr&& other) = default; 80 PosixErrorOr(const PosixErrorOr&) = default; 81 PosixErrorOr& operator=(const PosixErrorOr&) = default; 82 83 // Conversion copy/move constructor, T must be convertible from U. 84 template <typename U> 85 friend class PosixErrorOr; 86 87 template <typename U> 88 PosixErrorOr(PosixErrorOr<U> other); 89 90 template <typename U> 91 PosixErrorOr& operator=(PosixErrorOr<U> other); 92 93 // Returns true if this PosixErrorOr contains some T. 94 bool ok() const; 95 96 // Return a copy of the contained PosixError or NoError(). 97 PosixError error() const; 98 99 // Returns a reference to our current value, or CHECK-fails if !this->ok(). 100 const T& ValueOrDie() const&; 101 T& ValueOrDie() &; 102 const T&& ValueOrDie() const&&; 103 T&& ValueOrDie() &&; 104 105 // Ignores any errors. This method does nothing except potentially suppress 106 // complaints from any tools that are checking that errors are not dropped on 107 // the floor. 108 void IgnoreError() const {} 109 110 private: 111 absl::variant<T, PosixError> value_; 112 113 friend class PosixErrorIsMatcherCommonImpl; 114 }; 115 116 template <typename T> 117 PosixErrorOr<T>::PosixErrorOr(const PosixError& error) : value_(error) { 118 TEST_CHECK_MSG( 119 !error.ok(), 120 "Constructing PosixErrorOr with NoError, eg. errno 0 is not allowed."); 121 } 122 123 template <typename T> 124 PosixErrorOr<T>::PosixErrorOr(const T& value) : value_(value) {} 125 126 template <typename T> 127 PosixErrorOr<T>::PosixErrorOr(T&& value) : value_(std::move(value)) {} 128 129 // Conversion copy/move constructor, T must be convertible from U. 130 template <typename T> 131 template <typename U> 132 inline PosixErrorOr<T>::PosixErrorOr(PosixErrorOr<U> other) { 133 if (absl::holds_alternative<U>(other.value_)) { 134 // T is convertible from U. 135 value_ = absl::get<U>(std::move(other.value_)); 136 } else if (absl::holds_alternative<PosixError>(other.value_)) { 137 value_ = absl::get<PosixError>(std::move(other.value_)); 138 } else { 139 TEST_CHECK_MSG(false, "PosixErrorOr does not contain PosixError or value"); 140 } 141 } 142 143 template <typename T> 144 template <typename U> 145 inline PosixErrorOr<T>& PosixErrorOr<T>::operator=(PosixErrorOr<U> other) { 146 if (absl::holds_alternative<U>(other.value_)) { 147 // T is convertible from U. 148 value_ = absl::get<U>(std::move(other.value_)); 149 } else if (absl::holds_alternative<PosixError>(other.value_)) { 150 value_ = absl::get<PosixError>(std::move(other.value_)); 151 } else { 152 TEST_CHECK_MSG(false, "PosixErrorOr does not contain PosixError or value"); 153 } 154 return *this; 155 } 156 157 template <typename T> 158 PosixError PosixErrorOr<T>::error() const { 159 if (!absl::holds_alternative<PosixError>(value_)) { 160 return PosixError(); 161 } 162 return absl::get<PosixError>(value_); 163 } 164 165 template <typename T> 166 bool PosixErrorOr<T>::ok() const { 167 return absl::holds_alternative<T>(value_); 168 } 169 170 template <typename T> 171 const T& PosixErrorOr<T>::ValueOrDie() const& { 172 TEST_CHECK(absl::holds_alternative<T>(value_)); 173 return absl::get<T>(value_); 174 } 175 176 template <typename T> 177 T& PosixErrorOr<T>::ValueOrDie() & { 178 TEST_CHECK(absl::holds_alternative<T>(value_)); 179 return absl::get<T>(value_); 180 } 181 182 template <typename T> 183 const T&& PosixErrorOr<T>::ValueOrDie() const&& { 184 TEST_CHECK(absl::holds_alternative<T>(value_)); 185 return std::move(absl::get<T>(value_)); 186 } 187 188 template <typename T> 189 T&& PosixErrorOr<T>::ValueOrDie() && { 190 TEST_CHECK(absl::holds_alternative<T>(value_)); 191 return std::move(absl::get<T>(value_)); 192 } 193 194 extern ::std::ostream& operator<<(::std::ostream& os, const PosixError& e); 195 196 template <typename T> 197 ::std::ostream& operator<<(::std::ostream& os, const PosixErrorOr<T>& e) { 198 os << e.error(); 199 return os; 200 } 201 202 // NoError is a PosixError that represents a successful state, i.e. No Error. 203 inline PosixError NoError() { return PosixError(); } 204 205 // Monomorphic implementation of matcher IsPosixErrorOk() for a given type T. 206 // T can be PosixError, PosixErrorOr<>, or a reference to either of them. 207 template <typename T> 208 class MonoPosixErrorIsOkMatcherImpl : public ::testing::MatcherInterface<T> { 209 public: 210 void DescribeTo(std::ostream* os) const override { *os << "is OK"; } 211 void DescribeNegationTo(std::ostream* os) const override { 212 *os << "is not OK"; 213 } 214 bool MatchAndExplain(T actual_value, 215 ::testing::MatchResultListener*) const override { 216 return actual_value.ok(); 217 } 218 }; 219 220 // Implements IsPosixErrorOkMatcher() as a polymorphic matcher. 221 class IsPosixErrorOkMatcher { 222 public: 223 template <typename T> 224 operator ::testing::Matcher<T>() const { // NOLINT 225 return MakeMatcher(new MonoPosixErrorIsOkMatcherImpl<T>()); 226 } 227 }; 228 229 // Monomorphic implementation of a matcher for a PosixErrorOr. 230 template <typename PosixErrorOrType> 231 class IsPosixErrorOkAndHoldsMatcherImpl 232 : public ::testing::MatcherInterface<PosixErrorOrType> { 233 public: 234 using ValueType = typename std::remove_reference<decltype( 235 std::declval<PosixErrorOrType>().ValueOrDie())>::type; 236 237 template <typename InnerMatcher> 238 explicit IsPosixErrorOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher) 239 : inner_matcher_(::testing::SafeMatcherCast<const ValueType&>( 240 std::forward<InnerMatcher>(inner_matcher))) {} 241 242 void DescribeTo(std::ostream* os) const override { 243 *os << "is OK and has a value that "; 244 inner_matcher_.DescribeTo(os); 245 } 246 247 void DescribeNegationTo(std::ostream* os) const override { 248 *os << "isn't OK or has a value that "; 249 inner_matcher_.DescribeNegationTo(os); 250 } 251 252 bool MatchAndExplain( 253 PosixErrorOrType actual_value, 254 ::testing::MatchResultListener* listener) const override { 255 // We can't extract the value if it doesn't contain one. 256 if (!actual_value.ok()) { 257 return false; 258 } 259 260 ::testing::StringMatchResultListener inner_listener; 261 const bool matches = inner_matcher_.MatchAndExplain( 262 actual_value.ValueOrDie(), &inner_listener); 263 const std::string inner_explanation = inner_listener.str(); 264 *listener << "has a value " 265 << ::testing::PrintToString(actual_value.ValueOrDie()); 266 267 if (!inner_explanation.empty()) { 268 *listener << " " << inner_explanation; 269 } 270 return matches; 271 } 272 273 private: 274 const ::testing::Matcher<const ValueType&> inner_matcher_; 275 }; 276 277 // Implements IsOkAndHolds() as a polymorphic matcher. 278 template <typename InnerMatcher> 279 class IsPosixErrorOkAndHoldsMatcher { 280 public: 281 explicit IsPosixErrorOkAndHoldsMatcher(InnerMatcher inner_matcher) 282 : inner_matcher_(std::move(inner_matcher)) {} 283 284 // Converts this polymorphic matcher to a monomorphic one of the given type. 285 // PosixErrorOrType can be either PosixErrorOr<T> or a reference to 286 // PosixErrorOr<T>. 287 template <typename PosixErrorOrType> 288 operator ::testing::Matcher<PosixErrorOrType>() const { // NOLINT 289 return ::testing::MakeMatcher( 290 new IsPosixErrorOkAndHoldsMatcherImpl<PosixErrorOrType>( 291 inner_matcher_)); 292 } 293 294 private: 295 const InnerMatcher inner_matcher_; 296 }; 297 298 // PosixErrorIs() is a polymorphic matcher. This class is the common 299 // implementation of it shared by all types T where PosixErrorIs() can be 300 // used as a Matcher<T>. 301 class PosixErrorIsMatcherCommonImpl { 302 public: 303 PosixErrorIsMatcherCommonImpl( 304 ::testing::Matcher<int> code_matcher, 305 ::testing::Matcher<const std::string&> message_matcher) 306 : code_matcher_(std::move(code_matcher)), 307 message_matcher_(std::move(message_matcher)) {} 308 309 void DescribeTo(std::ostream* os) const; 310 311 void DescribeNegationTo(std::ostream* os) const; 312 313 bool MatchAndExplain(const PosixError& error, 314 ::testing::MatchResultListener* result_listener) const; 315 316 template <typename T> 317 bool MatchAndExplain(const PosixErrorOr<T>& error_or, 318 ::testing::MatchResultListener* result_listener) const { 319 if (error_or.ok()) { 320 *result_listener << "has a value " 321 << ::testing::PrintToString(error_or.ValueOrDie()); 322 return false; 323 } 324 325 return MatchAndExplain(error_or.error(), result_listener); 326 } 327 328 private: 329 const ::testing::Matcher<int> code_matcher_; 330 const ::testing::Matcher<const std::string&> message_matcher_; 331 }; 332 333 // Monomorphic implementation of matcher PosixErrorIs() for a given type 334 // T. T can be PosixError, PosixErrorOr<>, or a reference to either of them. 335 template <typename T> 336 class MonoPosixErrorIsMatcherImpl : public ::testing::MatcherInterface<T> { 337 public: 338 explicit MonoPosixErrorIsMatcherImpl( 339 PosixErrorIsMatcherCommonImpl common_impl) 340 : common_impl_(std::move(common_impl)) {} 341 342 void DescribeTo(std::ostream* os) const override { 343 common_impl_.DescribeTo(os); 344 } 345 346 void DescribeNegationTo(std::ostream* os) const override { 347 common_impl_.DescribeNegationTo(os); 348 } 349 350 bool MatchAndExplain( 351 T actual_value, 352 ::testing::MatchResultListener* result_listener) const override { 353 return common_impl_.MatchAndExplain(actual_value, result_listener); 354 } 355 356 private: 357 PosixErrorIsMatcherCommonImpl common_impl_; 358 }; 359 360 inline ::testing::Matcher<int> ToErrorCodeMatcher( 361 const ::testing::Matcher<int>& m) { 362 return m; 363 } 364 365 // Implements PosixErrorIs() as a polymorphic matcher. 366 class PosixErrorIsMatcher { 367 public: 368 template <typename ErrorCodeMatcher> 369 PosixErrorIsMatcher(ErrorCodeMatcher&& code_matcher, 370 ::testing::Matcher<const std::string&> message_matcher) 371 : common_impl_( 372 ToErrorCodeMatcher(std::forward<ErrorCodeMatcher>(code_matcher)), 373 std::move(message_matcher)) {} 374 375 // Converts this polymorphic matcher to a monomorphic matcher of the 376 // given type. T can be StatusOr<>, Status, or a reference to 377 // either of them. 378 template <typename T> 379 operator ::testing::Matcher<T>() const { // NOLINT 380 return MakeMatcher(new MonoPosixErrorIsMatcherImpl<T>(common_impl_)); 381 } 382 383 private: 384 const PosixErrorIsMatcherCommonImpl common_impl_; 385 }; 386 387 // Returns a gMock matcher that matches a PosixError or PosixErrorOr<> whose 388 // error code matches code_matcher, and whose error message matches 389 // message_matcher. 390 template <typename ErrorCodeMatcher> 391 PosixErrorIsMatcher PosixErrorIs( 392 ErrorCodeMatcher&& code_matcher, 393 ::testing::Matcher<const std::string&> message_matcher) { 394 return PosixErrorIsMatcher(std::forward<ErrorCodeMatcher>(code_matcher), 395 std::move(message_matcher)); 396 } 397 398 // Returns a gMock matcher that matches a PosixError or PosixErrorOr<> whose 399 // error code matches code_matcher. 400 template <typename ErrorCodeMatcher> 401 PosixErrorIsMatcher PosixErrorIs(ErrorCodeMatcher&& code_matcher) { 402 return PosixErrorIsMatcher(std::forward<ErrorCodeMatcher>(code_matcher), 403 ::testing::_); 404 } 405 406 // Returns a gMock matcher that matches a PosixErrorOr<> which is ok() and 407 // value matches the inner matcher. 408 template <typename InnerMatcher> 409 IsPosixErrorOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type> 410 IsPosixErrorOkAndHolds(InnerMatcher&& inner_matcher) { 411 return IsPosixErrorOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>( 412 std::forward<InnerMatcher>(inner_matcher)); 413 } 414 415 // Internal helper for concatenating macro values. 416 #define POSIX_ERROR_IMPL_CONCAT_INNER_(x, y) x##y 417 #define POSIX_ERROR_IMPL_CONCAT_(x, y) POSIX_ERROR_IMPL_CONCAT_INNER_(x, y) 418 419 #define POSIX_ERROR_IMPL_ASSIGN_OR_RETURN_(posixerroror, lhs, rexpr) \ 420 auto posixerroror = (rexpr); \ 421 if (!posixerroror.ok()) { \ 422 return (posixerroror.error()); \ 423 } \ 424 lhs = std::move(posixerroror).ValueOrDie() 425 426 #define EXPECT_NO_ERRNO(expression) \ 427 EXPECT_THAT(expression, IsPosixErrorOkMatcher()) 428 #define ASSERT_NO_ERRNO(expression) \ 429 ASSERT_THAT(expression, IsPosixErrorOkMatcher()) 430 431 #define ASSIGN_OR_RETURN_ERRNO(lhs, rexpr) \ 432 POSIX_ERROR_IMPL_ASSIGN_OR_RETURN_( \ 433 POSIX_ERROR_IMPL_CONCAT_(_status_or_value, __LINE__), lhs, rexpr) 434 435 #define RETURN_IF_ERRNO(s) \ 436 do { \ 437 if (!s.ok()) { \ 438 return s; \ 439 } \ 440 } while (false); 441 442 #define ASSERT_NO_ERRNO_AND_VALUE(expr) \ 443 ({ \ 444 auto _expr_result = (expr); \ 445 ASSERT_NO_ERRNO(_expr_result); \ 446 std::move(_expr_result).ValueOrDie(); \ 447 }) 448 449 #define EXPECT_NO_ERRNO_AND_VALUE(expr) \ 450 ({ \ 451 auto _expr_result = (expr); \ 452 EXPECT_NO_ERRNO(_expr_result); \ 453 std::move(_expr_result).ValueOrDie(); \ 454 }) 455 456 } // namespace testing 457 } // namespace gvisor 458 459 #endif // GVISOR_TEST_UTIL_POSIX_ERROR_H_