First draft
diff --git a/doctest/doctest.h b/doctest/doctest.h
index 71b7d1c..9629181 100644
--- a/doctest/doctest.h
+++ b/doctest/doctest.h
@@ -904,16 +904,6 @@
DOCTEST_INTERFACE std::ostream* tlssPush();
DOCTEST_INTERFACE String tlssPop();
-
- template <bool C>
- struct StringMakerBase
- {
- template <typename T>
- static String convert(const DOCTEST_REF_WRAP(T)) {
- return "{?}";
- }
- };
-
// Vector<int> and various type other than pointer or array.
template<typename T>
struct filldata
@@ -923,22 +913,29 @@
}
};
- template<typename T,unsigned long N>
+ template<typename T, unsigned long N>
struct filldata<T[N]>
{
static void fill(std::ostream* stream, const T (&in)[N]) {
+ *stream << "[";
for (unsigned long i = 0; i < N; i++) {
+ if (i != 0) { *stream << ", "; }
*stream << in[i];
}
+ *stream << "]";
}
};
+ // "forward declaration" for ostream::write
+ DOCTEST_INTERFACE void writeChars(std::ostream* stream, const char* cstr, unsigned long count);
+
// Specialized since we don't want the terminating null byte!
template<unsigned long N>
struct filldata<const char[N]>
{
static void fill(std::ostream* stream, const char(&in)[N]) {
- *stream << in;
+ // Cut off 0 byte if null-terminated
+ writeChars(stream, in, in[N-1] == '\0' ? N-1 : N);
}
};
@@ -947,31 +944,13 @@
filldata<T>::fill(stream, in);
}
- template<typename T,unsigned long N>
+ template<typename T, unsigned long N>
void filloss(std::ostream* stream, const T (&in)[N]) {
// T[N], T(&)[N], T(&&)[N] have same behaviour.
// Hence remove reference.
filldata<typename remove_reference<decltype(in)>::type>::fill(stream, in);
}
- template <>
- struct StringMakerBase<true>
- {
- template <typename T>
- static String convert(const DOCTEST_REF_WRAP(T) in) {
- /* When parameter "in" is a null terminated const char* it works.
- * When parameter "in" is a T arr[N] without '\0' we can fill the
- * stringstream with N objects (T=char).If in is char pointer *
- * without '\0' , it would cause segfault
- * stepping over unaccessible memory.
- */
-
- std::ostream* stream = tlssPush();
- filloss(stream, in);
- return tlssPop();
- }
- };
-
DOCTEST_INTERFACE String rawMemoryToString(const void* object, unsigned size);
template <typename T>
@@ -985,34 +964,65 @@
}
} // namespace detail
-template <typename T>
-struct StringMaker : public detail::StringMakerBase<detail::has_insertion_operator<T>::value>
-{};
+namespace detail {
+ template <bool C>
+ struct StringStreamBase
+ {
+ template <typename T>
+ static void convert(std::ostream* s, const T&) {
+ *s << "{?}";
+ }
-template <typename T>
-struct StringMaker<T*>
-{
- template <typename U>
- static String convert(U* p) {
- if(p)
- return detail::rawMemoryToString(p);
- return "NULL";
- }
-};
+ // always treat char* as a string in this context - no matter
+ // if DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING is defined
+ static void convert(std::ostream* s, const char* in) { *s << String(in); }
+ };
-template <typename R, typename C>
-struct StringMaker<R C::*>
-{
- static String convert(R C::*p) {
- if(p)
- return detail::rawMemoryToString(p);
- return "NULL";
+ template <>
+ struct StringStreamBase<true>
+ {
+ template <typename T>
+ static void convert(std::ostream* s, const T& in) {
+ filloss(s, in);
+ }
+ };
+
+ template <typename T>
+ struct StringStream : public StringStreamBase<has_insertion_operator<T>::value>
+ {};
+
+ template <typename T>
+ void toStream(std::ostream* s, const T& value) {
+ StringStream<T>::convert(s, value);
}
-};
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char* in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, const char* in);
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ DOCTEST_INTERFACE void toStream(std::ostream* s, bool in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, float in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, double in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, double long in);
+
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char signed in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int short in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int short unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in);
+}
template <typename T, typename detail::enable_if<!detail::is_enum<T>::value, bool>::type = true>
String toString(const DOCTEST_REF_WRAP(T) value) {
- return StringMaker<T>::convert(value);
+ std::ostream* stream = detail::tlssPush();
+ detail::toStream(stream, value);
+ return detail::tlssPop();
}
#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
@@ -1664,58 +1674,6 @@
DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et);
- template <bool C>
- struct StringStreamBase
- {
- template <typename T>
- static void convert(std::ostream* s, const T& in) {
- *s << toString(in);
- }
-
- // always treat char* as a string in this context - no matter
- // if DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING is defined
- static void convert(std::ostream* s, const char* in) { *s << String(in); }
- };
-
- template <>
- struct StringStreamBase<true>
- {
- template <typename T>
- static void convert(std::ostream* s, const T& in) {
- *s << in;
- }
- };
-
- template <typename T>
- struct StringStream : public StringStreamBase<has_insertion_operator<T>::value>
- {};
-
- template <typename T>
- void toStream(std::ostream* s, const T& value) {
- StringStream<T>::convert(s, value);
- }
-
-#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- DOCTEST_INTERFACE void toStream(std::ostream* s, char* in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, const char* in);
-#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- DOCTEST_INTERFACE void toStream(std::ostream* s, bool in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, float in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, double in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, double long in);
-
- DOCTEST_INTERFACE void toStream(std::ostream* s, char in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, char signed in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, char unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int short in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int short unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in);
-
// ContextScope base class used to allow implementing methods of ContextScope
// that don't depend on the template parameter in doctest.cpp.
class DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
@@ -3195,6 +3153,10 @@
} // namespace
namespace detail {
+ void writeChars(std::ostream* stream, const char* cstr, unsigned long count) {
+ stream->write(cstr, count);
+ }
+
String rawMemoryToString(const void* object, unsigned size) {
// Reverse order for little endian architectures
int i = 0, end = static_cast<int>(size), inc = 1;
diff --git a/doctest/parts/doctest.cpp b/doctest/parts/doctest.cpp
index 30ac73b..945c596 100644
--- a/doctest/parts/doctest.cpp
+++ b/doctest/parts/doctest.cpp
@@ -235,6 +235,10 @@
} // namespace
namespace detail {
+ void writeChars(std::ostream* stream, const char* cstr, unsigned long count) {
+ stream->write(cstr, count);
+ }
+
String rawMemoryToString(const void* object, unsigned size) {
// Reverse order for little endian architectures
int i = 0, end = static_cast<int>(size), inc = 1;
diff --git a/doctest/parts/doctest_fwd.h b/doctest/parts/doctest_fwd.h
index e326947..af74b63 100644
--- a/doctest/parts/doctest_fwd.h
+++ b/doctest/parts/doctest_fwd.h
@@ -901,16 +901,6 @@
DOCTEST_INTERFACE std::ostream* tlssPush();
DOCTEST_INTERFACE String tlssPop();
-
- template <bool C>
- struct StringMakerBase
- {
- template <typename T>
- static String convert(const DOCTEST_REF_WRAP(T)) {
- return "{?}";
- }
- };
-
// Vector<int> and various type other than pointer or array.
template<typename T>
struct filldata
@@ -920,22 +910,29 @@
}
};
- template<typename T,unsigned long N>
+ template<typename T, unsigned long N>
struct filldata<T[N]>
{
static void fill(std::ostream* stream, const T (&in)[N]) {
+ *stream << "[";
for (unsigned long i = 0; i < N; i++) {
+ if (i != 0) { *stream << ", "; }
*stream << in[i];
}
+ *stream << "]";
}
};
+ // "forward declaration" for ostream::write
+ DOCTEST_INTERFACE void writeChars(std::ostream* stream, const char* cstr, unsigned long count);
+
// Specialized since we don't want the terminating null byte!
template<unsigned long N>
struct filldata<const char[N]>
{
static void fill(std::ostream* stream, const char(&in)[N]) {
- *stream << in;
+ // Cut off 0 byte if null-terminated
+ writeChars(stream, in, in[N-1] == '\0' ? N-1 : N);
}
};
@@ -944,31 +941,13 @@
filldata<T>::fill(stream, in);
}
- template<typename T,unsigned long N>
+ template<typename T, unsigned long N>
void filloss(std::ostream* stream, const T (&in)[N]) {
// T[N], T(&)[N], T(&&)[N] have same behaviour.
// Hence remove reference.
filldata<typename remove_reference<decltype(in)>::type>::fill(stream, in);
}
- template <>
- struct StringMakerBase<true>
- {
- template <typename T>
- static String convert(const DOCTEST_REF_WRAP(T) in) {
- /* When parameter "in" is a null terminated const char* it works.
- * When parameter "in" is a T arr[N] without '\0' we can fill the
- * stringstream with N objects (T=char).If in is char pointer *
- * without '\0' , it would cause segfault
- * stepping over unaccessible memory.
- */
-
- std::ostream* stream = tlssPush();
- filloss(stream, in);
- return tlssPop();
- }
- };
-
DOCTEST_INTERFACE String rawMemoryToString(const void* object, unsigned size);
template <typename T>
@@ -982,34 +961,65 @@
}
} // namespace detail
-template <typename T>
-struct StringMaker : public detail::StringMakerBase<detail::has_insertion_operator<T>::value>
-{};
+namespace detail {
+ template <bool C>
+ struct StringStreamBase
+ {
+ template <typename T>
+ static void convert(std::ostream* s, const T&) {
+ *s << "{?}";
+ }
-template <typename T>
-struct StringMaker<T*>
-{
- template <typename U>
- static String convert(U* p) {
- if(p)
- return detail::rawMemoryToString(p);
- return "NULL";
- }
-};
+ // always treat char* as a string in this context - no matter
+ // if DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING is defined
+ static void convert(std::ostream* s, const char* in) { *s << String(in); }
+ };
-template <typename R, typename C>
-struct StringMaker<R C::*>
-{
- static String convert(R C::*p) {
- if(p)
- return detail::rawMemoryToString(p);
- return "NULL";
+ template <>
+ struct StringStreamBase<true>
+ {
+ template <typename T>
+ static void convert(std::ostream* s, const T& in) {
+ filloss(s, in);
+ }
+ };
+
+ template <typename T>
+ struct StringStream : public StringStreamBase<has_insertion_operator<T>::value>
+ {};
+
+ template <typename T>
+ void toStream(std::ostream* s, const T& value) {
+ StringStream<T>::convert(s, value);
}
-};
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char* in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, const char* in);
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ DOCTEST_INTERFACE void toStream(std::ostream* s, bool in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, float in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, double in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, double long in);
+
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char signed in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int short in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int short unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in);
+}
template <typename T, typename detail::enable_if<!detail::is_enum<T>::value, bool>::type = true>
String toString(const DOCTEST_REF_WRAP(T) value) {
- return StringMaker<T>::convert(value);
+ std::ostream* stream = detail::tlssPush();
+ detail::toStream(stream, value);
+ return detail::tlssPop();
}
#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
@@ -1661,58 +1671,6 @@
DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et);
- template <bool C>
- struct StringStreamBase
- {
- template <typename T>
- static void convert(std::ostream* s, const T& in) {
- *s << toString(in);
- }
-
- // always treat char* as a string in this context - no matter
- // if DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING is defined
- static void convert(std::ostream* s, const char* in) { *s << String(in); }
- };
-
- template <>
- struct StringStreamBase<true>
- {
- template <typename T>
- static void convert(std::ostream* s, const T& in) {
- *s << in;
- }
- };
-
- template <typename T>
- struct StringStream : public StringStreamBase<has_insertion_operator<T>::value>
- {};
-
- template <typename T>
- void toStream(std::ostream* s, const T& value) {
- StringStream<T>::convert(s, value);
- }
-
-#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- DOCTEST_INTERFACE void toStream(std::ostream* s, char* in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, const char* in);
-#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- DOCTEST_INTERFACE void toStream(std::ostream* s, bool in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, float in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, double in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, double long in);
-
- DOCTEST_INTERFACE void toStream(std::ostream* s, char in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, char signed in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, char unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int short in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int short unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in);
-
// ContextScope base class used to allow implementing methods of ContextScope
// that don't depend on the template parameter in doctest.cpp.
class DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
diff --git a/examples/all_features/stringification.cpp b/examples/all_features/stringification.cpp
index adca1e7..8c0ce48 100644
--- a/examples/all_features/stringification.cpp
+++ b/examples/all_features/stringification.cpp
@@ -2,6 +2,17 @@
#include "header.h"
+TEST_CASE("no headers") {
+ char chs1[] = { '1', 'a', 's' };
+ MESSAGE(chs1); CHECK(chs1 == nullptr);
+ const char* chs2{"1as"};
+ MESSAGE(chs2); CHECK(chs2 == nullptr);
+ MESSAGE("1as"); CHECK("1as" == nullptr);
+
+ int ints[] = { 0, 1, 1, 2, 3, 5, 8, 13 };
+ MESSAGE(ints); CHECK(ints == nullptr);
+}
+
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <string>
#include <vector>
@@ -18,34 +29,31 @@
template <typename T>
ostream& operator<<(ostream& stream, const vector<T>& in) {
stream << "[";
- for(size_t i = 0; i < in.size(); ++i)
- if(i < in.size() - 1)
- stream << in[i] << ", ";
- else
- stream << in[i];
+ for (size_t i = 0; i < in.size(); ++i) {
+ if (i != 0) { stream << ", "; }
+ stream << in[i];
+ }
stream << "]";
return stream;
}
}
// as an alternative you may write a specialization of doctest::StringMaker
-namespace doctest
-{
+namespace doctest
+{ namespace detail {
template <typename T>
-struct StringMaker<std::list<T> >
+struct StringStream<std::list<T>>
{
- static String convert(const std::list<T>& in) {
- std::ostringstream oss;
-
- oss << "[";
- for(typename std::list<T>::const_iterator it = in.begin(); it != in.end(); ++it)
- oss << *it << ", ";
- oss << "]";
-
- return oss.str().c_str();
+ static void convert(std::ostream* s, const std::list<T>& in) {
+ *s << "[";
+ for (typename std::list<T>::const_iterator it = in.begin(); it != in.end();) {
+ *s << *it;
+ if (++it != in.end()) { *s << ", "; }
+ }
+ *s << "]";
}
};
-}
+} }
template <typename T, typename K>
struct MyType
@@ -76,8 +84,10 @@
friend bool operator==(const Foo&, const Foo&) { return false; }
};
-// as a third option you may provide an overload of toString()
-inline doctest::String toString(const Foo&) { return "Foo{}"; }
+std::ostream& operator<<(std::ostream& stream, const Bar::Foo&) {
+ stream << "Foo{}";
+ return stream;
+}
struct MyOtherType
{
@@ -106,12 +116,15 @@
bla1.two = 4u;
Bar::Foo f1;
+ MESSAGE(f1);
Bar::Foo f2;
CHECK(f1 == f2);
// std::string already has an operator<< working with std::ostream
std::string dummy = "omg";
+ MESSAGE(dummy);
+
CHECK(dummy == "tralala"); // should fail
CHECK("tralala" == dummy); // should fail
@@ -120,6 +133,8 @@
vec1.push_back(2);
vec1.push_back(3);
+ MESSAGE(vec1);
+
std::vector<int> vec2;
vec2.push_back(1);
vec2.push_back(2);
@@ -132,6 +147,8 @@
lst_1.push_back(42);
lst_1.push_back(3);
+ MESSAGE(lst_1);
+
std::list<int> lst_2;
lst_2.push_back(1);
lst_2.push_back(2);
diff --git a/examples/all_features/test_output/filter_2.txt b/examples/all_features/test_output/filter_2.txt
index 662a7e2..8618276 100644
--- a/examples/all_features/test_output/filter_2.txt
+++ b/examples/all_features/test_output/filter_2.txt
@@ -1,6 +1,6 @@
[doctest] run with "--help" for options
===============================================================================
-[doctest] test cases: 0 | 0 passed | 0 failed | 96 skipped
+[doctest] test cases: 0 | 0 passed | 0 failed | 97 skipped
[doctest] assertions: 0 | 0 passed | 0 failed |
[doctest] Status: SUCCESS!
Program code.
diff --git a/examples/all_features/test_output/filter_2_xml.txt b/examples/all_features/test_output/filter_2_xml.txt
index 8764a89..b1342f9 100644
--- a/examples/all_features/test_output/filter_2_xml.txt
+++ b/examples/all_features/test_output/filter_2_xml.txt
@@ -90,6 +90,7 @@
<TestCase name="namespace 8 friend vs global" filename="namespace8.cpp" line="0" skipped="true"/>
<TestCase name="namespace 9 both global" filename="namespace9.cpp" line="0" skipped="true"/>
<TestCase name="no checks" filename="no_failures.cpp" line="0" skipped="true"/>
+ <TestCase name="no headers" filename="stringification.cpp" line="0" skipped="true"/>
<TestCase name="normal macros" filename="assertion_macros.cpp" line="0" skipped="true"/>
</TestSuite>
<TestSuite name="ts1">
@@ -136,6 +137,6 @@
<TestCase name="will end from an unknown exception" filename="coverage_maxout.cpp" line="0" skipped="true"/>
</TestSuite>
<OverallResultsAsserts successes="0" failures="0"/>
- <OverallResultsTestCases successes="0" failures="0" skipped="96"/>
+ <OverallResultsTestCases successes="0" failures="0" skipped="97"/>
</doctest>
Program code.
diff --git a/examples/all_features/test_output/stringification.cpp.txt b/examples/all_features/test_output/stringification.cpp.txt
index 234e806..18f8bca 100644
--- a/examples/all_features/test_output/stringification.cpp.txt
+++ b/examples/all_features/test_output/stringification.cpp.txt
@@ -1,22 +1,54 @@
[doctest] run with "--help" for options
===============================================================================
stringification.cpp(0):
+TEST CASE: no headers
+
+stringification.cpp(0): MESSAGE: 1as
+
+stringification.cpp(0): ERROR: CHECK( chs1 == nullptr ) is NOT correct!
+ values: CHECK( 1as == NULL )
+
+stringification.cpp(0): MESSAGE: 1as
+
+stringification.cpp(0): ERROR: CHECK( chs2 == nullptr ) is NOT correct!
+ values: CHECK( 1as == NULL )
+
+stringification.cpp(0): MESSAGE: 1as
+
+stringification.cpp(0): ERROR: CHECK( "1as" == nullptr ) is NOT correct!
+ values: CHECK( 1as == NULL )
+
+stringification.cpp(0): MESSAGE: [0, 1, 1, 2, 3, 5, 8, 13]
+
+stringification.cpp(0): ERROR: CHECK( ints == nullptr ) is NOT correct!
+ values: CHECK( [0, 1, 1, 2, 3, 5, 8, 13] == NULL )
+
+===============================================================================
+stringification.cpp(0):
TEST CASE: all asserts should fail and show how the objects get stringified
+stringification.cpp(0): MESSAGE: Foo{}
+
stringification.cpp(0): ERROR: CHECK( f1 == f2 ) is NOT correct!
values: CHECK( Foo{} == Foo{} )
+stringification.cpp(0): MESSAGE: omg
+
stringification.cpp(0): ERROR: CHECK( dummy == "tralala" ) is NOT correct!
values: CHECK( omg == tralala )
stringification.cpp(0): ERROR: CHECK( "tralala" == dummy ) is NOT correct!
values: CHECK( tralala == omg )
+stringification.cpp(0): MESSAGE: [1, 2, 3]
+
stringification.cpp(0): ERROR: CHECK( vec1 == vec2 ) is NOT correct!
values: CHECK( [1, 2, 3] == [1, 2, 4] )
+stringification.cpp(0): MESSAGE: [1, 42, 3]
+
stringification.cpp(0): ERROR: CHECK( lst_1 == lst_2 ) is NOT correct!
- values: CHECK( [1, 42, 3, ] == [1, 2, 666, ] )
+ values: CHECK( [1, 42, 3] == [1, 2, 666] )
stringification.cpp(0): ERROR: CHECK( s1 == s2 ) is NOT correct!
values: CHECK( MyOtherType: 42 == MyOtherType: 666 )
@@ -42,7 +74,7 @@
stringification.cpp(0): ERROR: test case THREW exception: 5
===============================================================================
-[doctest] test cases: 2 | 0 passed | 2 failed |
-[doctest] assertions: 9 | 0 passed | 9 failed |
+[doctest] test cases: 3 | 0 passed | 3 failed |
+[doctest] assertions: 13 | 0 passed | 13 failed |
[doctest] Status: FAILURE!
Program code.
diff --git a/examples/all_features/test_output/stringification.cpp_junit.txt b/examples/all_features/test_output/stringification.cpp_junit.txt
index a5e39dc..1b2f7f0 100644
--- a/examples/all_features/test_output/stringification.cpp_junit.txt
+++ b/examples/all_features/test_output/stringification.cpp_junit.txt
@@ -1,6 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
- <testsuite name="all_features" errors="2" failures="9" tests="9">
+ <testsuite name="all_features" errors="2" failures="13" tests="13">
+ <testcase classname="stringification.cpp" name="no headers" status="run">
+ <failure message="1as == NULL" type="CHECK">
+stringification.cpp(0):
+CHECK( chs1 == nullptr ) is NOT correct!
+ values: CHECK( 1as == NULL )
+
+ </failure>
+ <failure message="1as == NULL" type="CHECK">
+stringification.cpp(0):
+CHECK( chs2 == nullptr ) is NOT correct!
+ values: CHECK( 1as == NULL )
+
+ </failure>
+ <failure message="1as == NULL" type="CHECK">
+stringification.cpp(0):
+CHECK( "1as" == nullptr ) is NOT correct!
+ values: CHECK( 1as == NULL )
+
+ </failure>
+ <failure message="[0, 1, 1, 2, 3, 5, 8, 13] == NULL" type="CHECK">
+stringification.cpp(0):
+CHECK( ints == nullptr ) is NOT correct!
+ values: CHECK( [0, 1, 1, 2, 3, 5, 8, 13] == NULL )
+
+ </failure>
+ </testcase>
<testcase classname="stringification.cpp" name="all asserts should fail and show how the objects get stringified" status="run">
<failure message="Foo{} == Foo{}" type="CHECK">
stringification.cpp(0):
@@ -26,10 +52,10 @@
values: CHECK( [1, 2, 3] == [1, 2, 4] )
</failure>
- <failure message="[1, 42, 3, ] == [1, 2, 666, ]" type="CHECK">
+ <failure message="[1, 42, 3] == [1, 2, 666]" type="CHECK">
stringification.cpp(0):
CHECK( lst_1 == lst_2 ) is NOT correct!
- values: CHECK( [1, 42, 3, ] == [1, 2, 666, ] )
+ values: CHECK( [1, 42, 3] == [1, 2, 666] )
</failure>
<failure message="MyOtherType: 42 == MyOtherType: 666" type="CHECK">
diff --git a/examples/all_features/test_output/stringification.cpp_xml.txt b/examples/all_features/test_output/stringification.cpp_xml.txt
index 67f6c96..d703781 100644
--- a/examples/all_features/test_output/stringification.cpp_xml.txt
+++ b/examples/all_features/test_output/stringification.cpp_xml.txt
@@ -2,7 +2,67 @@
<doctest binary="all_features">
<Options order_by="file" rand_seed="324" first="0" last="4294967295" abort_after="0" subcase_filter_levels="2147483647" case_sensitive="false" no_throw="false" no_skip="false"/>
<TestSuite>
+ <TestCase name="no headers" filename="stringification.cpp" line="0">
+ <Message type="WARNING" filename="stringification.cpp" line="0">
+ <Text>
+ 1as
+ </Text>
+ </Message>
+ <Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
+ <Original>
+ chs1 == nullptr
+ </Original>
+ <Expanded>
+ 1as == NULL
+ </Expanded>
+ </Expression>
+ <Message type="WARNING" filename="stringification.cpp" line="0">
+ <Text>
+ 1as
+ </Text>
+ </Message>
+ <Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
+ <Original>
+ chs2 == nullptr
+ </Original>
+ <Expanded>
+ 1as == NULL
+ </Expanded>
+ </Expression>
+ <Message type="WARNING" filename="stringification.cpp" line="0">
+ <Text>
+ 1as
+ </Text>
+ </Message>
+ <Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
+ <Original>
+ "1as" == nullptr
+ </Original>
+ <Expanded>
+ 1as == NULL
+ </Expanded>
+ </Expression>
+ <Message type="WARNING" filename="stringification.cpp" line="0">
+ <Text>
+ [0, 1, 1, 2, 3, 5, 8, 13]
+ </Text>
+ </Message>
+ <Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
+ <Original>
+ ints == nullptr
+ </Original>
+ <Expanded>
+ [0, 1, 1, 2, 3, 5, 8, 13] == NULL
+ </Expanded>
+ </Expression>
+ <OverallResultsAsserts successes="0" failures="4" test_case_success="false"/>
+ </TestCase>
<TestCase name="all asserts should fail and show how the objects get stringified" filename="stringification.cpp" line="0">
+ <Message type="WARNING" filename="stringification.cpp" line="0">
+ <Text>
+ Foo{}
+ </Text>
+ </Message>
<Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
<Original>
f1 == f2
@@ -11,6 +71,11 @@
Foo{} == Foo{}
</Expanded>
</Expression>
+ <Message type="WARNING" filename="stringification.cpp" line="0">
+ <Text>
+ omg
+ </Text>
+ </Message>
<Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
<Original>
dummy == "tralala"
@@ -27,6 +92,11 @@
tralala == omg
</Expanded>
</Expression>
+ <Message type="WARNING" filename="stringification.cpp" line="0">
+ <Text>
+ [1, 2, 3]
+ </Text>
+ </Message>
<Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
<Original>
vec1 == vec2
@@ -35,12 +105,17 @@
[1, 2, 3] == [1, 2, 4]
</Expanded>
</Expression>
+ <Message type="WARNING" filename="stringification.cpp" line="0">
+ <Text>
+ [1, 42, 3]
+ </Text>
+ </Message>
<Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
<Original>
lst_1 == lst_2
</Original>
<Expanded>
- [1, 42, 3, ] == [1, 2, 666, ]
+ [1, 42, 3] == [1, 2, 666]
</Expanded>
</Expression>
<Expression success="false" type="CHECK" filename="stringification.cpp" line="0">
@@ -96,7 +171,7 @@
<OverallResultsAsserts successes="0" failures="0" test_case_success="false"/>
</TestCase>
</TestSuite>
- <OverallResultsAsserts successes="0" failures="9"/>
- <OverallResultsTestCases successes="0" failures="2"/>
+ <OverallResultsAsserts successes="0" failures="13"/>
+ <OverallResultsTestCases successes="0" failures="3"/>
</doctest>
Program code.
diff --git a/scripts/coverage_maxout.cpp b/scripts/coverage_maxout.cpp
index 8b6e574..2530089 100644
--- a/scripts/coverage_maxout.cpp
+++ b/scripts/coverage_maxout.cpp
@@ -77,21 +77,6 @@
std::ostringstream oss;
- // toStream
- detail::toStream(&oss, true);
- detail::toStream(&oss, 0.5f);
- detail::toStream(&oss, 0.5);
- detail::toStream(&oss, static_cast<long double>(0.1));
- detail::toStream(&oss, 'c');
- detail::toStream(&oss, static_cast<signed char>('c'));
- detail::toStream(&oss, static_cast<unsigned char>(1));
- detail::toStream(&oss, static_cast<short>(1));
- detail::toStream(&oss, static_cast<long>(1));
- detail::toStream(&oss, static_cast<unsigned long>(1));
- detail::toStream(&oss, static_cast<unsigned short>(1));
- detail::toStream(&oss, static_cast<long long>(1));
- detail::toStream(&oss, static_cast<unsigned long long>(1));
-
// trigger code path for String to ostream through operator<<
oss << str;
// trigger code path for assert string of a non-existent assert type
@@ -102,8 +87,8 @@
#endif
str += oss.str().c_str();
str += failureString(assertType::is_normal);
- CHECK(str == "omgomgomgaaaNULLtrue00.5f0.50.199991111111true0.50.50.1cc"
- "111111omgomgomgaaaNULLtrue00.5f0.50.199991111111");
+ CHECK(str == "omgomgomgaaaNULLtrue00.5f0.50.199991111111"
+ "omgomgomgaaaNULLtrue00.5f0.50.199991111111");
// trigger code path for rawMemoryToString
bool isThereAnything = str.size() > 0u;
bool len_is_zero = detail::rawMemoryToString(isThereAnything).size() == 0u;