Skip to content

Commit

Permalink
Add tests for DOCTEST_CONFIG_USE_STD_HEADERS (doctest#643)
Browse files Browse the repository at this point in the history
* Add std headers

* Fix and suppress warnings

* Use new-style cast

* More fixes to weird ambiguities

* Fix MSVC

* Try fix ancient GCC

* Fix fix

* Add missing `typename`

* Adjust docs

* Test remove enums.cpp

* Readd tests

* Fix assert count
  • Loading branch information
Saalvage authored May 2, 2022
1 parent 499a0fd commit 94b52bb
Show file tree
Hide file tree
Showing 11 changed files with 1,025 additions and 72 deletions.
36 changes: 21 additions & 15 deletions doctest/doctest.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,9 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP

// this is kept here for backwards compatibility since the config option was changed
#ifdef DOCTEST_CONFIG_USE_IOSFWD
#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
#define DOCTEST_CONFIG_USE_STD_HEADERS
#endif
#endif // DOCTEST_CONFIG_USE_IOSFWD

// for clang - always include ciso646 (which drags some std stuff) because
Expand All @@ -465,17 +467,21 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP
#if DOCTEST_CLANG
#include <ciso646>
#ifdef _LIBCPP_VERSION
#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
#define DOCTEST_CONFIG_USE_STD_HEADERS
#endif
#endif // _LIBCPP_VERSION
#endif // clang

#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <cstddef>
#include <ostream>
#include <istream>
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
#else // DOCTEST_CONFIG_USE_STD_HEADERS

// Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
Expand Down Expand Up @@ -6195,7 +6201,7 @@ namespace {
// log the preamble of the test case only if there is something
// else to print - something other than that an assert has failed
if(opt.duration ||
(st.failure_flags && st.failure_flags != TestCaseFailureReason::AssertFailure))
(st.failure_flags && st.failure_flags != static_cast<int>(TestCaseFailureReason::AssertFailure)))
logTestStart();

if(opt.duration)
Expand Down Expand Up @@ -6446,30 +6452,30 @@ namespace {
if(!parseOption(argc, argv, pattern, &parsedValue))
return false;

if(type == 0) {
if(type) {
// integer
// TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
int theInt = std::atoi(parsedValue.c_str()); // NOLINT
if (theInt != 0) {
res = theInt; //!OCLINT parameter reassignment
return true;
}
} else {
// boolean
const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1
const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1
const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1
const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1

// if the value matches any of the positive/negative possibilities
for(unsigned i = 0; i < 4; i++) {
if(parsedValue.compare(positive[i], true) == 0) {
for (unsigned i = 0; i < 4; i++) {
if (parsedValue.compare(positive[i], true) == 0) {
res = 1; //!OCLINT parameter reassignment
return true;
}
if(parsedValue.compare(negative[i], true) == 0) {
if (parsedValue.compare(negative[i], true) == 0) {
res = 0; //!OCLINT parameter reassignment
return true;
}
}
} else {
// integer
// TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
int theInt = std::atoi(parsedValue.c_str()); // NOLINT
if(theInt != 0) {
res = theInt; //!OCLINT parameter reassignment
return true;
}
}
return false;
}
Expand Down
30 changes: 15 additions & 15 deletions doctest/parts/doctest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3194,7 +3194,7 @@ namespace {
// log the preamble of the test case only if there is something
// else to print - something other than that an assert has failed
if(opt.duration ||
(st.failure_flags && st.failure_flags != TestCaseFailureReason::AssertFailure))
(st.failure_flags && st.failure_flags != static_cast<int>(TestCaseFailureReason::AssertFailure)))
logTestStart();

if(opt.duration)
Expand Down Expand Up @@ -3445,30 +3445,30 @@ namespace {
if(!parseOption(argc, argv, pattern, &parsedValue))
return false;

if(type == 0) {
if(type) {
// integer
// TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
int theInt = std::atoi(parsedValue.c_str()); // NOLINT
if (theInt != 0) {
res = theInt; //!OCLINT parameter reassignment
return true;
}
} else {
// boolean
const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1
const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1
const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1
const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1

// if the value matches any of the positive/negative possibilities
for(unsigned i = 0; i < 4; i++) {
if(parsedValue.compare(positive[i], true) == 0) {
for (unsigned i = 0; i < 4; i++) {
if (parsedValue.compare(positive[i], true) == 0) {
res = 1; //!OCLINT parameter reassignment
return true;
}
if(parsedValue.compare(negative[i], true) == 0) {
if (parsedValue.compare(negative[i], true) == 0) {
res = 0; //!OCLINT parameter reassignment
return true;
}
}
} else {
// integer
// TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
int theInt = std::atoi(parsedValue.c_str()); // NOLINT
if(theInt != 0) {
res = theInt; //!OCLINT parameter reassignment
return true;
}
}
return false;
}
Expand Down
6 changes: 6 additions & 0 deletions doctest/parts/doctest_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,9 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP

// this is kept here for backwards compatibility since the config option was changed
#ifdef DOCTEST_CONFIG_USE_IOSFWD
#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
#define DOCTEST_CONFIG_USE_STD_HEADERS
#endif
#endif // DOCTEST_CONFIG_USE_IOSFWD

// for clang - always include ciso646 (which drags some std stuff) because
Expand All @@ -462,17 +464,21 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP
#if DOCTEST_CLANG
#include <ciso646>
#ifdef _LIBCPP_VERSION
#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
#define DOCTEST_CONFIG_USE_STD_HEADERS
#endif
#endif // _LIBCPP_VERSION
#endif // clang

#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <cstddef>
#include <ostream>
#include <istream>
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
#else // DOCTEST_CONFIG_USE_STD_HEADERS

// Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
Expand Down
1 change: 1 addition & 0 deletions examples/all_features/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ endfunction()
add_test_all_features(no_multithreading DOCTEST_CONFIG_NO_MULTITHREADING)
add_test_all_features(no_multi_lane_atomics DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS)
add_test_all_features(disabled DOCTEST_CONFIG_DISABLE)
add_test_all_features(std_headers DOCTEST_CONFIG_USE_STD_HEADERS)

# TODO: think about fixing these in a different way! - see issue #61 or commit 6b61e8aa3818c5ea100cedc1bb48a60ea10df6e8
if(MSVC)
Expand Down
36 changes: 24 additions & 12 deletions examples/all_features/enums.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
#include <doctest/doctest.h>

// GCC < 5 breaks when trying to compare enums to integers when using std headers.
#if !defined(DOCTEST_CONFIG_USE_STD_HEADERS) || DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(5, 0, 0)
#define RET_TYPE(x) x
#else
#define RET_TYPE(x) typename doctest::detail::types::underlying_type<x>::type
#endif

template <typename S>
static RET_TYPE(S) castToUnderlying(S in) {
return in;
}

#include "header.h"

DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
Expand Down Expand Up @@ -68,13 +80,13 @@ TEST_CASE("enum 1")
static_assert(std::is_enum<EnumClassSC>::value, "");
ostr << printable(EnumClassSC::Zero) << printable(EnumClassSC::One) << printable(EnumClassSC::Two);

CHECK_EQ(Zero, 0);
CHECK_EQ(One, 1);
CHECK_EQ(Two, 2);
CHECK_EQ(castToUnderlying(Zero), 0);
CHECK_EQ(castToUnderlying(One), 1);
CHECK_EQ(castToUnderlying(Two), 2);

CHECK_EQ(TypedZero, 0);
CHECK_EQ(TypedOne, 1);
CHECK_EQ(TypedTwo, 2);
CHECK_EQ(castToUnderlying(TypedZero), 0);
CHECK_EQ(castToUnderlying(TypedOne), 1);
CHECK_EQ(castToUnderlying(TypedTwo), 2);

CHECK_EQ(EnumClassSC::Zero, EnumClassSC::Zero);
CHECK_EQ(EnumClassSC::One, EnumClassSC::One);
Expand All @@ -83,13 +95,13 @@ TEST_CASE("enum 1")

TEST_CASE("enum 2" * doctest::should_fail())
{
CHECK_EQ(Zero, 1);
CHECK_EQ(One, 2);
CHECK_EQ(Two, 3);
CHECK_EQ(castToUnderlying(Zero), 1);
CHECK_EQ(castToUnderlying(One), 2);
CHECK_EQ(castToUnderlying(Two), 3);

CHECK_EQ(TypedZero, 1);
CHECK_EQ(TypedOne, 2);
CHECK_EQ(TypedTwo, 3);
CHECK_EQ(castToUnderlying(TypedZero), 1);
CHECK_EQ(castToUnderlying(TypedOne), 2);
CHECK_EQ(castToUnderlying(TypedTwo), 3);

CHECK_EQ(EnumClassC::Zero, EnumClassC::One);
CHECK_EQ(EnumClassC::One, EnumClassC::Two);
Expand Down
12 changes: 6 additions & 6 deletions examples/all_features/test_output/enums.cpp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
enums.cpp(0):
TEST CASE: enum 2

enums.cpp(0): ERROR: CHECK_EQ( Zero, 1 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(Zero), 1 ) is NOT correct!
values: CHECK_EQ( 0, 1 )

enums.cpp(0): ERROR: CHECK_EQ( One, 2 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(One), 2 ) is NOT correct!
values: CHECK_EQ( 1, 2 )

enums.cpp(0): ERROR: CHECK_EQ( Two, 3 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(Two), 3 ) is NOT correct!
values: CHECK_EQ( 2, 3 )

enums.cpp(0): ERROR: CHECK_EQ( TypedZero, 1 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(TypedZero), 1 ) is NOT correct!
values: CHECK_EQ( 0, 1 )

enums.cpp(0): ERROR: CHECK_EQ( TypedOne, 2 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(TypedOne), 2 ) is NOT correct!
values: CHECK_EQ( 1, 2 )

enums.cpp(0): ERROR: CHECK_EQ( TypedTwo, 3 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(TypedTwo), 3 ) is NOT correct!
values: CHECK_EQ( 2, 3 )

enums.cpp(0): ERROR: CHECK_EQ( EnumClassC::Zero, EnumClassC::One ) is NOT correct!
Expand Down
12 changes: 6 additions & 6 deletions examples/all_features/test_output/enums.cpp_junit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,37 @@
<testcase classname="enums.cpp" name="enum 2" status="run">
<failure message="0, 1" type="CHECK_EQ">
enums.cpp(0):
CHECK_EQ( Zero, 1 ) is NOT correct!
CHECK_EQ( castToUnderlying(Zero), 1 ) is NOT correct!
values: CHECK_EQ( 0, 1 )

</failure>
<failure message="1, 2" type="CHECK_EQ">
enums.cpp(0):
CHECK_EQ( One, 2 ) is NOT correct!
CHECK_EQ( castToUnderlying(One), 2 ) is NOT correct!
values: CHECK_EQ( 1, 2 )

</failure>
<failure message="2, 3" type="CHECK_EQ">
enums.cpp(0):
CHECK_EQ( Two, 3 ) is NOT correct!
CHECK_EQ( castToUnderlying(Two), 3 ) is NOT correct!
values: CHECK_EQ( 2, 3 )

</failure>
<failure message="0, 1" type="CHECK_EQ">
enums.cpp(0):
CHECK_EQ( TypedZero, 1 ) is NOT correct!
CHECK_EQ( castToUnderlying(TypedZero), 1 ) is NOT correct!
values: CHECK_EQ( 0, 1 )

</failure>
<failure message="1, 2" type="CHECK_EQ">
enums.cpp(0):
CHECK_EQ( TypedOne, 2 ) is NOT correct!
CHECK_EQ( castToUnderlying(TypedOne), 2 ) is NOT correct!
values: CHECK_EQ( 1, 2 )

</failure>
<failure message="2, 3" type="CHECK_EQ">
enums.cpp(0):
CHECK_EQ( TypedTwo, 3 ) is NOT correct!
CHECK_EQ( castToUnderlying(TypedTwo), 3 ) is NOT correct!
values: CHECK_EQ( 2, 3 )

</failure>
Expand Down
12 changes: 6 additions & 6 deletions examples/all_features/test_output/enums.cpp_xml.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,47 @@
<TestCase name="enum 2" filename="enums.cpp" line="0" should_fail="true">
<Expression success="false" type="CHECK_EQ" filename="enums.cpp" line="0">
<Original>
Zero, 1
castToUnderlying(Zero), 1
</Original>
<Expanded>
0, 1
</Expanded>
</Expression>
<Expression success="false" type="CHECK_EQ" filename="enums.cpp" line="0">
<Original>
One, 2
castToUnderlying(One), 2
</Original>
<Expanded>
1, 2
</Expanded>
</Expression>
<Expression success="false" type="CHECK_EQ" filename="enums.cpp" line="0">
<Original>
Two, 3
castToUnderlying(Two), 3
</Original>
<Expanded>
2, 3
</Expanded>
</Expression>
<Expression success="false" type="CHECK_EQ" filename="enums.cpp" line="0">
<Original>
TypedZero, 1
castToUnderlying(TypedZero), 1
</Original>
<Expanded>
0, 1
</Expanded>
</Expression>
<Expression success="false" type="CHECK_EQ" filename="enums.cpp" line="0">
<Original>
TypedOne, 2
castToUnderlying(TypedOne), 2
</Original>
<Expanded>
1, 2
</Expanded>
</Expression>
<Expression success="false" type="CHECK_EQ" filename="enums.cpp" line="0">
<Original>
TypedTwo, 3
castToUnderlying(TypedTwo), 3
</Original>
<Expanded>
2, 3
Expand Down
12 changes: 6 additions & 6 deletions examples/all_features/test_output/no_multi_lane_atomics.txt
Original file line number Diff line number Diff line change
Expand Up @@ -318,22 +318,22 @@ Should have failed but didn't! Marking it as failed!
enums.cpp(0):
TEST CASE: enum 2

enums.cpp(0): ERROR: CHECK_EQ( Zero, 1 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(Zero), 1 ) is NOT correct!
values: CHECK_EQ( 0, 1 )

enums.cpp(0): ERROR: CHECK_EQ( One, 2 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(One), 2 ) is NOT correct!
values: CHECK_EQ( 1, 2 )

enums.cpp(0): ERROR: CHECK_EQ( Two, 3 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(Two), 3 ) is NOT correct!
values: CHECK_EQ( 2, 3 )

enums.cpp(0): ERROR: CHECK_EQ( TypedZero, 1 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(TypedZero), 1 ) is NOT correct!
values: CHECK_EQ( 0, 1 )

enums.cpp(0): ERROR: CHECK_EQ( TypedOne, 2 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(TypedOne), 2 ) is NOT correct!
values: CHECK_EQ( 1, 2 )

enums.cpp(0): ERROR: CHECK_EQ( TypedTwo, 3 ) is NOT correct!
enums.cpp(0): ERROR: CHECK_EQ( castToUnderlying(TypedTwo), 3 ) is NOT correct!
values: CHECK_EQ( 2, 3 )

enums.cpp(0): ERROR: CHECK_EQ( EnumClassC::Zero, EnumClassC::One ) is NOT correct!
Expand Down
Loading

0 comments on commit 94b52bb

Please sign in to comment.