Skip to content

Commit

Permalink
Allow for several directories in TEST_DATA_DIR
Browse files Browse the repository at this point in the history
  • Loading branch information
vrabaud committed Dec 1, 2023
1 parent b1e92f1 commit bbeb59c
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 36 deletions.
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ if(AVIF_ENABLE_FUZZTEST)
target_link_libraries(${TEST_NAME} PRIVATE aviftest_helpers ${ARGN})
link_fuzztest(${TEST_NAME})
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT "TEST_DATA_DIR=${CMAKE_CURRENT_SOURCE_DIR}/data/")
set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT "TEST_DATA_DIRS=${CMAKE_CURRENT_SOURCE_DIR}/data/")
endmacro()

if(AVIF_LOCAL_FUZZTEST)
Expand Down
2 changes: 1 addition & 1 deletion tests/gtest/avif_fuzztest_dec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ ::testing::Environment* const kStackLimitEnv = SetStackLimitTo512x1024Bytes();
//------------------------------------------------------------------------------

void Decode(const std::string& arbitrary_bytes, DecoderPtr decoder) {
ASSERT_NE(GetSeedDataDir(), nullptr); // Make sure seeds are available.
ASSERT_FALSE(GetSeedDataDirs().empty()); // Make sure seeds are available.

ImagePtr decoded(avifImageCreateEmpty());
ASSERT_NE(decoded, nullptr);
Expand Down
2 changes: 1 addition & 1 deletion tests/gtest/avif_fuzztest_dec_incr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ avifResult AvifIoRead(struct avifIO* io, uint32_t read_flags, uint64_t offset,

void DecodeIncr(const std::string& arbitrary_bytes, bool is_persistent,
bool give_size_hint, bool use_nth_image_api) {
ASSERT_NE(GetSeedDataDir(), nullptr); // Make sure seeds are available.
ASSERT_FALSE(GetSeedDataDirs().empty()); // Make sure seeds are available.

ImagePtr reference(avifImageCreateEmpty());
ASSERT_NE(reference.get(), nullptr);
Expand Down
57 changes: 37 additions & 20 deletions tests/gtest/avif_fuzztest_helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -213,43 +213,60 @@ ::testing::Environment* SetEnv(const char* name, const char* value) {

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

const char* GetSeedDataDir() { return std::getenv("TEST_DATA_DIR"); }
std::vector<std::string> GetSeedDataDirs() {
const char* var = std::getenv("TEST_DATA_DIRS");
std::vector<std::string> res;
if (var == nullptr || *var == 0) return res;
const char* var_start = var;
while (true) {
if (*var == 0 || *var == ';') {
res.push_back(std::string(var_start, var - var_start));
if (*var == 0) break;
var_start = var + 1;
}
++var;
}
return res;
}

std::vector<std::string> GetTestImagesContents(
size_t max_file_size, const std::vector<avifAppFileFormat>& image_formats) {
// Use an environment variable to get the test data directory because
// fuzztest seeds are created before the main() function is called, so the
// test has no chance to parse command line arguments.
const char* const test_data_dir = GetSeedDataDir();
if (test_data_dir == nullptr) {
const std ::vector<std::string> test_data_dirs = GetSeedDataDirs();
if (test_data_dirs.empty()) {
// Only a warning because this can happen when running the binary with
// --list_fuzz_tests (such as with gtest_discover_tests() in cmake).
std::cerr << "WARNING: TEST_DATA_DIR env variable not set, unable to read "
std::cerr << "WARNING: TEST_DATA_DIRS env variable not set, unable to read "
"seed files";
return {};
}

std::cout << "Reading seeds from " << test_data_dir << " (non recursively)\n";
auto tuple_vector = fuzztest::ReadFilesFromDirectory(test_data_dir);
std::vector<std::string> seeds;
seeds.reserve(tuple_vector.size());
for (auto& [file_content] : tuple_vector) {
if (file_content.size() > max_file_size) continue;
if (!image_formats.empty()) {
const avifAppFileFormat format = avifGuessBufferFileFormat(
reinterpret_cast<const uint8_t*>(file_content.data()),
file_content.size());
if (std::find(image_formats.begin(), image_formats.end(), format) ==
image_formats.end()) {
continue;
for (const std::string& test_data_dir : test_data_dirs) {
std::cout << "Reading seeds from " << test_data_dir
<< " (non recursively)\n";
auto tuple_vector = fuzztest::ReadFilesFromDirectory(test_data_dir);
seeds.reserve(tuple_vector.size());
for (auto& [file_content] : tuple_vector) {
if (file_content.size() > max_file_size) continue;
if (!image_formats.empty()) {
const avifAppFileFormat format = avifGuessBufferFileFormat(
reinterpret_cast<const uint8_t*>(file_content.data()),
file_content.size());
if (std::find(image_formats.begin(), image_formats.end(), format) ==
image_formats.end()) {
continue;
}
}
}

seeds.push_back(std::move(file_content));
seeds.push_back(std::move(file_content));
}
}
if (seeds.empty()) {
std::cerr << "ERROR: no files found in " << test_data_dir
<< " that match the given file size and format criteria\n";
std::cerr << "ERROR: no files found that match the given file size and "
"format criteria\n";
std::abort();
}
std::cout << "Returning " << seeds.size() << " seed images\n";
Expand Down
25 changes: 13 additions & 12 deletions tests/gtest/avif_fuzztest_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,31 +195,32 @@ inline ::testing::Environment* SetStackLimitTo512x1024Bytes() {

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

// Returns the value of the 'TEST_DATA_DIR' environment variable.
// 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_NE(GetSeedDataDir(), nullptr) if they want to make sure that seeds are
// actually used.
const char* GetSeedDataDir();
// 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_DIR' environment variable, that are smaller than
// 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_DIR is not set, returns an empty set.
// Tests that use this should ASSERT_NE(GetSeedDataDir(), nullptr)
// 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_DIR is set but doesn't
// 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_DIR' environment variable to load the seeds.
// If TEST_DATA_DIR is not set, no seeds are used.
// Tests that use this should ASSERT_NE(GetSeedDataDir(), nullptr)
// 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_DIR is set but doesn't
// 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) {
Expand Down
2 changes: 1 addition & 1 deletion tests/gtest/avif_fuzztest_read_image.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void ReadImageFile(const std::string& arbitrary_bytes,
bool ignore_color_profile, bool ignore_exif, bool ignore_xmp,
bool allow_changing_cicp, bool ignore_gain_map,
avifMatrixCoefficients matrix_coefficients) {
ASSERT_NE(GetSeedDataDir(), nullptr); // Make sure seeds are available.
ASSERT_FALSE(GetSeedDataDirs().empty()); // Make sure seeds are available.

// Write the byte stream to a temp file since avifReadImage() takes a file
// path as input.
Expand Down

0 comments on commit bbeb59c

Please sign in to comment.