chromium/third_party/fuzztest/src/fuzztest/internal/domains/domain_base.h

// 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_