chromium/third_party/libavif/src/tests/gtest/avif_fuzztest_helpers.h

// Copyright 2022 Google LLC
// SPDX-License-Identifier: BSD-2-Clause

#ifndef LIBAVIF_TESTS_OSS_FUZZ_AVIF_FUZZTEST_HELPERS_H_
#define LIBAVIF_TESTS_OSS_FUZZ_AVIF_FUZZTEST_HELPERS_H_

#include <cstdint>
#include <cstdlib>
#include <vector>

#include "avif/avif.h"
#include "aviftest_helpers.h"
#include "avifutil.h"
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"

namespace avif {
namespace testutil {

//------------------------------------------------------------------------------
// C++ wrapper for scoped memory management of C API objects.

// Exposed for convenient fuzztest reproducer output.
ImagePtr CreateAvifImage8b(size_t width, size_t height,
                           avifPixelFormat pixel_format, bool has_alpha,
                           const std::vector<uint8_t>& samples);
ImagePtr CreateAvifImage16b(size_t width, size_t height, int depth,
                            avifPixelFormat pixel_format, bool has_alpha,
                            const std::vector<uint16_t>& samples);
std::vector<ImagePtr> CreateAvifAnim8b(size_t num_frames, size_t width,
                                       size_t height,
                                       avifPixelFormat pixel_format,
                                       bool has_alpha,
                                       const std::vector<uint8_t>& samples);
std::vector<ImagePtr> CreateAvifAnim16b(size_t num_frames, size_t width,
                                        size_t height, int depth,
                                        avifPixelFormat pixel_format,
                                        bool has_alpha,
                                        const std::vector<uint16_t>& samples);
EncoderPtr CreateAvifEncoder(avifCodecChoice codec_choice, int max_threads,
                             int min_quantizer, int max_quantizer,
                             int min_quantizer_alpha, int max_quantizer_alpha,
                             int tile_rows_log2, int tile_cols_log2, int speed);
DecoderPtr CreateAvifDecoder(avifCodecChoice codec_choice, int max_threads,
                             avifDecoderSource requested_source,
                             bool allow_progressive, bool allow_incremental,
                             bool ignore_exif, bool ignore_xmp,
                             uint32_t image_size_limit,
                             uint32_t image_dimension_limit,
                             uint32_t image_count_limit,
                             avifStrictFlags strict_flags);
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
enum class GainMapDecodeMode {};
DecoderPtr AddGainMapOptionsToDecoder(DecoderPtr decoder,
                                      GainMapDecodeMode gain_map_decode_mode);
#endif

//------------------------------------------------------------------------------
// Custom fuzztest generators.
// See https://github.com/google/fuzztest/blob/main/doc/domains-reference.md.

// Do not generate images wider or taller than this.
inline constexpr size_t kMaxDimension =;  // In pixels.

// Used to reduce kMaxDimension to keep the same complexity as a still image.
inline constexpr size_t kMaxNumFramesSquareRoot =;
// Do not generate animations with more than this number of frames.
inline constexpr size_t kMaxNumFrames =;

size_t GetNumSamples(size_t num_frames, size_t width, size_t height,
                     avifPixelFormat pixel_format, bool has_alpha);

// To avoid using fuzztest::internal, the return type of the functions below is
// auto.

inline auto ArbitraryPixelFormat() {}

// avifImage generator type: Width, height, pixel format and 8-bit samples.
inline auto ArbitraryAvifImage8b() {}

// avifImage generator type: Width, height, depth, pixel format and 16-bit
// samples.
inline auto ArbitraryAvifImage16b() {}

// avifImage generator type: Number of frames, width, height, pixel format and
// 8-bit samples.
inline auto ArbitraryAvifAnim8b() {}

// avifImage generator type: Number of frames, width, height, depth, pixel
// format and 16-bit samples.
inline auto ArbitraryAvifAnim16b() {}

// Generator for an arbitrary ImagePtr.
inline auto ArbitraryAvifImage() {}

// Generator for an arbitrary std::vector<ImagePtr>.
inline auto ArbitraryAvifAnim() {}

// Generator for an arbitrary EncoderPtr.
inline auto ArbitraryAvifEncoder() {}

// Generator for an arbitrary DecoderPtr with base options fuzzed (i.e.
// without "experimental" options hidden behind compile flags).
inline auto ArbitraryBaseAvifDecoder() {}

#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
// Generator for an arbitrary DecoderPtr with base options and gain map
// options fuzzed, with the exception of 'ignoreColorAndAlpha' (because it would
// break most tests' assumptions).
inline auto ArbitraryAvifDecoderWithGainMapOptions() {}

// Generator for an arbitrary DecoderPtr.
inline auto ArbitraryAvifDecoder() {}
#else
// Generator for an arbitrary DecoderPtr.
inline auto ArbitraryAvifDecoder() { return ArbitraryBaseAvifDecoder(); }
#endif  // AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP

//------------------------------------------------------------------------------
// Environment setup

// Sets the environment variable 'name' to the 'value' during the setup step.
::testing::Environment* SetEnv(const char* name, const char* value);

inline ::testing::Environment* SetStackLimitTo512x1024Bytes() {}

//------------------------------------------------------------------------------

// Returns the paths contained in the 'TEST_DATA_DIRS' environment variable.
// Several paths can be set in the variable, separated by ';'.
// Returns nullptr if not set.
// Tests that use ArbitraryImageWithSeeds() should
// ASSERT_FALSE(GetSeedDataDirs().empty()) if they want to make sure that seeds
// are actually used.
std::vector<std::string> GetSeedDataDirs();

// Returns a list of test images contents (not paths) from the directory set in
// the 'TEST_DATA_DIRS' environment variable, that are smaller than
// 'max_file_size' and have one of the formats in 'image_formats' (or any format
// if 'image_formats' is empty).
// If TEST_DATA_DIRS is not set, returns an empty set.
// Tests that use this should ASSERT_FALSE(GetSeedDataDirs().empty())
// if they want to make sure that seeds are actually used.
// Terminates the program with abort() if TEST_DATA_DIRS is set but doesn't
// contain any matching images.
std::vector<std::string> GetTestImagesContents(
    size_t max_file_size, const std::vector<avifAppFileFormat>& image_formats);

// Generator for an arbitrary ImagePtr that uses test image files as seeds.
// Uses the 'TEST_DATA_DIRS' environment variable to load the seeds.
// If TEST_DATA_DIRS is not set, no seeds are used.
// Tests that use this should ASSERT_FALSE(GetSeedDataDirs().empty())
// if they want to make sure that seeds are actually used.
// Terminates the program with abort() if TEST_DATA_DIRS is set but doesn't
// contain any matching images.
inline auto ArbitraryImageWithSeeds(
    const std::vector<avifAppFileFormat>& image_formats) {}

//------------------------------------------------------------------------------

}  // namespace testutil
}  // namespace avif

#endif  // LIBAVIF_TESTS_OSS_FUZZ_AVIF_FUZZTEST_HELPERS_H_