Arbitrary StatusCode Domain

PiperOrigin-RevId: 914981771
diff --git a/doc/domains-reference.md b/doc/domains-reference.md
index 4db6565..32ea226 100644
--- a/doc/domains-reference.md
+++ b/doc/domains-reference.md
@@ -42,6 +42,8 @@
 -   Protocol buffer types: `MyProtoMessage`, etc.
 -   [Abseil time library types](https://abseil.io/docs/cpp/guides/time):
     `absl::Duration`, `absl::Time`.
+-   [Abseil status types](https://abseil.io/docs/cpp/guides/status):
+    `absl::StatusCode`.
 
 Composite or container types, like `std::optional<T>` or `std::vector<T>`, are
 supported as long as the inner types are. For example,
diff --git a/domain_tests/arbitrary_domains_test.cc b/domain_tests/arbitrary_domains_test.cc
index ce61170..6b2829a 100644
--- a/domain_tests/arbitrary_domains_test.cc
+++ b/domain_tests/arbitrary_domains_test.cc
@@ -626,5 +626,44 @@
   EXPECT_THAT(to_find, IsEmpty());
 }
 
+TEST(ArbitraryStatusCodeTest, GeneratesAllValues) {
+  absl::flat_hash_set<absl::StatusCode> to_find = {
+      absl::StatusCode::kOk,
+      absl::StatusCode::kCancelled,
+      absl::StatusCode::kUnknown,
+      absl::StatusCode::kInvalidArgument,
+      absl::StatusCode::kDeadlineExceeded,
+      absl::StatusCode::kNotFound,
+      absl::StatusCode::kAlreadyExists,
+      absl::StatusCode::kPermissionDenied,
+      absl::StatusCode::kResourceExhausted,
+      absl::StatusCode::kFailedPrecondition,
+      absl::StatusCode::kAborted,
+      absl::StatusCode::kOutOfRange,
+      absl::StatusCode::kUnimplemented,
+      absl::StatusCode::kInternal,
+      absl::StatusCode::kUnavailable,
+      absl::StatusCode::kDataLoss,
+      absl::StatusCode::kUnauthenticated,
+  };
+  auto domain = Arbitrary<absl::StatusCode>();
+  absl::BitGen prng;
+
+  const int max_iterations = IterationsToHitAll(17, 1.0 / (4 * 17));
+  for (int i = 0; i < max_iterations && !to_find.empty(); ++i) {
+    to_find.erase(domain.GetRandomValue(prng));
+  }
+
+  EXPECT_THAT(to_find, IsEmpty());
+}
+
+TEST(ArbitraryStatusCodeTest, InitGeneratesSeeds) {
+  Domain<absl::StatusCode> domain = Arbitrary<absl::StatusCode>().WithSeeds(
+      {absl::StatusCode::kInvalidArgument});
+
+  EXPECT_THAT(GenerateInitialValues(domain, 1000),
+              Contains(Value(domain, absl::StatusCode::kInvalidArgument)));
+}
+
 }  // namespace
 }  // namespace fuzztest
diff --git a/fuzztest/internal/domains/arbitrary_impl.h b/fuzztest/internal/domains/arbitrary_impl.h
index b4d5348..d31c31b 100644
--- a/fuzztest/internal/domains/arbitrary_impl.h
+++ b/fuzztest/internal/domains/arbitrary_impl.h
@@ -31,6 +31,7 @@
 
 #include "absl/random/bit_gen_ref.h"
 #include "absl/random/distributions.h"
+#include "absl/status/status.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/time.h"
 #include "./fuzztest/internal/domains/absl_helpers.h"
@@ -583,6 +584,32 @@
             ArbitraryImpl<absl::Duration>()) {}
 };
 
+// Arbitrary for absl::StatusCode.
+using StatusCodeUnderlyingT = std::underlying_type_t<absl::StatusCode>;
+
+template <>
+class ArbitraryImpl<absl::StatusCode>
+    : public ReversibleMapImpl<
+          absl::StatusCode (*)(StatusCodeUnderlyingT),
+          std::optional<std::tuple<StatusCodeUnderlyingT>> (*)(
+              absl::StatusCode),
+          InRangeImpl<StatusCodeUnderlyingT>> {
+ public:
+  ArbitraryImpl()
+      : ReversibleMapImpl<absl::StatusCode (*)(StatusCodeUnderlyingT),
+                          std::optional<std::tuple<StatusCodeUnderlyingT>> (*)(
+                              absl::StatusCode),
+                          InRangeImpl<StatusCodeUnderlyingT>>(
+            [](StatusCodeUnderlyingT code) {
+              return static_cast<absl::StatusCode>(code);
+            },
+            [](absl::StatusCode code) {
+              return std::optional{
+                  std::tuple{static_cast<StatusCodeUnderlyingT>(code)}};
+            },
+            InRangeImpl<StatusCodeUnderlyingT>(0, 16)) {}
+};
+
 // Arbitrary for absl::BitGenRef.
 template <>
 class ArbitraryImpl<absl::BitGenRef>