From e8c9360849f8cd07f13643fb69839a7b3e8df383 Mon Sep 17 00:00:00 2001 From: Daniel Lowengrub Date: Wed, 13 May 2026 11:58:10 -0700 Subject: [PATCH] Arbitrary StatusCode Domain PiperOrigin-RevId: 914981771 --- doc/domains-reference.md | 2 ++ domain_tests/arbitrary_domains_test.cc | 39 ++++++++++++++++++++++ fuzztest/internal/domains/arbitrary_impl.h | 27 +++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/doc/domains-reference.md b/doc/domains-reference.md index 4db65653c..32ea226f4 100644 --- a/doc/domains-reference.md +++ b/doc/domains-reference.md @@ -42,6 +42,8 @@ protocol buffers. Specifically, for the following types: - 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` or `std::vector`, 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 ce611704e..6b2829a8d 100644 --- a/domain_tests/arbitrary_domains_test.cc +++ b/domain_tests/arbitrary_domains_test.cc @@ -626,5 +626,44 @@ TEST(ArbitraryTimeTest, ArbitraryVectorHasAllTypesOfValues) { EXPECT_THAT(to_find, IsEmpty()); } +TEST(ArbitraryStatusCodeTest, GeneratesAllValues) { + absl::flat_hash_set 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::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 domain = Arbitrary().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 b4d53484e..d31c31bf7 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 @@ class ArbitraryImpl ArbitraryImpl()) {} }; +// Arbitrary for absl::StatusCode. +using StatusCodeUnderlyingT = std::underlying_type_t; + +template <> +class ArbitraryImpl + : public ReversibleMapImpl< + absl::StatusCode (*)(StatusCodeUnderlyingT), + std::optional> (*)( + absl::StatusCode), + InRangeImpl> { + public: + ArbitraryImpl() + : ReversibleMapImpl> (*)( + absl::StatusCode), + InRangeImpl>( + [](StatusCodeUnderlyingT code) { + return static_cast(code); + }, + [](absl::StatusCode code) { + return std::optional{ + std::tuple{static_cast(code)}}; + }, + InRangeImpl(0, 16)) {} +}; + // Arbitrary for absl::BitGenRef. template <> class ArbitraryImpl