Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions doc/domains-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ use out of the box.

### Arbitrary Domains

The `Arbitrary<T>()` domain is implemented for all native C++ types and for
protocol buffers. Specifically, for the following types:
The `Arbitrary<T>()` domain is implemented for all native C++ types,
protocol buffers, and some Abseil types.
Specifically, for the following types:

- Boolean type: `bool`.
- Character types: `char`, `signed char`, `unsigned char`.
Expand All @@ -43,7 +44,7 @@ protocol buffers. Specifically, for the following types:
- [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`.
`absl::StatusCode`, `absl::Status` (without support for payloads).

Composite or container types, like `std::optional<T>` or `std::vector<T>`, are
supported as long as the inner types are. For example,
Expand Down
1 change: 1 addition & 0 deletions domain_tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ cc_test(
"@abseil-cpp//absl/random",
"@abseil-cpp//absl/random:bit_gen_ref",
"@abseil-cpp//absl/status",
"@abseil-cpp//absl/strings:cord",
"@abseil-cpp//absl/time",
"@com_google_fuzztest//fuzztest:domain_core",
"@com_google_fuzztest//fuzztest/internal:serialization",
Expand Down
1 change: 1 addition & 0 deletions domain_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ fuzztest_cc_test(
"arbitrary_domains_test.cc"
DEPS
fuzztest::domain_testing
absl::cord
absl::flat_hash_set
absl::random_random
absl::random_bit_gen_ref
Expand Down
39 changes: 39 additions & 0 deletions domain_tests/arbitrary_domains_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "absl/random/bit_gen_ref.h"
#include "absl/random/random.h"
#include "absl/status/status.h"
#include "absl/strings/cord.h"
#include "absl/time/time.h"
#include "./fuzztest/domain_core.h" // IWYU pragma: keep
#include "./domain_tests/domain_testing.h"
Expand Down Expand Up @@ -665,5 +666,43 @@ TEST(ArbitraryStatusCodeTest, InitGeneratesSeeds) {
Contains(Value(domain, absl::StatusCode::kInvalidArgument)));
}

TEST(ArbitraryStatusTest, GeneratesOkAndError) {
auto domain = Arbitrary<absl::Status>();
absl::BitGen prng;
bool found_ok = false;
bool found_error = false;

for (int i = 0; i < 100 && (!found_ok || !found_error); ++i) {
absl::Status s = domain.GetRandomValue(prng);
if (s.ok()) {
found_ok = true;
} else {
found_error = true;
}
}

EXPECT_TRUE(found_ok);
EXPECT_TRUE(found_error);
}

TEST(ArbitraryStatusTest, InitGeneratesSeeds) {
absl::Status seed = absl::InvalidArgumentError("seed message");
Domain<absl::Status> domain = Arbitrary<absl::Status>().WithSeeds({seed});

EXPECT_THAT(GenerateInitialValues(domain, 1000),
Contains(Value(domain, seed)));
}

TEST(ArbitraryStatusTest, FromValueAndGetValuePreserveCodeAndMessage) {
auto domain = Arbitrary<absl::Status>();
absl::Status status = absl::InvalidArgumentError("msg");
status.SetPayload("some_url", absl::Cord("payload"));
auto corpus_val = domain.FromValue(status);
ASSERT_TRUE(corpus_val.has_value());
absl::Status mapped_status = domain.GetValue(*corpus_val);
EXPECT_EQ(mapped_status.code(), status.code());
EXPECT_EQ(mapped_status.message(), status.message());
}

} // namespace
} // namespace fuzztest
28 changes: 28 additions & 0 deletions fuzztest/internal/domains/arbitrary_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
Expand Down Expand Up @@ -610,6 +611,33 @@ class ArbitraryImpl<absl::StatusCode>
InRangeImpl<StatusCodeUnderlyingT>(0, 16)) {}
};

// Arbitrary for absl::Status.
// Note: This does not generate payloads. Payloads in seeds are ignored.
template <>
class ArbitraryImpl<absl::Status>
: public ReversibleMapImpl<
absl::Status (*)(absl::StatusCode, std::string),
std::optional<std::tuple<absl::StatusCode, std::string>> (*)(
absl::Status),
ArbitraryImpl<absl::StatusCode>, ArbitraryImpl<std::string>> {
public:
ArbitraryImpl()
: ReversibleMapImpl<
absl::Status (*)(absl::StatusCode, std::string),
std::optional<std::tuple<absl::StatusCode, std::string>> (*)(
absl::Status),
ArbitraryImpl<absl::StatusCode>, ArbitraryImpl<std::string>>(
[](absl::StatusCode code, std::string msg) {
return absl::Status(code, msg);
},
+[](absl::Status status)
-> std::optional<std::tuple<absl::StatusCode, std::string>> {
return std::optional{
std::tuple{status.code(), std::string(status.message())}};
},
ArbitraryImpl<absl::StatusCode>(), ArbitraryImpl<std::string>()) {}
};

// Arbitrary for absl::BitGenRef.
template <>
class ArbitraryImpl<absl::BitGenRef>
Expand Down
Loading