No public description
PiperOrigin-RevId: 814701490
diff --git a/doc/domains-reference.md b/doc/domains-reference.md
index b3e5e0d..1a8ab91 100644
--- a/doc/domains-reference.md
+++ b/doc/domains-reference.md
@@ -212,475 +212,6 @@
`std::string_view`), and Abseil time library types (`absl::Duration` and
`absl::Time`).
-### `BitFlagCombinationOf` Domains
-
-The `BitFlagCombinationOf` domain takes a list of binary flags and yields a
-random combination of them made through bitwise operations (`&`, `^`, etc.).
-Consider we have the following bitflag values:
-
-```c++
-enum Options {
- kFirst = 1 << 0,
- kSecond = 1 << 1,
- kThird = 1 << 2,
-};
-```
-
-The domain `BitFlagCombinationOf({kFirst, kThird})` will include `{0, kFirst,
-kThird, kFirst | kThird}`.
-
-### Uniform Random Bit Generator (URBG) Domains
-
-When your property function relies on random functionality requiring a Uniform
-Random Bit Generator (URBG), pass the generator using
-[`absl::BitGenRef`](https://abseil.io/docs/cpp/guides/random#bitgenref-a-type-erased-urbg-interface)
-and utilize the `Arbitrary<absl::BitGenRef>()` domain. This approach provides a
-specialized random generator tailored for fuzz testing.
-
-#### Enhanced Reproducibility
-
-Using `Arbitrary<absl::BitGenRef>()` ensures test reproducibility. The random
-sequence underlying the bit generator becomes the input of the test.
-Consequently, if a bug surfaces with a specific sequence of random values, the
-test can be reliably reproduced.
-
-**Example:**
-
-```c++
-void NeverCrash(const std::vector<int>& vec, absl::BitGenRef bitgen) {
- ...
- std::shuffle(vec.begin(), vec.end(), bitgen);
- DoStuffWith(vec);
- ...
-}
-FUZZ_TEST(MySuite, NeverCrash);
-```
-
-In this example fuzz test, if a crash is found with a particular vector with a
-particular shuffle, it will be reproducible with the dumped reproducer input,
-because it contains both the vector and the `bitgen` provided values.
-
-#### Robust Boundary Condition Testing
-
-The `Arbitrary<absl::BitGenRef>()` domain also provides mocks for
-[Abseil Random Library distribution functions](https://abseil.io/docs/cpp/guides/random)
-(e.g., `absl::Uniform()`, `absl::Bernoulli()`). These mocks directly interact
-with the underlying random sequence and aid the discovery of boundary conditions
-and edge cases.
-
-**Example:**
-
-```c++
-void DistributionTest(absl::BitGenRef bitgen) {
- EXPECT_THAT(absl::Uniform(bitgen, 0, 100), Lt(100));
-}
-FUZZ_TEST(MySuite, DistributionTest);
-```
-
-In this example, it's likely that `absl::Uniform()` will return boundary values
-like 0 and 99.
-
-#### Upgrading Randomized Tests to Coverage-Guided Fuzz Tests
-
-This domain also facilitates the transformation of existing randomized tests
-into more effective, coverage-guided fuzz tests. Consider a randomized test that
-triggers a bug only with a specific sequence of random samples:
-
-```c++
-void RandomizedTest(absl::BitGenRef bitgen) {
- if (absl::Uniform(bitgen, 0, 256) == 'F' &&
- absl::Uniform(bitgen, 0, 256) == 'U' &&
- absl::Uniform(bitgen, 0, 256) == 'Z' &&
- absl::Uniform(bitgen, 0, 256) == 'Z') {
- std::abort(); // Bug!
- }
-}
-```
-
-Running this test independently with a standard URBG (e.g., `std::minstd_rand`
-or `absl::BitGen`) is unlikely to uncover the bug. However, integrating it with
-a fuzz test using the `Arbitrary<absl::BitGenRef>()` domain will reliably find
-the bug:
-
-```c++
-FUZZ_TEST(MySuite, RandomizedTest);
-```
-
-This is because the coverage-guided fuzzing algorithm is applied to the
-underlying random seed sequence in this case. This coverage-guidance
-significantly improves the exploration of the code paths, making the fuzz test
-more effective than the original randomized test.
-
-#### Integrating Existing Random Value Generators
-
-A common use case involves integrating existing random value generators into
-fuzz tests. This can be achieved as follows:
-
-```c++
-void MyApiReturnsTrueForValidValues(absl::BitGenRef bitgen) {
- MyValue val = RandomMyValueGenerator(bitgen);
- EXPECT_TRUE(MyApi(val));
-}
-FUZZ_TEST(MySuite, MyApiReturnsTrueForValidValues);
-```
-
-Again, the benefits of this approach are the following:
-
-- **Coverage-Guided Exploration:** By providing the `absl::BitGenRef` to the
- generator, the fuzzing engine can intelligently explore the space of
- possible random values, leading to better coverage of the `MyApi` function.
-- **Reproducibility:** The test becomes reproducible, as the random seed is
- part of the fuzz test input.
-- **Boundary and Edge Case Discovery:** The fuzzing engine can systematically
- probe boundary conditions and edge cases in the `RandomMyValueGenerator` and
- `MyApi` functions, potentially uncovering hidden bugs.
-- **Improved Test Effectiveness:** This approach leverages the strengths of
- both random value generation and coverage-guided fuzzing, resulting in a
- more effective and robust test.
-
-### Protocol Buffer Domains
-
-You can use the `Arbitrary<T>()` domain with any proto message type or bare
-proto enum, e.g.:
-
-```c++
-void DoingStuffDoesNotCrashWithAnyProto(const ProtoA& msg_a, const ProtoB msg_b) {
- DoStuff(msg_a, msg_b);
-}
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithAnyProto);
-
-void DoingStuffDoesNotCrashWithEnumValue(Proto::Enum e) {
- switch(e) {
- case Proto::ENUM_ABC:
- // etc...
- }
-}
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithEnumValue);
-```
-
-By default, all fields will use `Arbitrary<U>()` for their values. The
-exceptions are:
-
-* `string` fields for which
- [`features.utf8_validation`](https://protobuf.dev/editions/features/#utf8_validation)
- is enabled will guarantee UTF-8 values.
-* `enum` fields will select only valid labels.
-
-Alternatively, you can use `ProtobufOf` to define a domain for
-`unique_ptr<Message>` using a protobuf prototype (the default protobuf message).
-Note that `ProtobufOf` doesn't take `const Message*` (the prototype) directly.
-It takes a *function pointer* that returns a `const Message*`. This delays
-getting the prototype until the first use:
-
-```c++
-const Message* GetMessagePrototype() {
- const std::string name = GetPrototypeNameFromFlags();
- const Descriptor* descriptor =
- DescriptorPool::generated_pool()->FindMessageTypeByName(name);
- return MessageFactory::generated_factory()->GetPrototype(descriptor);
-}
-
-void DoStuffDoesNotCrashWithMyProto(const std::unique_ptr<Message>& my_proto){
- DoStuff(my_proto);
-}
-FUZZ_TEST(MySuite, DoStuffDoesNotCrashWithMyProto)
- .WithDomains(ProtobufOf(GetMessagePrototype));
-```
-
-#### Customizing Individual Fields
-
-Each proto field has a type (i.e., int32/string) and a rule
-(optional/repeated/required). You can customize the subdomains for type, rule,
-or both.
-
-**Customizing the field type:** You can customize the subdomains for type used
-on individual fields by calling `With<Type>Field` method. Consider the following
-proto:
-
-```proto
-message Address {
- string number = 0;
- string street = 1;
- string unit = 2;
- string city = 3;
- string state = 4;
- int zipcode = 5;
-}
-
-message Person {
- optional string ldap = 2;
- enum Gender {
- UNKNOWN = 0
- FEMALE = 1,
- MALE = 2,
- OTHER = 3,
- }
- optional Gender gender = 3;
- optional Address address = 4;
-}
-```
-
-You can customize the domain for each field like the following:
-
-```c++
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
- WithDomains(Arbitrary<Person>()
- .WithStringField("ldap", StringOf(AlphaChar()))
- .WithEnumField("gender", ElementOf<int>({FEMALE, MALE, OTHER}))
- .WithProtobufField("address",
- Arbitrary<Address>()
- .WithInt32Field("zipcode", InRange(10000, 99999))
- .WithStringField("state", String().WithSize(2)))
- .WithInt32Field("my.pkg.PersonExtender.id", InRange(100000, 999999)));
-```
-
-The inner domain is as follows:
-
-* For `int32`, `int64`, `uint32`, `uint64`, `bool`, `float`, `double`, and
- `string` fields the inner domain can be any `Domain<T>` of C++ type
- `int32_t`, `int64_t`, `uint32_t`, `uint64_t`, `bool`, `float`, `double`, and
- `std::string` respectively.
-* For `enum` fields the inner domain is a `Domain<int>`. Note that values that
- are not valid enums would be stored in the unknown fields set if the field
- is a closed enum. Open enums would accept any value. The default domain for
- enum fields only chooses between valid labels.
-* For `message` fields the inner domain is a
- `Domain<std::unique_ptr<Message>>`. The domain returned by
- `Arbitrary<MyProto>()` qualifies. Note that even though it uses
- `unique_ptr`, a null value is not allowed and will trigger undefined
- behavior or a runtime assertion of some kind.
-
-The field domains are indexed by field name and will be verified at startup. A
-mismatch between the field names and the inner domains will cause a runtime
-failure. For extension fields, the full name should be used.
-
-IMPORTANT: Note that *optional* fields are not always set by the fuzzer.
-
-**Customizing the field rule:** You can customize the field rule for optional or
-repeated fields:
-
-* `WithFieldUnset` will keep the field empty.
-* `WithFieldAlwaysSet` will keep the field non-empty.
-
-```c++
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
- WithDomains(Arbitrary<MyProto>()
- .WithFieldUnset("optional_no_val")
- .WithFieldUnset("repeated_empty")
- .WithFieldAlwaysSet("optional_has_val")
- .WithFieldAlwaysSet("repeated_field_non_empty"));
-```
-
-In addition, for repeated fields, you can customize its size with
-`WithRepeatedField[Min|Max]Size`.
-
-```c++
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
- WithDomains(Arbitrary<MyProto>()
- .WithRepeatedFieldSize("size1", 1, 2)
- .WithRepeatedFieldMinSize("size_ge_2", 2)
- .WithRepeatedFieldMaxSize("size_le_3", 3));
-```
-
-**Customizing the field rule and type:** You can also customize both the rule
-and type at the same time with `With[Optional|Repeated]<Type>Field`:
-
-```c++
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
- WithDomains(Arbitrary<MyProto>()
- // Could be set or unset.
- .WithOptionalInt64Field("int", OptionalOf(InRange(1l, 10l)))
- // Is always unset.
- .WithOptionalUInt32Field("uint32", NullOpt<int32_t>())
- // Is always set.
- .WithOptionalInt32Field("int32", NonNull(OptionalOf(InRange(1, 10))))
- // Is non-empty.
- .WithRepeatedInt32Field("rep_int", VectorOf(InRange(1, 10)).WithMinSize(1))
- // Is vector of unique elements.
- .WithRepeatedInt64Field("rep_int64", UniqueElementsVectorOf(InRange(1l, 10l))));
-```
-
-For *optional* fields the domain is of the form `Domain<std::optional<Type>>`
-and for *repeated* fields the domain is of the form `Domain<std::vector<Type>>`.
-
-Also, `With<Type>FieldAlwaysSet` is a shorter alternative when one wants to
-customize non-empty fields:
-
-```c++
-// Short form for .WithOptionalInt32Field("optional_int", NonNull(InRange(1, 10)))
-.WithInt32FieldAlwaysSet("optional_int", InRange(1, 10))
-
-// Short form for .WithRepeatedInt32Field("repeated_int", VectorOf(InRange(1, 10)).WithMinSize(1))
-.WithInt32FieldAlwaysSet("repeated_int", InRange(1, 10))
-```
-
-#### Customizing a Subset of Fields
-
-You can customize the domain for a subset of fields, for example all fields with
-message type `Date`, or all fields with "amount" in the field's name.
-
-IMPORTANT: Note that customization options can conflict each other. In case of
-conflicts the latter customization always overrides the former. Moreover,
-individual field customization discussed in the previous section cannot precede
-customizations in this section.
-
-**Customizing Multiple Fields With Same Type:** You can set the domain for a
-subset of fields with the same type using `With<Type>Fields`. By default this
-applies to all fields of Type. You can also provide a filter function to select
-a subset of fields. Consider the `Moving` proto:
-
-```proto
-message Address{
- optional string line1 = 1;
- optional string line2 = 2;
- optional string city = 3;
- optional State state = 4;
- optional int32 zipcode = 5;
-}
-
-message Moving{
- optional Address from_address = 1;
- optional Address to_address = 2;
- optional google.protobuf.Timestamp start_ts = 3;
- optional google.protobuf.Timestamp deadline_ts = 4;
- optional google.protobuf.Timestamp finish_ts = 5;
- optional int32 customer_id = 6;
- optional int32 distance = 7;
- optional int32 cost_estimate = 8;
- optional int32 balance = 9;
-}
-```
-
-Most integer fields should be positive and there are multiple
-`Timestamp`/`zipcode` fields which require special domains:
-
-```c++
-
-bool IsZipCode(const FieldDescriptor* field) {
- return field->name() == "zipcode";
-}
-bool IsTimestamp(const FieldDescriptor* field){
- return field->message_type()->full_name() == "google.protobuf.Timestamp";
-}
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto)
- .WithDomains(Arbitrary<Moving>()
- // All int fields should be positive
- .WithInt32Fields(Positive<int>())
- // except balance field which can be negative
- .WithInt32Field("balance", Arbitrary<int>())
- // and except all zipcode fields which should have 5 digits
- .WithInt32Fields(IsZipcode, InRange(10000, 99999))
- // All Timestamp fields should have "nanos" field unset.
- .WithProtobufFields(IsTimestamp, Arbitrary<Timestamp>().WithFieldUnset("nanos")));
-```
-
-Notice that these filters apply recursively to nested protos as well. You can
-restrict the filter to optional or repeated fields by using
-`WithOptional<Type>Fields` or `WithRepeated<Type>Fields`, respectively.
-
-**Customizing Rules of Multiple Fields:** You can customize the nullness for a
-subset of fields using `WithFieldsAlwaysSet`, `WithFieldsUnset`, and filters:
-
-```c++
-bool IsProtoType(const FieldDescriptor* field){
- return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
-}
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
- WithDomains(Arbitrary<MyProto>()
- // Always set optional fields, and repeated fields have size > 0,
- .WithFieldsAlwaysSet()
- // except fields that contain nested protos,
- .WithFieldsUnset(IsProtoType)
- // and except "foo" field. We override the nullness by using the
- // WithOptionalInt32Filed, which will allow the fuzzer to set and unset
- // this field.
- .WithOptionalInt32Field("foo", OptionalOf(Arbitrary<int>()))
- );
-```
-
-You can restrict the filter to optional or repeated fields by using
-`WithOptionalFields[Unset|AlwaysSet]` or `WithRepeatedFields[Unset|AlwaysSet]`,
-respectively.
-
-Furthermore, you can customize repeated fields size using
-`WithRepeatedFields[Min|Max]?Size`:
-
-```c++
-bool IsChildrenOfBinaryTree(const FieldDescriptor* field){
- return field->containing_type()->full_name() == "my_package.Node"
- && field->name() == "children";
-}
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
- WithDomains(Arbitrary<MyProto>()
- // Repeated fields should have size in range 1-10
- .WithRepeatedFieldsMinSize(1)
- .WithRepeatedFieldsMaxSize(10)
- // except children of the inner nodes of a binary tree (has exactly two children).
- .WithRepeatedFieldsSize(IsChildrenOfBinaryTree, 2)
- // and except "additional_info" field which can be empty or arbitrary large
- .WithInt32Field("additional_info", VectorOf(String()))
- );
-```
-
-Warning: `With[Repeated]Fields[Unset|AlwaysSet]` will overwrite previous
-`WithRepeatedFields[Min|Max]?Size` for a given field. For example, in the
-following code, the repeated fields can have any size other than zero:
-`Arbitrary<MyProto>().WithRepeatedFieldsMinSize(2).WithRepeatedFieldsSize(2).WithFieldsAlwaysSet()`
-
-Notice that `With[Optional|Repeated]Fields[Unset|AlwaysSet]` and
-`WithRepeatedFields[Min|Max]?Size` work recursively and apply to subprotos as
-well, unless subproto domains are explicitly defined. Also, calling
-`With[Optional|Repeated]FieldsAlwaysSet` or `WithRepeatedFields[Min]?Size(X)`
-with `X > 0` on recursively defined protos causes a failure.
-
-#### Customizing Oneof Fields
-
-You can customize oneof fields similarly as other optional fields. However, the
-oneof could be unset even if you always set one of its field. Consider the
-following example:
-
-```proto
-message Algorithm{
- oneof strategy {
- string strategy_id = 1;
- int64 legacy_strategy_id = 2;
- }
-}
-```
-
-Then, you wish to customize the domain and test different non-legacy strategies.
-The following would not work because the `legacy_strategy_id` could still have
-values.
-
-```c++ {.bad}
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
- WithDomains(Arbitrary<Algorithm>()
- .WithFieldAlwaysSet("strategy_id"));
-```
-
-For oneof to always have a value, at least one of its field should be marked as
-`AlwaysSet` and the rest should be marked `Unset` (for example, when you use
-`WithFieldsAlwaysSet`). Otherwise, you need to explicitly set it by
-`WithOneofAlwaysSet`:
-
-```c++
-FUZZ_TEST(MySuite, DoingStuffDoesNotCrashWithCustomProto).
- WithDomains(Arbitrary<Algorithm>()
- .WithOneofAlwaysSet("strategy")
- .WithFieldUnset("legacy_strategy_id"));
-```
-
-## What Domains Should You Use for View Types?
-
-If your property function takes "view types", such as `std::string_view` or
-`std::span<T>`, you have multiple options.
-
-For a `std::string_view` parameter you can use `std::string` domains, such as
-`Arbitrary<std::string>()` or `InRegexp("[ab]+")`. The `string`-s created by the
-domain get implicitly converted to `string_view`-s. Alternatively, you can use
-`Arbitrary<std::string_view>()` which creates `string_view`-s in the first
-place, automatically backed by `string` values. This means that in regular
-value-parameterized unit tests,
`.WithDomains()` can be omitted:
```c++