about summary refs log tree commit diff
path: root/third_party/nix/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/nix/src/tests')
-rw-r--r--third_party/nix/src/tests/status_helpers.h83
1 files changed, 83 insertions, 0 deletions
diff --git a/third_party/nix/src/tests/status_helpers.h b/third_party/nix/src/tests/status_helpers.h
new file mode 100644
index 000000000000..ca596dbb5254
--- /dev/null
+++ b/third_party/nix/src/tests/status_helpers.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <absl/status/status.h>
+#include <absl/status/statusor.h>
+#include <absl/strings/str_cat.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace testing {
+
+/*
+ * This file contains gtest matchers for absl::Status.
+ *
+ * Example usage:
+ *
+ *   EXPECT_OK(status); -- fails the test if 'status' is an error
+ *   ASSERT_OK(status); -- instantly fails the test if error
+ *
+ *   using ::testing::IsStatusCode;
+ *   EXPECT_THAT(status, IsStatusCode(absl::StatusCode::kInternal));
+ */
+
+namespace nix_internal {
+
+using ::testing::MakeMatcher;
+using ::testing::Matcher;
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+
+MATCHER_P(IsStatusCode, code, "") { return arg.code() == code; }
+
+class StatusCodeMatcher {
+ public:
+  StatusCodeMatcher(absl::StatusCode code) : code_(code) {}
+
+  // Match on absl::Status.
+  template <class T,
+            typename std::enable_if<std::is_same<T, absl::Status>::value,
+                                    int>::type int_ = 0>
+  bool MatchAndExplain(const T& status,
+                       MatchResultListener* /* listener */) const {
+    return status.code() == code_;
+  }
+
+  // Match on absl::StatusOr.
+  //
+  // note: I check for the return value of ConsumeValueOrDie because it's the
+  // only non-overloaded member I could figure out how to select. Checking for
+  // the presence of .status() didn't work because it's overloaded, so
+  // std::invoke_result can't pick which overload to use.
+  template <class T,
+            typename std::enable_if<
+                std::is_same<typename std::invoke_result<
+                                 decltype(&T::ConsumeValueOrDie), T>::type,
+                             typename T::value_type>::value,
+                int>::type int_ = 0>
+  bool MatchAndExplain(const T& statusor,
+                       MatchResultListener* /* listener */) const {
+    return statusor.status().code() == code_;
+  }
+
+  void DescribeTo(std::ostream* os) const { *os << "is " << code_; }
+
+  void DescribeNegationTo(std::ostream* os) const { *os << "isn't " << code_; }
+
+ private:
+  absl::StatusCode code_;
+};
+
+}  // namespace nix_internal
+
+PolymorphicMatcher<nix_internal::StatusCodeMatcher> IsStatusCode(
+    absl::StatusCode code) {
+  return MakePolymorphicMatcher(nix_internal::StatusCodeMatcher(code));
+}
+
+#define EXPECT_OK(status) \
+  EXPECT_THAT((status), testing::IsStatusCode(absl::StatusCode::kOk))
+
+#define ASSERT_OK(status) \
+  ASSERT_THAT((status), testing::IsStatusCode(absl::StatusCode::kOk))
+
+}  // namespace testing