From cdee8e76c506f68d4493a6d3062944d46ce78600 Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Sun, 5 Feb 2017 19:06:21 +0000 Subject: [PATCH 1/8] fix for trac issue #12814, including a new test for the issue --- include/boost/core/lightweight_test.hpp | 37 +++++++++++++++++++++++++ test/lightweight_test_test.cpp | 5 ++++ 2 files changed, 42 insertions(+) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index d6db024..e084b35 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -23,6 +23,7 @@ #include #include #include +#include // IDE's like Visual Studio perform better if output goes to std::cout or // some other stream, so allow user to configure output stream: @@ -118,6 +119,24 @@ template inline void test_eq_impl( char const * expr1, char co } } +// overload for const char* +inline void test_eq_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const char* t, const char* u ) +{ + if( std::strcmp(t, u) == 0 ) + { + report_errors_remind(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test '" << expr1 << " == " << expr2 + << "' failed in function '" << function << "': " + << "'" << t << "' != '" << u << "'" << std::endl; + ++test_errors(); + } +} + template inline void test_ne_impl( char const * expr1, char const * expr2, char const * file, int line, char const * function, T const & t, U const & u ) { @@ -135,6 +154,24 @@ template inline void test_ne_impl( char const * expr1, char co } } +// overload for const char* +inline void test_ne_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const char* t, const char* u ) +{ + if( std::strcmp(t, u) != 0 ) + { + report_errors_remind(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test '" << expr1 << " == " << expr2 + << "' failed in function '" << function << "': " + << "'" << t << "' == '" << u << "'" << std::endl; + ++test_errors(); + } +} + #if defined(_MSC_VER) # pragma warning(pop) #elif defined(__clang__) && defined(__has_warning) diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index d4808a1..be87950 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -65,10 +65,15 @@ int main() BOOST_TEST_EQ( ++x, ++y ); BOOST_TEST_EQ( x++, y++ ); + const char* s1 = "abc"; // make sure addresses are different + const char* s2 = "abc"; // make sure addresses are different + BOOST_TEST_EQ(s1, s2); + // BOOST_TEST_NE BOOST_TEST_NE( ++x, y ); BOOST_TEST_NE( &x, &y ); + BOOST_TEST_NE( "abc", "ABC" ); // BOOST_TEST_THROWS From 7774d33e45a774c0c5659da550790d7705cf5862 Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Sun, 5 Feb 2017 19:24:15 +0000 Subject: [PATCH 2/8] really make sure addresses are different --- test/lightweight_test_test.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index be87950..a38d9d2 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -65,9 +65,7 @@ int main() BOOST_TEST_EQ( ++x, ++y ); BOOST_TEST_EQ( x++, y++ ); - const char* s1 = "abc"; // make sure addresses are different - const char* s2 = "abc"; // make sure addresses are different - BOOST_TEST_EQ(s1, s2); + BOOST_TEST_EQ("abc", "xxxabc"+3); // make sure addresses are different // BOOST_TEST_NE From 3942e9c0974e8435b6d12de4fe2695e691423ab1 Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Sun, 5 Feb 2017 20:01:47 +0000 Subject: [PATCH 3/8] following pdimovs suggestion to avoid folding --- test/lightweight_test_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index a38d9d2..a2c5971 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -65,7 +65,7 @@ int main() BOOST_TEST_EQ( ++x, ++y ); BOOST_TEST_EQ( x++, y++ ); - BOOST_TEST_EQ("abc", "xxxabc"+3); // make sure addresses are different + BOOST_TEST_EQ("xabc"+1, "yabc"+1); // make sure addresses are different // BOOST_TEST_NE From cc5472623f05ca8c37b7aea14687c8393efcd92a Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Mon, 6 Feb 2017 20:08:43 +0000 Subject: [PATCH 4/8] compare pointers as addresses and use BOOST_TEST_CSTR_xx to compare cstrings --- include/boost/core/lightweight_test.hpp | 51 ++++++++++++++++++++++--- test/lightweight_test_test.cpp | 7 ++-- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index e084b35..2608582 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -119,9 +119,27 @@ template inline void test_eq_impl( char const * expr1, char co } } -// overload for const char* -inline void test_eq_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const char* t, const char* u ) +// overloads for pointers compare and print addresses +template inline void test_eq_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const T* const t, const U* const u ) +{ + if( t == u ) + { + report_errors_remind(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test '" << expr1 << " == " << expr2 + << "' failed in function '" << function << "': " + << "'" << (const void*)t << "' != '" << (const void*)u << "'" << std::endl; + ++test_errors(); + } +} + +// impl for cstring +inline void test_cstr_eq_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const char* const t, const char* const u ) { if( std::strcmp(t, u) == 0 ) { @@ -154,9 +172,27 @@ template inline void test_ne_impl( char const * expr1, char co } } -// overload for const char* -inline void test_ne_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const char* t, const char* u ) +// overloads for pointers compare and print addresses +template inline void test_ne_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const T* const t, const U* const u ) +{ + if( t != u ) + { + report_errors_remind(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test '" << expr1 << " == " << expr2 + << "' failed in function '" << function << "': " + << "'" << (const void*)t << "' == '" << (const void*)u << "'" << std::endl; + ++test_errors(); + } +} + +// impl for cstring +inline void test_cstr_ne_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, const char* const t, const char* const u ) { if( std::strcmp(t, u) != 0 ) { @@ -214,6 +250,9 @@ inline int report_errors() #define BOOST_TEST_EQ(expr1,expr2) ( ::boost::detail::test_eq_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) #define BOOST_TEST_NE(expr1,expr2) ( ::boost::detail::test_ne_impl(#expr1, #expr2, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, expr1, expr2) ) +#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) ) + #ifndef BOOST_NO_EXCEPTIONS #define BOOST_TEST_THROWS( EXPR, EXCEP ) \ try { \ diff --git a/test/lightweight_test_test.cpp b/test/lightweight_test_test.cpp index a2c5971..a3b04a9 100644 --- a/test/lightweight_test_test.cpp +++ b/test/lightweight_test_test.cpp @@ -64,14 +64,15 @@ int main() BOOST_TEST_EQ( ++x, ++y ); BOOST_TEST_EQ( x++, y++ ); - - BOOST_TEST_EQ("xabc"+1, "yabc"+1); // make sure addresses are different + BOOST_TEST_CSTR_EQ("xabc"+1, "yabc"+1); // equal cstrings, different addresses + BOOST_TEST_EQ( &y, &y ); // BOOST_TEST_NE BOOST_TEST_NE( ++x, y ); BOOST_TEST_NE( &x, &y ); - BOOST_TEST_NE( "abc", "ABC" ); + BOOST_TEST_NE("xabc"+1, "yabc"+1); // equal cstrings, different addresses + BOOST_TEST_CSTR_NE("x", "y"); // BOOST_TEST_THROWS From 4570cced275ae36261634a4a23d1fb66873b124e Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Tue, 7 Feb 2017 15:05:08 +0000 Subject: [PATCH 5/8] more compared code following suggestion from Glen Fernandes and testing expected failures --- include/boost/core/lightweight_test.hpp | 58 ++++++------------------- test/Jamfile.v2 | 2 + test/lightweight_test_fail10.cpp | 18 ++++++++ test/lightweight_test_fail9.cpp | 18 ++++++++ 4 files changed, 51 insertions(+), 45 deletions(-) create mode 100644 test/lightweight_test_fail10.cpp create mode 100644 test/lightweight_test_fail9.cpp diff --git a/include/boost/core/lightweight_test.hpp b/include/boost/core/lightweight_test.hpp index 2608582..804c8f4 100644 --- a/include/boost/core/lightweight_test.hpp +++ b/include/boost/core/lightweight_test.hpp @@ -102,6 +102,12 @@ inline void throw_failed_impl(char const * excep, char const * file, int line, c # pragma GCC diagnostic ignored "-Wsign-compare" #endif +// specialize test output for char pointers to avoid printing as cstring +template inline const T& test_output_impl(const T& v) { return v; } +inline const void* test_output_impl(const char* v) { return v; } +inline const void* test_output_impl(const unsigned char* v) { return v; } +inline const void* test_output_impl(const signed char* v) { return v; } + template inline void test_eq_impl( char const * expr1, char const * expr2, char const * file, int line, char const * function, T const & t, U const & u ) { @@ -114,43 +120,7 @@ template inline void test_eq_impl( char const * expr1, char co BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): test '" << expr1 << " == " << expr2 << "' failed in function '" << function << "': " - << "'" << t << "' != '" << u << "'" << std::endl; - ++test_errors(); - } -} - -// overloads for pointers compare and print addresses -template inline void test_eq_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const T* const t, const U* const u ) -{ - if( t == u ) - { - report_errors_remind(); - } - else - { - BOOST_LIGHTWEIGHT_TEST_OSTREAM - << file << "(" << line << "): test '" << expr1 << " == " << expr2 - << "' failed in function '" << function << "': " - << "'" << (const void*)t << "' != '" << (const void*)u << "'" << std::endl; - ++test_errors(); - } -} - -// impl for cstring -inline void test_cstr_eq_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const char* const t, const char* const u ) -{ - if( std::strcmp(t, u) == 0 ) - { - report_errors_remind(); - } - else - { - BOOST_LIGHTWEIGHT_TEST_OSTREAM - << file << "(" << line << "): test '" << expr1 << " == " << expr2 - << "' failed in function '" << function << "': " - << "'" << t << "' != '" << u << "'" << std::endl; + << "'" << test_output_impl(t) << "' != '" << test_output_impl(u) << "'" << std::endl; ++test_errors(); } } @@ -167,16 +137,15 @@ template inline void test_ne_impl( char const * expr1, char co BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): test '" << expr1 << " != " << expr2 << "' failed in function '" << function << "': " - << "'" << t << "' == '" << u << "'" << std::endl; + << "'" << test_output_impl(t) << "' == '" << test_output_impl(u) << "'" << std::endl; ++test_errors(); } } -// overloads for pointers compare and print addresses -template inline void test_ne_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const T* const t, const U* const u ) +inline void test_cstr_eq_impl( char const * expr1, char const * expr2, + char const * file, int line, char const * function, char const * const t, char const * const u ) { - if( t != u ) + if( std::strcmp(t, u) == 0 ) { report_errors_remind(); } @@ -185,14 +154,13 @@ template inline void test_ne_impl( char const * expr1, char co BOOST_LIGHTWEIGHT_TEST_OSTREAM << file << "(" << line << "): test '" << expr1 << " == " << expr2 << "' failed in function '" << function << "': " - << "'" << (const void*)t << "' == '" << (const void*)u << "'" << std::endl; + << "'" << t << "' != '" << u << "'" << std::endl; ++test_errors(); } } -// impl for cstring inline void test_cstr_ne_impl( char const * expr1, char const * expr2, - char const * file, int line, char const * function, const char* const t, const char* const u ) + char const * file, int line, char const * function, char const * const t, char const * const u ) { if( std::strcmp(t, u) != 0 ) { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f93ff51..31ba00f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -76,6 +76,8 @@ run-fail lightweight_test_fail7.cpp ; run-fail lightweight_test_fail7.cpp : : : off : lightweight_test_fail7_no_rtti ; run-fail lightweight_test_fail8.cpp ; run-fail lightweight_test_fail8.cpp : : : off : lightweight_test_fail8_no_rtti ; +run-fail lightweight_test_fail9.cpp ; +run-fail lightweight_test_fail10.cpp ; run is_same_test.cpp ; diff --git a/test/lightweight_test_fail10.cpp b/test/lightweight_test_fail10.cpp new file mode 100644 index 0000000..388c47e --- /dev/null +++ b/test/lightweight_test_fail10.cpp @@ -0,0 +1,18 @@ +// +// Negative test for BOOST_TEST_EQ on const char* +// +// Copyright (c) 2017 Hans Dembinski +// +// 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 + +int main() +{ + BOOST_TEST_EQ("xab"+1 , "yab"+1); // compares addresses, not cstrings + + return boost::report_errors(); +} diff --git a/test/lightweight_test_fail9.cpp b/test/lightweight_test_fail9.cpp new file mode 100644 index 0000000..a87a4f1 --- /dev/null +++ b/test/lightweight_test_fail9.cpp @@ -0,0 +1,18 @@ +// +// Negative test for BOOST_TEST_CSTR_EQ +// +// Copyright (c) 2017 Hans Dembinski +// +// 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 + +int main() +{ + BOOST_TEST_CSTR_EQ("x" , "y"); + + return boost::report_errors(); +} From 7038296c157b6e5a284b6eb944275eb1b025943f Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Thu, 9 Feb 2017 12:47:47 +0000 Subject: [PATCH 6/8] build fix --- doc/Jamfile.v2 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index f598bb7..bdba059 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -5,8 +5,9 @@ # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://boost.org/LICENSE_1_0.txt) -import doxygen ; -import quickbook ; +using boostbook ; +using doxygen ; +using quickbook ; doxygen ref_reference : From fe137b97c3ed63ea25f3b9e112cf6fe71b24ab11 Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Thu, 9 Feb 2017 12:48:06 +0000 Subject: [PATCH 7/8] adding documentation for new test macros --- doc/lightweight_test.qbk | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index 4b9abd1..c7ef180 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -36,6 +36,8 @@ When using `lightweight_test.hpp`, *do not forget* to #define BOOST_ERROR(message) /*unspecified*/ #define BOOST_TEST_EQ(expr1, expr2) /*unspecified*/ #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_THROWS(expr, excep) /*unspecified*/ namespace boost @@ -101,6 +103,26 @@ message containing both expressions. [endsect] +[section BOOST_TEST_CSTR_EQ] + +`` +BOOST_TEST_CSTR_EQ(expr1, expr2) +`` + +Specialization of BOOST_TEST_EQ 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. + +[endsect] + +[section BOOST_TEST_CSTR_NE] + +`` +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. + +[endsect] + [section BOOST_TEST_THROWS] `` From b59a3df4c4c7d50003be2dc8126c602649f82c3d Mon Sep 17 00:00:00 2001 From: "hans.dembinski@gmail.com" Date: Thu, 9 Feb 2017 13:52:33 +0000 Subject: [PATCH 8/8] reverting changes to jamfile --- doc/Jamfile.v2 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index bdba059..f598bb7 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -5,9 +5,8 @@ # Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://boost.org/LICENSE_1_0.txt) -using boostbook ; -using doxygen ; -using quickbook ; +import doxygen ; +import quickbook ; doxygen ref_reference :