// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // IWYU pragma: private, include "fuzztest/fuzztest.h" // IWYU pragma: friend fuzztest/.* #ifndef FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_DOMAIN_BASE_H_ #define FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_DOMAIN_BASE_H_ #include <cstdint> #include <cstdlib> #include <functional> #include <iostream> #include <optional> #include <type_traits> #include <vector> #include "absl/random/bit_gen_ref.h" #include "absl/random/distributions.h" #include "absl/status/status.h" #include "absl/strings/str_format.h" #include "./fuzztest/internal/domains/domain_type_erasure.h" #include "./fuzztest/internal/meta.h" #include "./fuzztest/internal/printer.h" #include "./fuzztest/internal/serialization.h" #include "./fuzztest/internal/table_of_recent_compares.h" #include "./fuzztest/internal/type_support.h" namespace fuzztest::internal { void DestabilizeBitGen(absl::BitGenRef bitgen); } // namespace fuzztest::internal namespace fuzztest::domain_implementor { // `DomainBase` is the base class for all domain implementations. // // The type parameters are as follows: // // - `Derived`: Instead of virtual inheritance, the domain hierarchy uses the // Curiously Recurring Template Pattern (CRTP). A class `X` deriving from // `DomainBase` needs to instantiate the template with `Derived = X`. // - `ValueType`: The type of the user-facing values the domain represents. // If the deriving class is itself a template parameterized by its user value // type (as the first type parameter), you may omit this parameter. // - `CorpusType`: The type of the corpus values that the domain implementation // uses internally. Typically this is the same as `ValueType` (which is the // default), but sometimes the domain may need to maintain different or // additional information to be able to efficiently perform value mutation. // // The domain implementation can access `ValueType` and `CorpusType` through // the type members `DomainBase::value_type` and `DomainBase::corpus_type`. // // To implement a domain, a deriving class should implement at least the // following methods. See the documentation of the interface class `Domain<T>` // for a detailed description of each method. // // - corpus_type Init(absl::BitGenRef prng) // // The method that returns an initial value. To support seeding, this function // may first call `MaybeGetRandomSeed()` and return its non-nullopt result. // TODO(b/303324603): Move the call to `MaybeGetRandomSeed()` to a wrapper. // // - void Mutate(corpus_type& val, absl::BitGenRef prng, bool only_shrink) // // The method that mutates the corpus value. // // - absl::Status ValidateCorpusValue(const corpus_type& val) const // // The method to validate that the corpus value satisfies the domain's // constraints. // // - auto GetPrinter() const // // The method that returns the domain's printer---a class that provides one of // the following two methods for printing user/corpus values. // TODO(b/303324603): Add more documentation about printers. // // void PrintUserValue(const value_type& val, // RawSink out, // PrintMode mode) const // // void PrintCorpusValue(const corpus_type& val, // RawSink out, // PrintMode mode) const // // In addition, if the domain has a custom `CorpusType`, it will need to // override (by shadowing) the methods `GetValue()`, `FromValue()`, // `ParseCorpus()`, and `SerializeCorpus()`. See the default implementations of // these methods below. template <typename Derived, typename ValueType = fuzztest::internal::ExtractTemplateParameter<0, Derived>, typename CorpusType = ValueType> class DomainBase { … }; } // namespace fuzztest::domain_implementor #endif // FUZZTEST_FUZZTEST_INTERNAL_DOMAINS_DOMAIN_BASE_H_