diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index c7ef180..77a3e49 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -38,6 +38,7 @@ When using `lightweight_test.hpp`, *do not forget* to #define BOOST_TEST_NE(expr1, expr2) /*unspecified*/ #define BOOST_TEST_CSTR_EQ(expr1, expr2) /*unspecified*/ #define BOOST_TEST_CSTR_NE(expr1, expr2) /*unspecified*/ +#define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) /* unspecified */ #define BOOST_TEST_THROWS(expr, excep) /*unspecified*/ namespace boost @@ -121,6 +122,14 @@ BOOST_TEST_CSTR_NE(expr1, expr2) Specialization of BOOST_TEST_NE which interprets expr1 and expr2 as pointers to null-terminated byte strings (C strings). If `std::strcmp(expr1, expr2) == 0`, increase the error count and output a message containing both expressions. +[section BOOST_TEST_ALL_EQ] + +`` +BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) +`` + +Compares the content of two sequences. If they have different sizes, or if any pairwise element differs, increases the error count and outputs a message containing at most 8 differing elements. + [endsect] [section BOOST_TEST_THROWS] diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index d1766a4..b4b59c7 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -19,6 +19,7 @@ // http://www.boost.org/LICENSE_1_0.txt // +#include #include #include #include @@ -180,6 +181,74 @@ inline void test_cstr_ne_impl( char const * expr1, char const * expr2, } } +template +void test_all_eq_impl(FormattedOutputFunction& output, + char const * file, int line, char const * function, + InputIterator1 first_begin, InputIterator1 first_end, + InputIterator2 second_begin, InputIterator2 second_end) +{ + InputIterator1 first_it = first_begin; + InputIterator2 second_it = second_begin; + typename std::iterator_traits::difference_type first_index = 0; + typename std::iterator_traits::difference_type second_index = 0; + std::size_t error_count = 0; + const std::size_t max_count = 8; + do + { + while ((first_it != first_end) && (second_it != second_end) && (*first_it == *second_it)) + { + ++first_it; + ++second_it; + ++first_index; + ++second_index; + } + if ((first_it == first_end) || (second_it == second_end)) + { + break; // do-while + } + if (error_count == 0) + { + output << file << "(" << line << "): Container contents differ in function '" << function << "':"; + } + else if (error_count >= max_count) + { + output << " ..."; + break; + } + output << " [" << first_index << "] '" << test_output_impl(*first_it) << "' != '" << test_output_impl(*second_it) << "'"; + ++first_it; + ++second_it; + ++first_index; + ++second_index; + ++error_count; + } while (first_it != first_end); + + first_index += std::distance(first_it, first_end); + second_index += std::distance(second_it, second_end); + if (first_index != second_index) + { + if (error_count == 0) + { + output << file << "(" << line << "): Container sizes differ in function '" << function << "': size(" << first_index << ") != size(" << second_index << ")"; + } + else + { + output << " [*] size(" << first_index << ") != size(" << second_index << ")"; + } + ++error_count; + } + + if (error_count == 0) + { + boost::detail::report_errors_remind(); + } + else + { + output << std::endl; + ++boost::detail::test_errors(); + } +} + #if defined(_MSC_VER) # pragma warning(pop) #elif defined(__clang__) && defined(__has_warning) @@ -225,6 +294,8 @@ inline int report_errors() #define BOOST_TEST_CSTR_EQ(expr1,expr2) ( ::boost::detail::test_cstr_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) #define BOOST_TEST_CSTR_NE(expr1,expr2) ( ::boost::detail::test_cstr_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) +#define BOOST_TEST_ALL_EQ(begin1, end1, begin2, end2) ( ::boost::detail::test_all_eq_impl(BOOST_LIGHTWEIGHT_TEST_OSTREAM, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, begin1, end1, begin2, end2) ) + #ifndef BOOST_NO_EXCEPTIONS #define BOOST_TEST_THROWS( EXPR, EXCEP ) \ try { \ diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 31ba00f..712de26 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -65,6 +65,7 @@ run lightweight_test_test.cpp ; run lightweight_test_test.cpp : : : off : lightweight_test_test_no_except ; run lightweight_test_test2.cpp ; +run lightweight_test_all_eq_test.cpp ; run-fail lightweight_test_fail.cpp ; run-fail lightweight_test_fail2.cpp ; diff --git a/test/lightweight_test_all_eq_test.cpp b/test/lightweight_test_all_eq_test.cpp new file mode 100644 index 0000000..0fb0fb9 --- /dev/null +++ b/test/lightweight_test_all_eq_test.cpp @@ -0,0 +1,126 @@ +// +// Negative test for BOOST_TEST_ALL_EQ +// +// Copyright (c) 2017 Bjorn Reese +// +// Distributed under 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 +#include +#include + +int main() +{ + int test_cases = 0; + + // Array + + { + int x[] = { 1 }; + int y[] = { 1, 2 }; + BOOST_TEST_ALL_EQ( x, x + sizeof(x)/sizeof(x[0]), y, y + sizeof(y)/sizeof(y[0]) ); + ++test_cases; + } + + { + int x[] = { 1, 2 }; + int y[] = { 1 }; + BOOST_TEST_ALL_EQ( x, x + sizeof(x)/sizeof(x[0]), y, y + sizeof(y)/sizeof(y[0]) ); + ++test_cases; + } + + { + int x[] = { 2 }; + int y[] = { 1, 2 }; + BOOST_TEST_ALL_EQ( x, x + sizeof(x)/sizeof(x[0]), y, y + sizeof(y)/sizeof(y[0]) ); + ++test_cases; + } + + { + int x[] = { 1, 2, 3, 4 }; + int y[] = { 1, 3, 2, 4 }; + BOOST_TEST_ALL_EQ( x, x + sizeof(x)/sizeof(x[0]), y, y + sizeof(y)/sizeof(y[0]) ); + ++test_cases; + } + + // Vector + + { + std::vector x, y; + x.push_back( 1 ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::vector x, y; + y.push_back( 1 ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::vector x, y; + x.push_back( 1 ); x.push_back( 2 ); x.push_back( 3 ); x.push_back( 4 ); + y.push_back( 1 ); y.push_back( 3 ); y.push_back( 2 ); y.push_back( 4 ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::vector x, y; + x.push_back( 1.0f ); x.push_back( 2.0f ); x.push_back( 3.0f ); x.push_back( 4.0f ); + y.push_back( 4.0f ); y.push_back( 2.0f ); y.push_back( 3.0f ); y.push_back( 1.0f ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::vector x, y; + x.push_back( 1 ); x.push_back( 2 ); x.push_back( 3 ); + y.push_back( 1 ); y.push_back( 3 ); y.push_back( 2 ); y.push_back( 4 ); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::vector x, y; + x.push_back( 1 ); x.push_back( 2 ); x.push_back( 3 ); x.push_back( 4 ); + y.push_back( 1 ); y.push_back( 3 ); y.push_back( 2 );; + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + // Set + + { + std::set x, y; + x.insert(1); + y.insert(1); y.insert(3); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::set x, y; + x.insert(1); x.insert(2); + y.insert(1); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + { + std::set x, y; + x.insert(1); x.insert(2); + y.insert(1); y.insert(3); + BOOST_TEST_ALL_EQ( x.begin(), x.end(), y.begin(), y.end() ); + ++test_cases; + } + + boost::report_errors(); + + return boost::detail::test_errors() != test_cases; +} diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index a3b04a9..bfef152 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -8,6 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt // +#include #include struct X @@ -74,6 +75,15 @@ int main() BOOST_TEST_NE("xabc"+1, "yabc"+1); // equal cstrings, different addresses BOOST_TEST_CSTR_NE("x", "y"); + // BOOST_TEST_ALL_EQ + { + std::vector xarray; + xarray.push_back(1); + xarray.push_back(2); + std::vector yarray(xarray); + BOOST_TEST_ALL_EQ(xarray.begin(), xarray.end(), yarray.begin(), yarray.end()); + } + // BOOST_TEST_THROWS BOOST_TEST_THROWS( throw X(), X );