From bbeb59cd5e50aadcef58f0b4deb81f6d8eaad8e6 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Fri, 1 Dec 2023 13:42:04 +0100 Subject: [PATCH] Allow for several directories in TEST_DATA_DIR --- tests/CMakeLists.txt | 2 +- tests/gtest/avif_fuzztest_dec.cc | 2 +- tests/gtest/avif_fuzztest_dec_incr.cc | 2 +- tests/gtest/avif_fuzztest_helpers.cc | 57 ++++++++++++++++--------- tests/gtest/avif_fuzztest_helpers.h | 25 +++++------ tests/gtest/avif_fuzztest_read_image.cc | 2 +- 6 files changed, 54 insertions(+), 36 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d174e0536c..14b88e1c6b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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) diff --git a/tests/gtest/avif_fuzztest_dec.cc b/tests/gtest/avif_fuzztest_dec.cc index 13a3b541bd..2935c716c1 100644 --- a/tests/gtest/avif_fuzztest_dec.cc +++ b/tests/gtest/avif_fuzztest_dec.cc @@ -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); diff --git a/tests/gtest/avif_fuzztest_dec_incr.cc b/tests/gtest/avif_fuzztest_dec_incr.cc index 14a339a2f2..7b54f67c0a 100644 --- a/tests/gtest/avif_fuzztest_dec_incr.cc +++ b/tests/gtest/avif_fuzztest_dec_incr.cc @@ -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); diff --git a/tests/gtest/avif_fuzztest_helpers.cc b/tests/gtest/avif_fuzztest_helpers.cc index d5d8338a31..e55094b3e8 100644 --- a/tests/gtest/avif_fuzztest_helpers.cc +++ b/tests/gtest/avif_fuzztest_helpers.cc @@ -213,43 +213,60 @@ ::testing::Environment* SetEnv(const char* name, const char* value) { //------------------------------------------------------------------------------ -const char* GetSeedDataDir() { return std::getenv("TEST_DATA_DIR"); } +std::vector GetSeedDataDirs() { + const char* var = std::getenv("TEST_DATA_DIRS"); + std::vector 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 GetTestImagesContents( size_t max_file_size, const std::vector& 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 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 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(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(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"; diff --git a/tests/gtest/avif_fuzztest_helpers.h b/tests/gtest/avif_fuzztest_helpers.h index 268b4e2be9..0e0628473b 100644 --- a/tests/gtest/avif_fuzztest_helpers.h +++ b/tests/gtest/avif_fuzztest_helpers.h @@ -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 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 GetTestImagesContents( size_t max_file_size, const std::vector& 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& image_formats) { diff --git a/tests/gtest/avif_fuzztest_read_image.cc b/tests/gtest/avif_fuzztest_read_image.cc index c13ce8fd3a..2e920db23f 100644 --- a/tests/gtest/avif_fuzztest_read_image.cc +++ b/tests/gtest/avif_fuzztest_read_image.cc @@ -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.