From 7ec1c5c413cd81d11584f329af8a3cb36c9fa770 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 2 May 2018 11:41:16 -0700 Subject: [PATCH] Remove too-simple test, add tests for the variants of minmax_element --- minmax/fuzzing/minmax.fuzz.cpp | 52 ------- minmax/fuzzing/minmax_element.fuzz.cpp | 34 +++-- .../fuzzing/minmax_element_variants.fuzz.cpp | 139 ++++++++++++++++++ 3 files changed, 161 insertions(+), 64 deletions(-) delete mode 100644 minmax/fuzzing/minmax.fuzz.cpp create mode 100644 minmax/fuzzing/minmax_element_variants.fuzz.cpp diff --git a/minmax/fuzzing/minmax.fuzz.cpp b/minmax/fuzzing/minmax.fuzz.cpp deleted file mode 100644 index 06c0448..0000000 --- a/minmax/fuzzing/minmax.fuzz.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// (C) Copyright Marshall Clow 2018 -// Use, modification and distribution are subject to the -// Boost Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -// Fuzzing tests for: -// -// template -// tuple -// minmax(const T& a, const T& b); -// -// template -// tuple -// minmax(const T& a, const T& b, BinaryPredicate comp); - - -bool greater(uint8_t lhs, uint8_t rhs) { return lhs > rhs; } - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) { - typedef boost::tuple result_t; - if (sz < 2) return 0; // we only need two elements - - { - result_t result = boost::minmax(data[0], data[1]); - uint8_t const& first = result.get<0>(); - uint8_t const& second = result.get<1>(); - -// first must be <= second - if (second < first) return 1; - -// The references returned must be data[0] and data[1] - if (&first != data && &first != data + 1) return 2; - if (&second != data && &second != data + 1) return 2; - } - - { - result_t result = boost::minmax(data[0], data[1], greater); - uint8_t const& first = result.get<0>(); - uint8_t const& second = result.get<1>(); - -// first must be <= second - if (greater(second, first)) return 1; - -// The references returned must be data[0] and data[1] - if (&first != data && &first != data + 1) return 2; - if (&second != data && &second != data + 1) return 2; - } - - return 0; -} \ No newline at end of file diff --git a/minmax/fuzzing/minmax_element.fuzz.cpp b/minmax/fuzzing/minmax_element.fuzz.cpp index d2cb073..25c5570 100644 --- a/minmax/fuzzing/minmax_element.fuzz.cpp +++ b/minmax/fuzzing/minmax_element.fuzz.cpp @@ -4,8 +4,10 @@ // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include // for std::distance +#include // for assert #include +#include // Fuzzing tests for: // @@ -29,42 +31,50 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) { // Find the min and max result_t result = boost::minmax_element(data, data + sz); -// The iterators have to be in the sequence - if (std::distance(data, result.first) >= sz) return 1; - if (std::distance(data, result.second) >= sz) return 1; +// The iterators have to be in the sequence - and not at the end! + assert(std::distance(data, result.first) < sz); + assert(std::distance(data, result.second) < sz); // the minimum element can't be bigger than the max element uint8_t min_value = *result.first; uint8_t max_value = *result.second; - if (max_value < min_value) return 2; + assert(min_value <= max_value); // None of the elements in the sequence can be less than the min, nor greater than the max for (size_t i = 0; i < sz; ++i) { - if (data[i] < min_value) return 3; - if (max_value < data[i]) return 3; + assert(min_value <= data[i]); + assert(data[i] <= max_value); } + +// We returned the first min element, and the first max element + assert(boost::algorithm::none_of_equal(data, result.first, min_value)); + assert(boost::algorithm::none_of_equal(data, result.second, max_value)); } { // Find the min and max result_t result = boost::minmax_element(data, data + sz, greater); -// The iterators have to be in the sequence - if (std::distance(data, result.first) >= sz) return 1; - if (std::distance(data, result.second) >= sz) return 1; +// The iterators have to be in the sequence - and not at the end! + assert(std::distance(data, result.first) < sz); + assert(std::distance(data, result.second) < sz); // the minimum element can't be bigger than the max element uint8_t min_value = *result.first; uint8_t max_value = *result.second; - if (greater(max_value, min_value)) return 2; + assert (!greater(max_value, min_value)); // None of the elements in the sequence can be less than the min, nor greater than the max for (size_t i = 0; i < sz; ++i) { - if (greater(data[i], min_value)) return 3; - if (greater(max_value, data[i])) return 3; + assert(!greater(data[i], min_value)); + assert(!greater(max_value, data[i])); } + +// We returned the first min element, and the first max element + assert(boost::algorithm::none_of_equal(data, result.first, min_value)); + assert(boost::algorithm::none_of_equal(data, result.second, max_value)); } return 0; diff --git a/minmax/fuzzing/minmax_element_variants.fuzz.cpp b/minmax/fuzzing/minmax_element_variants.fuzz.cpp new file mode 100644 index 0000000..397a11f --- /dev/null +++ b/minmax/fuzzing/minmax_element_variants.fuzz.cpp @@ -0,0 +1,139 @@ +// (C) Copyright Marshall Clow 2018 +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include // for std::distance +#include // for assert + +#include +#include + +// Fuzzing tests for: +// +// template +// std::pair +// first_min_first_max_element(ForwardIterator first, ForwardIterator last); +// +// template +// std::pair +// first_min_first_max_element(ForwardIterator first, ForwardIterator last, +// BinaryPredicate comp); +// +// identical signatures for: +// first_min_last_max_element +// last_min_first_max_element +// last_min_last_max_element + +bool greater(uint8_t lhs, uint8_t rhs) { return lhs > rhs; } + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) { + typedef std::pair result_t; + const uint8_t * const dend = data + sz; + if (sz == 0) return 0; // we need at least one element + + { +// Find the min and max + result_t resultff = boost::first_min_first_max_element(data, dend); + result_t resultfl = boost::first_min_last_max_element (data, dend); + result_t resultlf = boost::last_min_first_max_element (data, dend); + result_t resultll = boost::last_min_last_max_element (data, dend); + +// The iterators have to be in the sequence - and not at the end! + assert(std::distance(data, resultff.first) < sz); + assert(std::distance(data, resultff.second) < sz); + assert(std::distance(data, resultfl.first) < sz); + assert(std::distance(data, resultfl.second) < sz); + assert(std::distance(data, resultlf.first) < sz); + assert(std::distance(data, resultlf.second) < sz); + assert(std::distance(data, resultll.first) < sz); + assert(std::distance(data, resultll.second) < sz); + +// the minimum element can't be bigger than the max element + +// Did we find the same min value and max value? + uint8_t min_value = *resultff.first; + uint8_t max_value = *resultff.second; + assert(min_value <= max_value); + + assert(*resultff.first == min_value); + assert(*resultfl.first == min_value); + assert(*resultlf.first == min_value); + assert(*resultll.first == min_value); + + assert(*resultff.second == max_value); + assert(*resultfl.second == max_value); + assert(*resultlf.second == max_value); + assert(*resultll.second == max_value); + +// None of the elements in the sequence can be less than the min, nor greater than the max + for (size_t i = 0; i < sz; ++i) { + assert(min_value <= data[i]); + assert(data[i] <= max_value); + } + +// Make sure we returned the "right" first and last element + assert(boost::algorithm::none_of_equal(data, resultff.first, min_value)); + assert(boost::algorithm::none_of_equal(data, resultfl.first, min_value)); + assert(boost::algorithm::none_of_equal(resultlf.first + 1, dend, min_value)); + assert(boost::algorithm::none_of_equal(resultll.first + 1, dend, min_value)); + + assert(boost::algorithm::none_of_equal(data, resultff.second, max_value)); + assert(boost::algorithm::none_of_equal(resultfl.second + 1, dend, max_value)); + assert(boost::algorithm::none_of_equal(data, resultlf.second, max_value)); + assert(boost::algorithm::none_of_equal(resultll.second + 1, dend, max_value)); + } + + { +// Find the min and max + result_t resultff = boost::first_min_first_max_element(data, dend, greater); + result_t resultfl = boost::first_min_last_max_element (data, dend, greater); + result_t resultlf = boost::last_min_first_max_element (data, dend, greater); + result_t resultll = boost::last_min_last_max_element (data, dend, greater); + +// The iterators have to be in the sequence - and not at the end! + assert(std::distance(data, resultff.first) < sz); + assert(std::distance(data, resultff.second) < sz); + assert(std::distance(data, resultfl.first) < sz); + assert(std::distance(data, resultfl.second) < sz); + assert(std::distance(data, resultlf.first) < sz); + assert(std::distance(data, resultlf.second) < sz); + assert(std::distance(data, resultll.first) < sz); + assert(std::distance(data, resultll.second) < sz); + +// the minimum element can't be bigger than the max element + uint8_t min_value = *resultff.first; + uint8_t max_value = *resultff.second; + + assert (!greater(max_value, min_value)); + + assert(*resultff.first == min_value); + assert(*resultfl.first == min_value); + assert(*resultlf.first == min_value); + assert(*resultll.first == min_value); + + assert(*resultff.second == max_value); + assert(*resultfl.second == max_value); + assert(*resultlf.second == max_value); + assert(*resultll.second == max_value); + +// None of the elements in the sequence can be less than the min, nor greater than the max + for (size_t i = 0; i < sz; ++i) { + assert(!greater(data[i], min_value)); + assert(!greater(max_value, data[i])); + } + +// We returned the first min element, and the first max element + assert(boost::algorithm::none_of_equal(data, resultff.first, min_value)); + assert(boost::algorithm::none_of_equal(data, resultfl.first, min_value)); + assert(boost::algorithm::none_of_equal(resultlf.first + 1, dend, min_value)); + assert(boost::algorithm::none_of_equal(resultll.first + 1, dend, min_value)); + + assert(boost::algorithm::none_of_equal(data, resultff.second, max_value)); + assert(boost::algorithm::none_of_equal(resultfl.second + 1, dend, max_value)); + assert(boost::algorithm::none_of_equal(data, resultlf.second, max_value)); + assert(boost::algorithm::none_of_equal(resultll.second + 1, dend, max_value)); + } + + return 0; +} \ No newline at end of file