diff --git a/format.cc b/format.cc index 77227589..2abbab8c 100644 --- a/format.cc +++ b/format.cc @@ -158,7 +158,7 @@ typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef); // Buffer should be at least of size 1. int safe_strerror( int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { - assert(buffer != 0 && buffer_size != 0); + FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer"); class StrError { private: diff --git a/format.h b/format.h index eed9a8ca..9440bcbe 100644 --- a/format.h +++ b/format.h @@ -175,6 +175,10 @@ inline uint32_t clzll(uint64_t x) { TypeName& operator=(const TypeName&) #endif +#ifndef FMT_ASSERT +# define FMT_ASSERT(condition, message) assert((condition) && message) +#endif + namespace fmt { // Fix the warning about long long on older versions of GCC @@ -1081,7 +1085,7 @@ class ArgVisitor { Result visit(const Arg &arg) { switch (arg.type) { default: - assert(false); + FMT_ASSERT(false, "invalid argument type"); return Result(); case Arg::INT: return FMT_DISPATCH(visit_int(arg.int_value)); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ed827d16..8c90504d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,6 +22,7 @@ if (HAVE_ENUM_BASE) add_definitions(-DFMT_USE_ENUM_BASE=1) endif () +add_fmt_test(assert-test) add_fmt_test(gtest-extra-test) add_fmt_test(format-test) if (FMT_PEDANTIC AND MSVC) diff --git a/test/assert-test.cc b/test/assert-test.cc new file mode 100644 index 00000000..e81f088a --- /dev/null +++ b/test/assert-test.cc @@ -0,0 +1,41 @@ +/* + Assertion tests + + Copyright (c) 2015, Victor Zverovich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "format.h" +#include "gtest/gtest.h" + +#if GTEST_HAS_DEATH_TEST +# define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEBUG_DEATH(statement, regex) +#else +# define EXPECT_DEBUG_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +#endif + +TEST(AssertTest, Fail) { + EXPECT_DEBUG_DEATH_IF_SUPPORTED(FMT_ASSERT(false, "don't panic!"), "don't panic!"); +} diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index fdf1ac07..d4a03c4c 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -25,6 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "test-assert.h" + // Include format.cc instead of format.h to test implementation-specific stuff. #include "format.cc" @@ -55,10 +57,8 @@ TEST(FormatTest, FormatNegativeNaN) { TEST(FormatTest, StrError) { char *message = 0; char buffer[BUFFER_SIZE]; -#ifndef NDEBUG - EXPECT_DEBUG_DEATH(fmt::safe_strerror(EDOM, message = 0, 0), "Assertion"); - EXPECT_DEBUG_DEATH(fmt::safe_strerror(EDOM, message = buffer, 0), "Assertion"); -#endif + EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = 0, 0), "invalid buffer"); + EXPECT_ASSERT(fmt::safe_strerror(EDOM, message = buffer, 0), "invalid buffer"); buffer[0] = 'x'; #ifdef _GNU_SOURCE // Use invalid error code to make sure that safe_strerror returns an error diff --git a/test/gtest-extra-test.cc b/test/gtest-extra-test.cc index 3ba219a5..6d8918b3 100644 --- a/test/gtest-extra-test.cc +++ b/test/gtest-extra-test.cc @@ -525,7 +525,7 @@ TEST(BufferedFileTest, CloseError) { TEST(BufferedFileTest, Fileno) { BufferedFile f; // fileno on a null FILE pointer either crashes or returns an error. - EXPECT_DEATH({ + EXPECT_DEATH_IF_SUPPORTED({ try { f.fileno(); } catch (fmt::SystemError) { diff --git a/test/test-assert.h b/test/test-assert.h new file mode 100644 index 00000000..549cde3b --- /dev/null +++ b/test/test-assert.h @@ -0,0 +1,42 @@ +/* + Test version of FMT_ASSERT + + Copyright (c) 2015, Victor Zverovich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FMT_TEST_ASSERT_H +#define FMT_TEST_ASSERT_H + +#include + +static std::string last_assert; + +#define FMT_ASSERT(condition, message) \ + if (!(condition)) last_assert = message; + +// Expects an assertion failure. +#define EXPECT_ASSERT(stmt, message) \ + { last_assert = ""; stmt; EXPECT_EQ(last_assert, message); } + +#endif // FMT_TEST_ASSERT_H diff --git a/test/util-test.cc b/test/util-test.cc index 3723a0b1..be50bc5c 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -25,6 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "test-assert.h" + #include #include #include @@ -680,7 +682,7 @@ TEST(ArgVisitorTest, VisitUnhandledArg) { TEST(ArgVisitorTest, VisitInvalidArg) { Arg arg = Arg(); arg.type = static_cast(Arg::CUSTOM + 1); - EXPECT_DEBUG_DEATH(TestVisitor().visit(arg), "Assertion"); + EXPECT_ASSERT(TestVisitor().visit(arg), "invalid argument type"); } // Tests fmt::internal::count_digits for integer type Int.