- tiny code rework - getting ready for lazy stringification + removing -Winline stuff for gcc 4.7
- updated roadmap
diff --git a/doc/markdown/roadmap.md b/doc/markdown/roadmap.md
index 2f194d2..3a2a97f 100644
--- a/doc/markdown/roadmap.md
+++ b/doc/markdown/roadmap.md
@@ -10,10 +10,21 @@
### For 1.2:
-- adding contextual info to asserts (logging) - with an ```INFO```/```CONTEXT``` /```TRACEPOINT``` macro (also look at [this](https://github.com/philsquared/Catch/issues/601))
+- adding contextual info to asserts (logging) - with an ```INFO```/```CONTEXT```/```CAPTURE```/```TRACEPOINT``` macro (also look at [this](https://github.com/philsquared/Catch/issues/601))
- add ```ERROR```/```FAIL``` macros (also ```ADD_FAILURE_AT(file, line);``` and extend the asserts to have ```_AT``` variants)
- Parametric test cases (Value/Type-parameterized tests) - https://github.com/onqtam/doctest/issues/38
- crash handling: signals on UNIX platforms or structured exceptions on Windows (should also have DOCTEST_CONFIG_NO_SIGNAL_CATCHING)
+- add a "wait key" option - as requested [here](https://github.com/philsquared/Catch/issues/477#issuecomment-256417686)
+- runtime performance
+ - the set holding all registered tests should use a specialized allocator to minimize program startup time
+ - lazily stringify expressions - only when needed
+ - pool allocator for the ```String``` class - currently very unoptimized
+ - get rid of local statics on the hot path - like in getContextState()
+- benchmarking
+ - make the bench.py script more usable - with command line arguments
+ - redo the compile time ones - also look into CATCH_CONFIG_FAST_COMPILE
+ - remove old benchmarks for doctest 1.0
+ - add runtime benchmarks
- change docs a bit - mainly what is in the landing page (add link to overload)
### For 1.3:
@@ -28,6 +39,7 @@
- an xml reporter
- jUnit/xUnit reporters
- a listener interface - similar to a reporter - look at Catch
+- ability to have no output when everything succeeds
- time stuff
- reporting running time of tests
- count a test case as failed if it exceeds X ms (but no force-killing!)
@@ -37,39 +49,29 @@
- generators? - look at Catch - and investigate what they are (also in [boost](http://www.boost.org/doc/libs/1_61_0/libs/test/doc/html/boost_test/tests_organization/test_cases/test_case_generation.html))
- mocking - investigate google mock assertion macros and interop with doctest (also [mockitopp](https://github.com/tpounds/mockitopp) and [trompeloeil](https://github.com/rollbear/trompeloeil)) - and write in FAQ - lest integrates with trompeloeil like [this](https://github.com/martinmoene/lest/commit/d347460642c80b227a5930bd92420726a9f085b3)
- look at property based testing (for example [rapidcheck](https://github.com/emil-e/rapidcheck)) - and write in FAQ
-- implement breaking into the debugger under linux - see [here](https://github.com/philsquared/Catch/pull/585) and [here](https://github.com/scottt/debugbreak)
### For 1.4:
- running tests a [few times](https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#repeating-the-tests)
-- runtime performance
- - the set holding all registered tests should use a specialized allocator to minimize program startup time
- - lazily stringify expressions - only when needed
- - pool allocator for the ```String``` class - currently very unoptimized
- - get rid of local statics on the hot path - like in getContextState() - they have synchronisation in C++11
-- benchmarking
- - make the bench.py script more usable - with command line arguments
- - redo the compile time ones - also look into CATCH_CONFIG_FAST_COMPILE
- - remove old benchmarks for doctest 1.0
- - add runtime benchmarks
- test execution in [separate processes](https://github.com/philsquared/Catch/issues/853) - ```fork()``` for UNIX and [this](https://github.com/nemequ/munit/issues/2) for Windows
- [symbolizer](https://github.com/facebook/folly/tree/master/folly/experimental/symbolizer) - for a stack trace - when an assertion fails - and it's in a user function with some deep callstack away from the current test case - how to know the exact code path that lead to the failing assert
+- ability to make the framework not capture unexpected exceptions - as requested [here](https://github.com/onqtam/doctest/issues/12#issuecomment-235334585)
+- add Approx ability to compare with absolute epsilon - [Catch PR](https://github.com/philsquared/Catch/pull/538)
+- ability to customize the colors in the console output (may also use styles - based on [this](https://github.com/agauniyal/rang))
+- implement breaking into the debugger under linux - see [here](https://github.com/philsquared/Catch/pull/585) and [here](https://github.com/scottt/debugbreak)
### Things that are being considered but not part of the roadmap yet:
+- when no assertion is encountered in a test case it should fail
- failure reporting should print out previous SECTIONs for data-driven testing - as requested [here](https://github.com/philsquared/Catch/issues/734)
- ```Bitwise()``` class that has overloaded operators for comparison - to be used to check objects bitwise against each other
- detect floating point exceptions
-- ability to customize the colors in the console output (may also use styles - based on [this](https://github.com/agauniyal/rang))
- option to output summary only
- support for tags
- may fail tag
- invisible tag
- look at Catch - https://github.com/philsquared/Catch/blob/master/docs/test-cases-and-sections.md#special-tags
- marking a test to run X times (should also multiply with the global test run times)
-- add a "wait key" option - as requested [here](https://github.com/philsquared/Catch/issues/477#issuecomment-256417686)
-- add Approx ability to compare with absolute epsilon - [Catch PR](https://github.com/philsquared/Catch/pull/538)
-- ability to have no output when everything succeeds
- integrate static analysis on the CI: **msvc**, **clang**, **cppcheck**
- extend Approx for types that have operator double - see [here](https://github.com/philsquared/Catch/issues/652) and [here](https://github.com/philsquared/Catch/pull/658)
- option to list files in which there are test cases who match the current filters
@@ -85,7 +87,6 @@
- https://msdn.microsoft.com/en-us/library/hh598953.aspx
- also look into similar Xcode integration - https://github.com/philsquared/Catch/pull/454
- ability to provide a temp folder that is cleared between each test case
-- ability to make the framework not capture unexpected exceptions - as requested [here](https://github.com/onqtam/doctest/issues/12#issuecomment-235334585)
- rework the examples folder - so the test runner is compiled only a few times - CI builds take a ton of time!
### Things that are very unlikely to enter the roadmap:
@@ -93,8 +94,8 @@
- test with missed warning flags for GCC - look into https://github.com/Barro/compiler-warnings
- utf8???
- handle ```wchar``` strings???
-- print a warning when no assertion is encountered in a test case
-- hierarchical test suites - using a stack for the pushed ones - should be easy
+- hierarchical test suites - using a stack for the pushed ones
+- ability to specify the width of the terminal in terms of characters (for example 60 - less than 80 - the default)
- ability to re-run only newly compiled tests based on time stamps using ```__DATE__``` and ```__TIME__``` - stored in some file
- add underscores to all preprocessor identifiers not intended for use by the user
- put everything from the ```detail``` namespace also in a nested anonymous namespace to make them with internal linkage
diff --git a/doctest/doctest.h b/doctest/doctest.h
index 82f96d4..a24d179 100644
--- a/doctest/doctest.h
+++ b/doctest/doctest.h
@@ -799,12 +799,7 @@
bool m_passed;
String m_decomposition;
-// to fix gcc 4.7 "-Winline" warnings
-#if defined(__GNUC__) && !defined(__clang__)
- __attribute__((noinline))
-#endif
- ~Result() {
- }
+ ~Result();
Result(bool passed = false, const String& decomposition = String())
: m_passed(passed)
@@ -814,17 +809,7 @@
: m_passed(other.m_passed)
, m_decomposition(other.m_decomposition) {}
-// to fix gcc 4.7 "-Winline" warnings
-#if defined(__GNUC__) && !defined(__clang__)
- __attribute__((noinline))
-#endif
- Result&
- operator=(const Result& other) {
- m_passed = other.m_passed;
- m_decomposition = other.m_decomposition;
-
- return *this;
- }
+ Result& operator=(const Result& other);
operator bool() { return !m_passed; }
@@ -1022,8 +1007,8 @@
struct TestAccessibleContextState
{
- bool no_throw; // to skip exceptions-related assertion macros
- bool no_breaks; // to not break into the debugger
+ bool success; // include successful assertions in output
+ bool no_throw; // to skip exceptions-related assertion macros
};
struct ContextState;
@@ -1070,25 +1055,26 @@
ResultBuilder(assertType::Enum assert_type, const char* file, int line, const char* expr,
const char* exception_type = "");
-// to fix gcc 4.7 "-Winline" warnings
-#if defined(__GNUC__) && !defined(__clang__)
- __attribute__((noinline))
-#endif
- ~ResultBuilder() {
- }
+ ~ResultBuilder();
- void setResult(const Result& res) { m_result = res; }
+ void setResult(const Result& res);
template <int comparison, typename L, typename R>
void binary_assert(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) {
m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
+
+ if(m_assert_type & assertType::is_false)
+ m_result.invert();
}
template <typename L>
void unary_assert(const DOCTEST_REF_WRAP(L) val) {
m_result.m_passed = !!val;
m_result.m_decomposition = toString(val);
+
+ if(m_assert_type & assertType::is_false)
+ m_result.invert();
}
void unexpectedExceptionOccurred();
@@ -1113,7 +1099,11 @@
const DOCTEST_REF_WRAP(R) rhs) {
ResultBuilder rb(assert_type, file, line, expr);
- rb.m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
+ rb.m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
+
+ if(assert_type & assertType::is_false)
+ rb.m_result.invert();
+
rb.m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
int res = 0;
@@ -1142,7 +1132,11 @@
const char* val_str, const DOCTEST_REF_WRAP(L) val) {
ResultBuilder rb(assert_type, file, line, val_str);
- rb.m_result.m_passed = !!val;
+ rb.m_result.m_passed = !!val;
+
+ if(assert_type & assertType::is_false)
+ rb.m_result.invert();
+
rb.m_result.m_decomposition = toString(val);
int res = 0;
@@ -1244,10 +1238,6 @@
public:
Context(int argc = 0, const char* const* argv = 0);
-// to fix gcc 4.7 "-Winline" warnings
-#if defined(__GNUC__) && !defined(__clang__)
- __attribute__((noinline))
-#endif
~Context();
void applyCommandLine(int argc, const char* const* argv);
@@ -2252,7 +2242,6 @@
int abort_after; // stop tests after this many failed assertions
int subcase_filter_levels; // apply the subcase filters for the first N levels
- bool success; // include successful assertions in output
bool case_sensitive; // if filtering should be case sensitive
bool exit; // if the program should be exited after the tests are ran/whatever
bool no_exitcode; // if the framework should return 0 as the exitcode
@@ -2260,6 +2249,7 @@
bool no_version; // to not print the version of the framework
bool no_colors; // if output to the console should be colorized
bool force_colors; // forces the use of colors even when a tty cannot be detected
+ bool no_breaks; // to not break into the debugger
bool no_path_in_filenames; // if the path to files should be removed from the output
bool no_line_numbers; // if source code line numbers should be omitted from the output
@@ -2778,6 +2768,15 @@
}
}
+ Result::~Result() {}
+
+ Result& Result::operator=(const Result& other) {
+ m_passed = other.m_passed;
+ m_decomposition = other.m_decomposition;
+
+ return *this;
+ }
+
// for sorting tests by file/line
int fileOrderComparator(const void* a, const void* b) {
const TestData* lhs = *static_cast<TestData* const*>(a);
@@ -3270,6 +3269,14 @@
++m_expr;
}
+ ResultBuilder::~ResultBuilder() {}
+
+ void ResultBuilder::setResult(const Result& res) {
+ m_result = res;
+ if(m_assert_type & assertType::is_false)
+ m_result.invert();
+ }
+
void ResultBuilder::unexpectedExceptionOccurred() {
m_threw = true;
@@ -3280,10 +3287,7 @@
if((m_assert_type & assertType::is_warn) == 0)
DOCTEST_GCS().numAssertionsForCurrentTestcase++;
- if(m_assert_type & assertType::is_false) {
- m_result.invert();
- m_failed = m_result;
- } else if(m_assert_type & assertType::is_throws) {
+ if(m_assert_type & assertType::is_throws) {
m_failed = !m_threw;
} else if(m_assert_type & assertType::is_throws_as) {
m_failed = !m_threw_as;
diff --git a/doctest/parts/doctest_fwd.h b/doctest/parts/doctest_fwd.h
index accccc1..ffb82b4 100644
--- a/doctest/parts/doctest_fwd.h
+++ b/doctest/parts/doctest_fwd.h
@@ -796,12 +796,7 @@
bool m_passed;
String m_decomposition;
-// to fix gcc 4.7 "-Winline" warnings
-#if defined(__GNUC__) && !defined(__clang__)
- __attribute__((noinline))
-#endif
- ~Result() {
- }
+ ~Result();
Result(bool passed = false, const String& decomposition = String())
: m_passed(passed)
@@ -811,17 +806,7 @@
: m_passed(other.m_passed)
, m_decomposition(other.m_decomposition) {}
-// to fix gcc 4.7 "-Winline" warnings
-#if defined(__GNUC__) && !defined(__clang__)
- __attribute__((noinline))
-#endif
- Result&
- operator=(const Result& other) {
- m_passed = other.m_passed;
- m_decomposition = other.m_decomposition;
-
- return *this;
- }
+ Result& operator=(const Result& other);
operator bool() { return !m_passed; }
@@ -1019,8 +1004,8 @@
struct TestAccessibleContextState
{
- bool no_throw; // to skip exceptions-related assertion macros
- bool no_breaks; // to not break into the debugger
+ bool success; // include successful assertions in output
+ bool no_throw; // to skip exceptions-related assertion macros
};
struct ContextState;
@@ -1067,25 +1052,26 @@
ResultBuilder(assertType::Enum assert_type, const char* file, int line, const char* expr,
const char* exception_type = "");
-// to fix gcc 4.7 "-Winline" warnings
-#if defined(__GNUC__) && !defined(__clang__)
- __attribute__((noinline))
-#endif
- ~ResultBuilder() {
- }
+ ~ResultBuilder();
- void setResult(const Result& res) { m_result = res; }
+ void setResult(const Result& res);
template <int comparison, typename L, typename R>
void binary_assert(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) {
m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
+
+ if(m_assert_type & assertType::is_false)
+ m_result.invert();
}
template <typename L>
void unary_assert(const DOCTEST_REF_WRAP(L) val) {
m_result.m_passed = !!val;
m_result.m_decomposition = toString(val);
+
+ if(m_assert_type & assertType::is_false)
+ m_result.invert();
}
void unexpectedExceptionOccurred();
@@ -1110,7 +1096,11 @@
const DOCTEST_REF_WRAP(R) rhs) {
ResultBuilder rb(assert_type, file, line, expr);
- rb.m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
+ rb.m_result.m_passed = RelationalComparator<comparison, L, R>()(lhs, rhs);
+
+ if(assert_type & assertType::is_false)
+ rb.m_result.invert();
+
rb.m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs);
int res = 0;
@@ -1139,7 +1129,11 @@
const char* val_str, const DOCTEST_REF_WRAP(L) val) {
ResultBuilder rb(assert_type, file, line, val_str);
- rb.m_result.m_passed = !!val;
+ rb.m_result.m_passed = !!val;
+
+ if(assert_type & assertType::is_false)
+ rb.m_result.invert();
+
rb.m_result.m_decomposition = toString(val);
int res = 0;
@@ -1241,10 +1235,6 @@
public:
Context(int argc = 0, const char* const* argv = 0);
-// to fix gcc 4.7 "-Winline" warnings
-#if defined(__GNUC__) && !defined(__clang__)
- __attribute__((noinline))
-#endif
~Context();
void applyCommandLine(int argc, const char* const* argv);
diff --git a/doctest/parts/doctest_impl.h b/doctest/parts/doctest_impl.h
index dfbfec1..976d388 100644
--- a/doctest/parts/doctest_impl.h
+++ b/doctest/parts/doctest_impl.h
@@ -228,7 +228,6 @@
int abort_after; // stop tests after this many failed assertions
int subcase_filter_levels; // apply the subcase filters for the first N levels
- bool success; // include successful assertions in output
bool case_sensitive; // if filtering should be case sensitive
bool exit; // if the program should be exited after the tests are ran/whatever
bool no_exitcode; // if the framework should return 0 as the exitcode
@@ -236,6 +235,7 @@
bool no_version; // to not print the version of the framework
bool no_colors; // if output to the console should be colorized
bool force_colors; // forces the use of colors even when a tty cannot be detected
+ bool no_breaks; // to not break into the debugger
bool no_path_in_filenames; // if the path to files should be removed from the output
bool no_line_numbers; // if source code line numbers should be omitted from the output
@@ -754,6 +754,15 @@
}
}
+ Result::~Result() {}
+
+ Result& Result::operator=(const Result& other) {
+ m_passed = other.m_passed;
+ m_decomposition = other.m_decomposition;
+
+ return *this;
+ }
+
// for sorting tests by file/line
int fileOrderComparator(const void* a, const void* b) {
const TestData* lhs = *static_cast<TestData* const*>(a);
@@ -1246,6 +1255,14 @@
++m_expr;
}
+ ResultBuilder::~ResultBuilder() {}
+
+ void ResultBuilder::setResult(const Result& res) {
+ m_result = res;
+ if(m_assert_type & assertType::is_false)
+ m_result.invert();
+ }
+
void ResultBuilder::unexpectedExceptionOccurred() {
m_threw = true;
@@ -1256,10 +1273,7 @@
if((m_assert_type & assertType::is_warn) == 0)
DOCTEST_GCS().numAssertionsForCurrentTestcase++;
- if(m_assert_type & assertType::is_false) {
- m_result.invert();
- m_failed = m_result;
- } else if(m_assert_type & assertType::is_throws) {
+ if(m_assert_type & assertType::is_throws) {
m_failed = !m_threw;
} else if(m_assert_type & assertType::is_throws_as) {
m_failed = !m_threw_as;